Skip to content

Commit

Permalink
Make Configuration.load() an instance method (#1512)
Browse files Browse the repository at this point in the history
  • Loading branch information
bartfeenstra authored Jun 26, 2024
1 parent bc15a29 commit f089858
Show file tree
Hide file tree
Showing 23 changed files with 637 additions and 539 deletions.
14 changes: 2 additions & 12 deletions betty/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,20 +151,10 @@ def update(self, other: Self) -> None:
self._dispatch_change()

@override
@classmethod
def load(
cls,
dump: Dump,
configuration: Self | None = None,
) -> Self:
if configuration is None:
configuration = cls()
def load(self, dump: Dump) -> None:
assert_record(
OptionalField(
"locale", assert_str() | assert_setattr(configuration, "locale")
)
OptionalField("locale", assert_str() | assert_setattr(self, "locale"))
)(dump)
return configuration

@override
def dump(self) -> VoidableDump:
Expand Down
5 changes: 1 addition & 4 deletions betty/assets/betty.pot
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Betty VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-06-21 17:59+0100\n"
"POT-Creation-Date: 2024-06-26 13:52+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -222,9 +222,6 @@ msgstr ""
msgid "Cannot load coordinates \"{coordinates}\", because they are in an unknown format."
msgstr ""

msgid "Cannot remove the last remaining locale {locale}"
msgstr ""

msgid "Celebrant"
msgstr ""

Expand Down
5 changes: 1 addition & 4 deletions betty/assets/locale/de-DE/betty.po
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Betty VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-06-21 17:59+0100\n"
"POT-Creation-Date: 2024-06-26 13:52+0100\n"
"PO-Revision-Date: 2024-02-08 13:24+0000\n"
"Last-Translator: Bart Feenstra <bart@bartfeenstra.com>\n"
"Language: de\n"
Expand Down Expand Up @@ -336,9 +336,6 @@ msgstr ""
"Die Koordinaten \"{coordinates}\" können nicht geladen werden, da sie in "
"einem unbekannten Format vorliegen."

msgid "Cannot remove the last remaining locale {locale}"
msgstr "Kann das letzte verbleibende Gebietsschema {locale} nicht entfernen"

msgid "Celebrant"
msgstr "Zelebrant"

Expand Down
5 changes: 1 addition & 4 deletions betty/assets/locale/fr-FR/betty.po
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-06-21 17:59+0100\n"
"POT-Creation-Date: 2024-06-26 13:52+0100\n"
"PO-Revision-Date: 2024-02-08 13:24+0000\n"
"Last-Translator: Bart Feenstra <bart@bartfeenstra.com>\n"
"Language: fr\n"
Expand Down Expand Up @@ -276,9 +276,6 @@ msgid ""
" format."
msgstr ""

msgid "Cannot remove the last remaining locale {locale}"
msgstr ""

msgid "Celebrant"
msgstr ""

Expand Down
5 changes: 1 addition & 4 deletions betty/assets/locale/nl-NL/betty.po
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-06-21 17:59+0100\n"
"POT-Creation-Date: 2024-06-26 13:52+0100\n"
"PO-Revision-Date: 2024-02-11 15:31+0000\n"
"Last-Translator: Bart Feenstra <bart@bartfeenstra.com>\n"
"Language: nl\n"
Expand Down Expand Up @@ -329,9 +329,6 @@ msgstr ""
"Can de coördinaten \"{coordinates}\" niet laden, omdat ze in een onbekend"
" formaat geschreven zijn."

msgid "Cannot remove the last remaining locale {locale}"
msgstr "Kan de laatst overgebleven taalregio {locale} niet verwijderen"

msgid "Celebrant"
msgstr "Ambtenaar"

Expand Down
5 changes: 1 addition & 4 deletions betty/assets/locale/uk/betty.po
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Betty VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-06-21 17:59+0100\n"
"POT-Creation-Date: 2024-06-26 13:52+0100\n"
"PO-Revision-Date: 2024-02-08 13:08+0000\n"
"Last-Translator: Rainer Thieringer <rainerthi@gmail.com>\n"
"Language: uk\n"
Expand Down Expand Up @@ -276,9 +276,6 @@ msgid ""
" format."
msgstr ""

msgid "Cannot remove the last remaining locale {locale}"
msgstr ""

msgid "Celebrant"
msgstr ""

Expand Down
136 changes: 59 additions & 77 deletions betty/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import weakref
from collections import OrderedDict
from collections.abc import Callable
from contextlib import suppress, chdir
from contextlib import chdir
from pathlib import Path
from reprlib import recursive_repr
from tempfile import TemporaryDirectory
Expand Down Expand Up @@ -41,7 +41,7 @@
from betty.serde.dump import Dumpable, Dump, minimize, VoidableDump, Void
from betty.serde.error import SerdeErrorCollection
from betty.serde.format import FormatRepository
from betty.serde.load import Assertion, assert_dict, assert_mapping, assert_sequence
from betty.serde.load import assert_dict, assert_sequence

if TYPE_CHECKING:
from _weakref import ReferenceType
Expand Down Expand Up @@ -96,32 +96,11 @@ def update(self, other: Self) -> None:
"""
raise NotImplementedError(repr(self))

@classmethod
def load(
cls,
dump: Dump,
configuration: Self | None = None,
) -> Self:
def load(self, dump: Dump) -> None:
"""
Load dumped configuration into a new configuration instance.
Load dumped configuration.
"""
raise NotImplementedError(repr(cls))

@classmethod
def assert_load(
cls: type[_ConfigurationT], configuration: _ConfigurationT | None = None
) -> Assertion[Dump, _ConfigurationT]:
"""
Assert that the dumped configuration can be loaded.
"""

def _assert_load(dump: Dump) -> _ConfigurationT:
return cls.load(dump, configuration)

_assert_load.__qualname__ = (
f"{_assert_load.__qualname__} for {cls.__module__}.{cls.__qualname__}.load"
)
return _assert_load
raise NotImplementedError(repr(self))


_ConfigurationT = TypeVar("_ConfigurationT", bound=Configuration)
Expand Down Expand Up @@ -213,13 +192,11 @@ async def read(self, configuration_file_path: Path | None = None) -> None:
configuration_file_path=str(self.configuration_file_path.resolve()),
)
):
loaded_configuration = self.load(
self.load(
formats.format_for(self.configuration_file_path.suffix[1:]).load(
read_configuration
),
self,
)
)
self.update(loaded_configuration)

def __del__(self) -> None:
if (
Expand Down Expand Up @@ -300,26 +277,22 @@ def __delitem__(self, configuration_key: _ConfigurationKeyT) -> None:
def __len__(self) -> int:
return len(self._configurations)

@override
def __eq__(self, other: Any) -> bool:
if not isinstance(other, self.__class__):
return NotImplemented
if list(self.keys()) != list(other.keys()):
return False
if list(self.values()) != list(other.values()):
return False
return True

@override # type: ignore[callable-functiontype]
@recursive_repr()
def __repr__(self) -> str:
return repr_instance(self, configurations=list(self.values()))

def _remove_without_dispatch(self, *configuration_keys: _ConfigurationKeyT) -> None:
for configuration_key in configuration_keys:
with suppress(LookupError):
self._on_remove(self._configurations[configuration_key]) # type: ignore[call-overload]
configuration = self._configurations[configuration_key] # type: ignore[call-overload]
del self._configurations[configuration_key] # type: ignore[call-overload]
self._on_remove(configuration)

def replace(self, *values: _ConfigurationT) -> None:
"""
Replace any existing values with the given ones.
"""
raise NotImplementedError(repr(self))

def remove(self, *configuration_keys: _ConfigurationKeyT) -> None:
"""
Expand Down Expand Up @@ -377,9 +350,13 @@ def to_keys(self, *indices: int | slice) -> Iterator[_ConfigurationKeyT]:
for index in sorted(unique_indices):
yield self.to_key(index)

@classmethod
def _item_type(cls) -> type[_ConfigurationT]:
raise NotImplementedError(repr(cls))
def load_item(self, dump: Dump) -> _ConfigurationT:
"""
Create and load a new item from the given dump, or raise an assertion error.
:raise betty.serde.load.AssertionFailed: Raised when the dump is invalid and cannot be loaded.
"""
raise NotImplementedError(repr(self))

def keys(self) -> Iterator[_ConfigurationKeyT]:
"""
Expand Down Expand Up @@ -450,6 +427,12 @@ def __init__(
self._configurations: MutableSequence[_ConfigurationT] = []
super().__init__(configurations)

@override
def __eq__(self, other: Any) -> bool:
if not isinstance(other, self.__class__):
return NotImplemented
return list(self.values()) == list(other.values())

@override
def to_index(self, configuration_key: int) -> int:
return configuration_key
Expand Down Expand Up @@ -492,19 +475,13 @@ def update(self, other: Self) -> None:
self.append(*other)

@override
@classmethod
def load(
cls,
dump: Dump,
configuration: Self | None = None,
) -> Self:
if configuration is None:
configuration = cls()
else:
configuration._clear_without_dispatch()
with SerdeErrorCollection().assert_valid():
configuration.append(*assert_sequence(cls._item_type().load)(dump))
return configuration
def replace(self, *values: _ConfigurationT) -> None:
self._clear_without_dispatch()
self.append(*values)

@override
def load(self, dump: Dump) -> None:
self.replace(*assert_sequence(self.load_item)(dump))

@override
def dump(self) -> VoidableDump:
Expand Down Expand Up @@ -582,6 +559,18 @@ def __init__(
)
super().__init__(configurations)

@override
def __eq__(self, other: Any) -> bool:
if not isinstance(other, self.__class__):
return NotImplemented
return {
self._get_key(configuration): configuration
for configuration in self.values()
} == {
self._get_key(configuration): configuration
for configuration in other.values()
}

def _minimize_item_dump(self) -> bool:
return False

Expand Down Expand Up @@ -616,10 +605,8 @@ def values(self) -> Iterator[_ConfigurationT]:
def update(self, other: Self) -> None:
self.replace(*other.values())

@override
def replace(self, *values: _ConfigurationT) -> None:
"""
Replace any existing values with the given ones.
"""
self_keys = list(self.keys())
other = {self._get_key(value): value for value in values}
other_values = list(values)
Expand All @@ -644,20 +631,16 @@ def replace(self, *values: _ConfigurationT) -> None:
self.move_to_beginning(*other_keys)

@override
@classmethod
def load(
cls,
dump: Dump,
configuration: Self | None = None,
) -> Self:
if configuration is None:
configuration = cls()
dict_dump = assert_dict()(dump)
mapping = assert_mapping(cls._item_type().load)(
{key: cls._load_key(value, key) for key, value in dict_dump.items()}
def load(self, dump: Dump) -> None:
self.clear()
self.replace(
*assert_sequence(self.load_item)(
[
self._load_key(item_value_dump, item_key_dump)
for item_key_dump, item_value_dump in assert_dict()(dump).items()
]
)
)
configuration.replace(*mapping.values())
return configuration

@override
def dump(self) -> VoidableDump:
Expand Down Expand Up @@ -749,13 +732,12 @@ def _move_by_offset(
def _get_key(self, configuration: _ConfigurationT) -> _ConfigurationKeyT:
raise NotImplementedError(repr(self))

@classmethod
def _load_key(
cls,
self,
item_dump: Dump,
key_dump: str,
) -> Dump:
raise NotImplementedError(repr(cls))
raise NotImplementedError(repr(self))

def _dump_key(self, item_dump: VoidableDump) -> tuple[VoidableDump, str]:
raise NotImplementedError(repr(self))
Expand Down
Loading

0 comments on commit f089858

Please sign in to comment.