From c8fb193e2ceec117db87b3f6c6138df61d6eeef7 Mon Sep 17 00:00:00 2001 From: "Vladislav A. Proskurov" Date: Sun, 7 Jul 2024 11:20:51 +0400 Subject: [PATCH 1/4] feat: add yaml state --- pyproject.toml | 1 + src/iokit/__init__.py | 3 ++- src/iokit/extensions/__init__.py | 2 ++ src/iokit/extensions/yaml.py | 18 ++++++++++++++ tests/test_yaml.py | 40 ++++++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/iokit/extensions/yaml.py create mode 100644 tests/test_yaml.py diff --git a/pyproject.toml b/pyproject.toml index ab2f451..487cf24 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ dependencies = [ "humanize>=4.9.0", "typing-extensions>=4.8.0", "pytz>=2024.1", + "PyYAML>=6.0.1", ] [tool.setuptools.dynamic] diff --git a/src/iokit/__init__.py b/src/iokit/__init__.py index 7d6dccb..8ce059d 100644 --- a/src/iokit/__init__.py +++ b/src/iokit/__init__.py @@ -5,6 +5,7 @@ "Jsonl", "Tar", "Txt", + "Yaml", "State", "filter_states", "find_state", @@ -14,6 +15,6 @@ ] __version__ = "0.1.2" -from .extensions import Dat, Gzip, Json, Jsonl, Tar, Txt +from .extensions import Dat, Gzip, Json, Jsonl, Tar, Txt, Yaml 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 8401702..672aaa3 100644 --- a/src/iokit/extensions/__init__.py +++ b/src/iokit/extensions/__init__.py @@ -5,6 +5,7 @@ "Jsonl", "Tar", "Txt", + "Yaml", ] from .dat import Dat @@ -13,3 +14,4 @@ from .jsonl import Jsonl from .tar import Tar from .txt import Txt +from .yaml import Yaml diff --git a/src/iokit/extensions/yaml.py b/src/iokit/extensions/yaml.py new file mode 100644 index 0000000..493013d --- /dev/null +++ b/src/iokit/extensions/yaml.py @@ -0,0 +1,18 @@ +__all__ = [ + "Yaml", +] + +from typing import Any + +import yaml + +from iokit.state import State + + +class Yaml(State, suffix="yaml"): + def __init__(self, data: Any, **kwargs: Any): + data = yaml.safe_dump(data).encode("utf-8") + super().__init__(data=data, **kwargs) + + def load(self) -> Any: + return yaml.safe_load(self.data) diff --git a/tests/test_yaml.py b/tests/test_yaml.py new file mode 100644 index 0000000..dbc39f9 --- /dev/null +++ b/tests/test_yaml.py @@ -0,0 +1,40 @@ +from iokit.extensions.yaml import Yaml + + +def test_yaml_empty() -> None: + state = Yaml([], name="empty") + assert state.name == "empty.yaml" + assert state.size == 3 + assert state.data.getvalue() == b"[]\n" + assert not state.load() + + +def test_yaml_single() -> None: + state = Yaml({"key": "value"}, name="single") + assert state.name == "single.yaml" + assert state.load() == {"key": "value"} + + +def test_yaml_multiple() -> None: + state = Yaml({"first": 1, "second": 2}, name="multiple") + assert state.name == "multiple.yaml" + assert state.load() == {"first": 1, "second": 2} + assert state.size == 19 + + +def test_yaml_different() -> None: + data = { + "list": [1, 2, 3], + "tuple": (4, 5, 6), + "dict": {"a": 1, "b": 2}, + "str": "hello", + "int": 42, + } + state = Yaml(data, name="different") + assert state.name == "different.yaml" + loaded = state.load() + assert all(v1 == v2 for v1, v2 in zip(loaded["list"], [1, 2, 3])) + assert all(v1 == v2 for v1, v2 in zip(loaded["tuple"], (4, 5, 6))) + assert loaded["dict"] == {"a": 1, "b": 2} + assert loaded["str"] == "hello" + assert loaded["int"] == 42 From 71d0edea46f4aa020ae181f875c4dd707be2a46a Mon Sep 17 00:00:00 2001 From: "Vladislav A. Proskurov" Date: Sun, 7 Jul 2024 11:23:20 +0400 Subject: [PATCH 2/4] feat: v0.1.3 --- 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 8ce059d..0afe476 100644 --- a/src/iokit/__init__.py +++ b/src/iokit/__init__.py @@ -13,7 +13,7 @@ "save_file", "save_temp", ] -__version__ = "0.1.2" +__version__ = "0.1.3" from .extensions import Dat, Gzip, Json, Jsonl, Tar, Txt, Yaml from .state import State, filter_states, find_state From 87b083cbe257271dfea67dfcb5f0be6c869ffc2f Mon Sep 17 00:00:00 2001 From: "Vladislav A. Proskurov" Date: Sun, 7 Jul 2024 11:24:24 +0400 Subject: [PATCH 3/4] ci: run tests on pull-request --- .github/workflows/tests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1e6fa9d..740f39f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,8 +1,6 @@ name: Tests on: - push: - branches: [ "main", "dev" ] pull_request: branches: [ "*" ] From 9f5d0755b4380871cb1bad3e6ddd78ca9377d461 Mon Sep 17 00:00:00 2001 From: "Vladislav A. Proskurov" Date: Sun, 7 Jul 2024 11:27:23 +0400 Subject: [PATCH 4/4] docs: yaml usage example --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f9b2698..b28b4f3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ IOKit is a Python library that offers a suite of utilities for managing a wide range of input/output operations. Central to its design is the concept of a `State`, where each state signifies a unit of data that can be loaded, saved, or transformed. Each state corresponds to a valid file state, represented as a bytes-like object. -IOKit abstracts and unifies serialization and deserialization operations from various libraries into a single, cohesive interface. This allows for direct manipulation of the file's state in memory, eliminating the need for disk interaction. Consequently, it facilitates the (de)serialization of data in multiple formats, such as `json`, `txt`, `tar`, `gzip`, among others. This abstraction not only simplifies data handling but also enhances efficiency by reducing disk I/O operations. +IOKit abstracts and unifies serialization and deserialization operations from various libraries into a single, cohesive interface. This allows for direct manipulation of the file's state in memory, eliminating the need for disk interaction. Consequently, it facilitates the (de)serialization of data in multiple formats, such as `json`, `yaml`, `txt`, `tar`, `gzip`, among others. This abstraction not only simplifies data handling but also enhances efficiency by reducing disk I/O operations. ## Installation @@ -48,6 +48,22 @@ single.json (16B) {'key': 'value'} ``` +### YAML + +```python +from iokit import Yaml + +data = {"key": "value"} +state = Yaml(data, name="single") +print(state) +print(state.load()) +``` + +```plain-text +single.yaml (11B) +{'key': 'value'} +``` + ### GZip Compression ```python