Skip to content

Commit 59566a6

Browse files
authored
Merge pull request #329 from jacebrowning/cache-default-factory
Add caching to default factory calls
2 parents 8b6be2a + cb2ee4c commit 59566a6

File tree

7 files changed

+38
-4
lines changed

7 files changed

+38
-4
lines changed

.verchew.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ version = 1
1717

1818
cli = dot
1919
cli_version_arg = -V
20-
version = 7 || 8 || 9 || 10
20+
version = graphviz
2121
optional = true
2222
message = This is only needed to generate UML diagrams for documentation.

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Release Notes
22

3+
## 2.2.3 (2024-05-26)
4+
5+
- Added caching to default factory calls.
6+
37
## 2.2.2 (2024-01-06)
48

59
- Fixed `Manager.all()` behavior for patterns with default vales.

datafiles/utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import dataclasses
44
import time
55
from contextlib import suppress
6+
from dataclasses import Field
67
from functools import lru_cache
78
from pathlib import Path
89
from pprint import pformat
@@ -30,14 +31,19 @@ def get_default_field_value(instance, name):
3031
return field.default
3132

3233
if not isinstance(field.default_factory, Missing): # type: ignore
33-
return field.default_factory() # type: ignore
34+
return _call_default_factory(field)
3435

3536
if not field.init and hasattr(instance, "__post_init__"):
3637
return getattr(instance, name)
3738

3839
return Missing
3940

4041

42+
@cached
43+
def _call_default_factory(field: Field):
44+
return field.default_factory() # type: ignore
45+
46+
4147
def prettify(value) -> str:
4248
"""Ensure value is a dictionary pretty-format it."""
4349
return pformat(dictify(value))

poetry.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tool.poetry]
22

33
name = "datafiles"
4-
version = "2.2.2"
4+
version = "2.2.3"
55
description = "File-based ORM for dataclasses."
66

77
license = "MIT"

tests/test_instantiation.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
from . import xfail_with_pep_563
1212

13+
counter = 0
14+
1315

1416
@datafile("../tmp/sample.yml", manual=True)
1517
class SampleWithDefaults:
@@ -150,6 +152,27 @@ def when_file_exists(expect):
150152
expect(sample.b) == 3.4
151153
expect(sample.c) == 9.9
152154

155+
def it_only_calls_factory_when_needed(expect):
156+
global counter
157+
counter = 0
158+
159+
def default_factory():
160+
global counter
161+
counter += 1
162+
logbreak(f"Called default factory: {counter}")
163+
return "a"
164+
165+
@datafile("../tmp/sample.yml")
166+
class Sample:
167+
value: str = field(default_factory=default_factory)
168+
169+
sample = Sample()
170+
171+
sample.value = "b"
172+
sample.value = "c"
173+
174+
expect(counter) == 2
175+
153176

154177
def describe_missing_attributes():
155178
@xfail_with_pep_563

tests/test_saving.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def without_initial_values(sample, expect):
4646
"""
4747
)
4848

49-
def with_convertable_initial_values(expect):
49+
def with_convertible_initial_values(expect):
5050
sample = Sample(1, 2, 3, 4)
5151

5252
sample.datafile.save()

0 commit comments

Comments
 (0)