Skip to content

Commit fa3be8e

Browse files
committed
feat(fixtures): Cached genesis model dump
1 parent 164de2d commit fa3be8e

File tree

1 file changed

+88
-1
lines changed

1 file changed

+88
-1
lines changed

packages/testing/src/execution_testing/fixtures/pre_alloc_groups.py

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
"""Pre-allocation group models for test fixture generation."""
22

33
import json
4+
from dataclasses import dataclass
45
from pathlib import Path
5-
from typing import Any, Dict, Generator, Iterator, KeysView, List, Self, Tuple
6+
from typing import (
7+
Any,
8+
Dict,
9+
Generator,
10+
Iterator,
11+
KeysView,
12+
List,
13+
Literal,
14+
Self,
15+
Tuple,
16+
)
617

718
from filelock import FileLock
819
from pydantic import Field, PrivateAttr
@@ -155,13 +166,89 @@ def add_test_pre(
155166
self.root[pre_alloc_hash] = group
156167

157168

169+
@dataclass(kw_only=True)
170+
class ModelDumpCache:
171+
"""
172+
Holds a cached dump of a model, the type of the cache (str or json)
173+
and the keyword arguments used to generate it.
174+
"""
175+
176+
model_dump_config: Dict[str, Any]
177+
"""Keyword arguments used to model dump the data."""
178+
model_dump_mode: Literal["json", "python"]
179+
"""Mode of the model dump when `model_dump` is called."""
180+
model_dump_type: Literal["string", "dict"]
181+
"""Whether `model_dump_json` or `model_dump` was used to generate the data."""
182+
data: Any
183+
184+
158185
class GroupPreAlloc(Alloc):
186+
"""
187+
Alloc that belongs to a pre-allocation group.
188+
189+
This is used to avoid re-calculating the state root for the pre-allocation
190+
group when it is accessed.
191+
192+
Also holds a cached model dump of the pre-allocation group, either in
193+
string or JSON format depending on the last request.
194+
"""
195+
159196
_pre_alloc_group: "PreAllocGroup" = PrivateAttr(init=False)
197+
_model_dump_cache: ModelDumpCache | None = PrivateAttr(None)
198+
_cache_miss_count: int = PrivateAttr(0)
160199

161200
def state_root(self) -> Hash:
162201
"""On pre-alloc groups, which are normally very big, we always cache."""
163202
return self._pre_alloc_group.genesis.state_root
164203

204+
def model_dump( # type: ignore[override]
205+
self, mode: Literal["json", "python"], **kwargs: Any
206+
) -> Any:
207+
"""
208+
Model dump the pre-allocation group, with caching.
209+
210+
Note: 'mode' here follows Pydantic's semantics:
211+
- 'python' -> standard model_dump
212+
- 'json' -> JSON-compatible python data
213+
"""
214+
if (
215+
self._model_dump_cache is not None
216+
and self._model_dump_cache.model_dump_mode == mode
217+
and self._model_dump_cache.model_dump_type == "dict"
218+
and self._model_dump_cache.model_dump_config == kwargs
219+
):
220+
return self._model_dump_cache.data
221+
222+
self._cache_miss_count += 1
223+
data = super().model_dump(mode=mode, **kwargs)
224+
self._model_dump_cache = ModelDumpCache(
225+
model_dump_mode=mode,
226+
model_dump_config=kwargs,
227+
model_dump_type="dict",
228+
data=data,
229+
)
230+
return data
231+
232+
def model_dump_json(self, **kwargs: Any) -> str:
233+
"""Model dump the pre-allocation group in JSON string format, with caching."""
234+
if (
235+
self._model_dump_cache is not None
236+
and self._model_dump_cache.model_dump_mode == "json"
237+
and self._model_dump_cache.model_dump_type == "string"
238+
and self._model_dump_cache.model_dump_config == kwargs
239+
):
240+
return self._model_dump_cache.data
241+
242+
self._cache_miss_count += 1
243+
data = super().model_dump_json(**kwargs)
244+
self._model_dump_cache = ModelDumpCache(
245+
model_dump_mode="json",
246+
model_dump_config=kwargs,
247+
model_dump_type="string",
248+
data=data,
249+
)
250+
return data
251+
165252

166253
class PreAllocGroup(PreAllocGroupBuilder):
167254
"""

0 commit comments

Comments
 (0)