From 702f4c93257e76709d195c8e56f54d338d9ecfad Mon Sep 17 00:00:00 2001 From: "Vladislav A. Proskurov" Date: Mon, 24 Jun 2024 16:31:34 +0400 Subject: [PATCH 1/5] test: base check of inheritanceness --- tests/test_state_inheritance.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/test_state_inheritance.py diff --git a/tests/test_state_inheritance.py b/tests/test_state_inheritance.py new file mode 100644 index 0000000..a8ee412 --- /dev/null +++ b/tests/test_state_inheritance.py @@ -0,0 +1,10 @@ +from iokit import Json, State + +class MyJson(Json, suffix="myjson"): + pass + +def test_state_inheritance_json() -> None: + myjson = MyJson({"a": 1}, name="test") + assert myjson.name == "test.myjson" + loaded = State(data=myjson.data, name="test.myjson") + assert loaded.load() == myjson.load() From 3686a455d42fa23679cfb4f6e9c00eed46b69af2 Mon Sep 17 00:00:00 2001 From: "Vladislav A. Proskurov" Date: Mon, 24 Jun 2024 16:49:10 +0400 Subject: [PATCH 2/5] feat: check subclasses while casting --- src/iokit/state.py | 20 +++++++++++++------- tests/test_state_inheritance.py | 4 +++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/iokit/state.py b/src/iokit/state.py index fc9457f..7359ffa 100644 --- a/src/iokit/state.py +++ b/src/iokit/state.py @@ -7,12 +7,14 @@ from datetime import datetime from fnmatch import fnmatch from io import BytesIO -from typing import Any, Generator, Iterable +from typing import Any, Generator, Iterable, Type from humanize import naturalsize from typing_extensions import Self from iokit.tools.time import now +from contextlib import suppress + Payload = BytesIO | bytes @@ -126,13 +128,17 @@ def __repr__(self) -> str: size = naturalsize(self.size, gnu=True) return f"{self.name} ({size})" + @classmethod + def by_suffix(cls, suffix: str) -> Type[Self]: + if suffix in cls._suffixes: + return cls + for klass in cls.__subclasses__(): + with suppress(ValueError): + return klass.by_suffix(suffix) + raise ValueError(f"Unknown state suffix {suffix}") + def cast(self) -> "State": - suffix = self.name.suffix - for klass in State.__subclasses__(): - if suffix in getattr(klass, "_suffixes"): - break - else: - raise ValueError(f"Unknown state suffix {suffix}") + klass = self.by_suffix(self.name.suffix) state = klass.__new__(klass) setattr(state, "_data", self.data) setattr(state, "_name", self.name) diff --git a/tests/test_state_inheritance.py b/tests/test_state_inheritance.py index a8ee412..cd64295 100644 --- a/tests/test_state_inheritance.py +++ b/tests/test_state_inheritance.py @@ -4,7 +4,9 @@ class MyJson(Json, suffix="myjson"): pass def test_state_inheritance_json() -> None: + assert getattr(MyJson, "_suffix") == "myjson" + assert getattr(MyJson, "_suffixes") == ("myjson",) myjson = MyJson({"a": 1}, name="test") assert myjson.name == "test.myjson" loaded = State(data=myjson.data, name="test.myjson") - assert loaded.load() == myjson.load() + assert loaded.load() == myjson.load() == {"a": 1} From ebd16e8e5a048a42705ca4de833f2288e2752827 Mon Sep 17 00:00:00 2001 From: "Vladislav A. Proskurov" Date: Mon, 24 Jun 2024 16:49:36 +0400 Subject: [PATCH 3/5] feat: --- src/iokit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iokit/__init__.py b/src/iokit/__init__.py index fa96bfd..0168a1e 100644 --- a/src/iokit/__init__.py +++ b/src/iokit/__init__.py @@ -11,7 +11,7 @@ "save_file", "save_temp", ] -__version__ = "0.1.1" +__version__ = "0.1.2" from .extensions import Gzip, Json, Jsonl, Tar, Txt from .state import State, filter_states, find_state From 30865e66e08e080885a9950e3980205b79134e89 Mon Sep 17 00:00:00 2001 From: "Vladislav A. Proskurov" Date: Mon, 24 Jun 2024 16:53:09 +0400 Subject: [PATCH 4/5] style: pre-commit --- src/iokit/state.py | 3 +-- tests/test_state_inheritance.py | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/iokit/state.py b/src/iokit/state.py index 7359ffa..fa87ba8 100644 --- a/src/iokit/state.py +++ b/src/iokit/state.py @@ -4,6 +4,7 @@ "find_state", ] +from contextlib import suppress from datetime import datetime from fnmatch import fnmatch from io import BytesIO @@ -13,8 +14,6 @@ from typing_extensions import Self from iokit.tools.time import now -from contextlib import suppress - Payload = BytesIO | bytes diff --git a/tests/test_state_inheritance.py b/tests/test_state_inheritance.py index cd64295..0b86e01 100644 --- a/tests/test_state_inheritance.py +++ b/tests/test_state_inheritance.py @@ -1,8 +1,10 @@ from iokit import Json, State + class MyJson(Json, suffix="myjson"): pass + def test_state_inheritance_json() -> None: assert getattr(MyJson, "_suffix") == "myjson" assert getattr(MyJson, "_suffixes") == ("myjson",) From daf34110490c2745e167563f9ac997d7410e8897 Mon Sep 17 00:00:00 2001 From: "Vladislav A. Proskurov" Date: Mon, 24 Jun 2024 17:08:38 +0400 Subject: [PATCH 5/5] feat: add *.dat state support --- src/iokit/__init__.py | 3 ++- src/iokit/extensions/__init__.py | 2 ++ src/iokit/extensions/dat.py | 15 +++++++++++++++ tests/test_dat.py | 13 +++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/iokit/extensions/dat.py create mode 100644 tests/test_dat.py diff --git a/src/iokit/__init__.py b/src/iokit/__init__.py index 0168a1e..7d6dccb 100644 --- a/src/iokit/__init__.py +++ b/src/iokit/__init__.py @@ -1,4 +1,5 @@ __all__ = [ + "Dat", "Gzip", "Json", "Jsonl", @@ -13,6 +14,6 @@ ] __version__ = "0.1.2" -from .extensions import Gzip, Json, Jsonl, Tar, Txt +from .extensions import Dat, Gzip, Json, Jsonl, Tar, Txt from .state import State, filter_states, find_state from .storage import load_file, save_file, save_temp diff --git a/src/iokit/extensions/__init__.py b/src/iokit/extensions/__init__.py index 72c0be0..8401702 100644 --- a/src/iokit/extensions/__init__.py +++ b/src/iokit/extensions/__init__.py @@ -1,4 +1,5 @@ __all__ = [ + "Dat", "Gzip", "Json", "Jsonl", @@ -6,6 +7,7 @@ "Txt", ] +from .dat import Dat from .gz import Gzip from .json import Json from .jsonl import Jsonl diff --git a/src/iokit/extensions/dat.py b/src/iokit/extensions/dat.py new file mode 100644 index 0000000..0cc3b02 --- /dev/null +++ b/src/iokit/extensions/dat.py @@ -0,0 +1,15 @@ +__all__ = [ + "Dat", +] + +from typing import Any + +from iokit.state import Payload, State + + +class Dat(State, suffix="dat"): + def __init__(self, data: Payload, **kwargs: Any): + super().__init__(data=data, **kwargs) + + def load(self) -> bytes: + return self._data.getvalue() diff --git a/tests/test_dat.py b/tests/test_dat.py new file mode 100644 index 0000000..e988ad9 --- /dev/null +++ b/tests/test_dat.py @@ -0,0 +1,13 @@ +from iokit import Dat, State + + +def test_dat() -> None: + state = Dat(b"test", name="test") + assert state.name == "test.dat" + assert state.load() == b"test" + + +def load_dat() -> None: + state = State(b"test", name="test.dat") + assert state.load() == b"test" + assert isinstance(state.cast(), Dat)