Skip to content

Commit

Permalink
Merge pull request #329 from jacebrowning/cache-default-factory
Browse files Browse the repository at this point in the history
Add caching to default factory calls
  • Loading branch information
jacebrowning committed May 26, 2024
2 parents 8b6be2a + cb2ee4c commit 59566a6
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .verchew.ini
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ version = 1

cli = dot
cli_version_arg = -V
version = 7 || 8 || 9 || 10
version = graphviz
optional = true
message = This is only needed to generate UML diagrams for documentation.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release Notes

## 2.2.3 (2024-05-26)

- Added caching to default factory calls.

## 2.2.2 (2024-01-06)

- Fixed `Manager.all()` behavior for patterns with default vales.
Expand Down
8 changes: 7 additions & 1 deletion datafiles/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import dataclasses
import time
from contextlib import suppress
from dataclasses import Field
from functools import lru_cache
from pathlib import Path
from pprint import pformat
Expand Down Expand Up @@ -30,14 +31,19 @@ def get_default_field_value(instance, name):
return field.default

if not isinstance(field.default_factory, Missing): # type: ignore
return field.default_factory() # type: ignore
return _call_default_factory(field)

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

return Missing


@cached
def _call_default_factory(field: Field):
return field.default_factory() # type: ignore


def prettify(value) -> str:
"""Ensure value is a dictionary pretty-format it."""
return pformat(dictify(value))
Expand Down
1 change: 1 addition & 0 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tool.poetry]

name = "datafiles"
version = "2.2.2"
version = "2.2.3"
description = "File-based ORM for dataclasses."

license = "MIT"
Expand Down
23 changes: 23 additions & 0 deletions tests/test_instantiation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

from . import xfail_with_pep_563

counter = 0


@datafile("../tmp/sample.yml", manual=True)
class SampleWithDefaults:
Expand Down Expand Up @@ -150,6 +152,27 @@ def when_file_exists(expect):
expect(sample.b) == 3.4
expect(sample.c) == 9.9

def it_only_calls_factory_when_needed(expect):
global counter
counter = 0

def default_factory():
global counter
counter += 1
logbreak(f"Called default factory: {counter}")
return "a"

@datafile("../tmp/sample.yml")
class Sample:
value: str = field(default_factory=default_factory)

sample = Sample()

sample.value = "b"
sample.value = "c"

expect(counter) == 2


def describe_missing_attributes():
@xfail_with_pep_563
Expand Down
2 changes: 1 addition & 1 deletion tests/test_saving.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def without_initial_values(sample, expect):
"""
)

def with_convertable_initial_values(expect):
def with_convertible_initial_values(expect):
sample = Sample(1, 2, 3, 4)

sample.datafile.save()
Expand Down

0 comments on commit 59566a6

Please sign in to comment.