iokit 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- iokit-0.0.1/LICENSE +21 -0
- iokit-0.0.1/PKG-INFO +17 -0
- iokit-0.0.1/README.md +2 -0
- iokit-0.0.1/pyproject.toml +38 -0
- iokit-0.0.1/setup.cfg +4 -0
- iokit-0.0.1/src/iokit/__init__.py +9 -0
- iokit-0.0.1/src/iokit/extensions/__init__.py +7 -0
- iokit-0.0.1/src/iokit/extensions/gz.py +20 -0
- iokit-0.0.1/src/iokit/extensions/txt.py +13 -0
- iokit-0.0.1/src/iokit/state.py +133 -0
- iokit-0.0.1/src/iokit.egg-info/PKG-INFO +17 -0
- iokit-0.0.1/src/iokit.egg-info/SOURCES.txt +13 -0
- iokit-0.0.1/src/iokit.egg-info/dependency_links.txt +1 -0
- iokit-0.0.1/src/iokit.egg-info/requires.txt +3 -0
- iokit-0.0.1/src/iokit.egg-info/top_level.txt +1 -0
iokit-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Vladislav A. Proskurov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
iokit-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: iokit
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Input Output Kit
|
|
5
|
+
Author-email: "Vladislav A. Proskurov" <rilshok@pm.me>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/rilshok/iokit
|
|
8
|
+
Project-URL: Repository, https://github.com/rilshok/iokit
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: humanize>=4.9.0
|
|
13
|
+
Requires-Dist: typing-extensions>=4.8.0
|
|
14
|
+
Requires-Dist: pytz>=2024.1
|
|
15
|
+
|
|
16
|
+
# iok
|
|
17
|
+
input / output kit
|
iokit-0.0.1/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "iokit"
|
|
3
|
+
description = "Input Output Kit"
|
|
4
|
+
readme = "README.md"
|
|
5
|
+
requires-python = ">=3.10"
|
|
6
|
+
license = {text = "MIT"}
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
authors = [
|
|
9
|
+
{name = "Vladislav A. Proskurov", email = "rilshok@pm.me"},
|
|
10
|
+
]
|
|
11
|
+
dependencies = [
|
|
12
|
+
"humanize>=4.9.0",
|
|
13
|
+
"typing-extensions>=4.8.0",
|
|
14
|
+
"pytz>=2024.1",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[tool.setuptools.dynamic]
|
|
18
|
+
version = {attr = "iokit.__version__"}
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://github.com/rilshok/iokit"
|
|
22
|
+
Repository = "https://github.com/rilshok/iokit"
|
|
23
|
+
|
|
24
|
+
[tool.mypy]
|
|
25
|
+
strict = true
|
|
26
|
+
|
|
27
|
+
[tool.ruff]
|
|
28
|
+
line-length = 100
|
|
29
|
+
|
|
30
|
+
[tool.ruff.format]
|
|
31
|
+
docstring-code-format = true
|
|
32
|
+
|
|
33
|
+
[tool.vulture]
|
|
34
|
+
make_whitelist = true
|
|
35
|
+
sort_by_size = true
|
|
36
|
+
verbose = true
|
|
37
|
+
min_confidence = 100
|
|
38
|
+
paths = ["src/iokit"]
|
iokit-0.0.1/setup.cfg
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import gzip
|
|
2
|
+
from io import BytesIO
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from iokit.state import State
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Gzip(State, suffix="gz"):
|
|
9
|
+
def __init__(self, state: State, compression: int = 1, **kwargs: Any):
|
|
10
|
+
data = BytesIO()
|
|
11
|
+
gzip_file = gzip.GzipFile(fileobj=data, mode="wb", compresslevel=compression, mtime=0)
|
|
12
|
+
with gzip_file as gzip_buffer:
|
|
13
|
+
gzip_buffer.write(state.data.getvalue())
|
|
14
|
+
super().__init__(data=data, name=state.name, **kwargs)
|
|
15
|
+
|
|
16
|
+
def load(self) -> State:
|
|
17
|
+
gzip_file = gzip.GzipFile(fileobj=self.data, mode="rb")
|
|
18
|
+
with gzip_file as file:
|
|
19
|
+
data = file.read()
|
|
20
|
+
return State(data=data, name=str(self.name).removesuffix(".gz")).cast()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from iokit.state import State
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Txt(State, suffix="txt"):
|
|
7
|
+
def __init__(self, data: str, **kwargs: Any):
|
|
8
|
+
if not isinstance(data, str): # type: ignore
|
|
9
|
+
raise TypeError(f"Expected str, got {type(data).__name__}")
|
|
10
|
+
super().__init__(data=data.encode("utf-8"), **kwargs)
|
|
11
|
+
|
|
12
|
+
def load(self) -> str:
|
|
13
|
+
return self.data.getvalue().decode("utf-8")
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from io import BytesIO
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import pytz
|
|
6
|
+
from humanize import naturalsize
|
|
7
|
+
from typing_extensions import Self
|
|
8
|
+
|
|
9
|
+
Payload = BytesIO | bytes
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def now() -> datetime:
|
|
13
|
+
return datetime.now(pytz.utc)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class StateName:
|
|
17
|
+
def __init__(self, name: str):
|
|
18
|
+
self._name = name
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def stem(self) -> str:
|
|
22
|
+
split = self._name.split(sep=".", maxsplit=1)
|
|
23
|
+
return split[0]
|
|
24
|
+
|
|
25
|
+
@stem.setter
|
|
26
|
+
def stem(self, new: str) -> None:
|
|
27
|
+
suffix = ".".join(self.suffixes)
|
|
28
|
+
self._name = f"{new}.{suffix}"
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def suffix(self) -> str:
|
|
32
|
+
split = self._name.rsplit(sep=".", maxsplit=1)
|
|
33
|
+
if len(split) == 2:
|
|
34
|
+
return f"{split[-1]}"
|
|
35
|
+
raise ValueError(f"State name '{self._name}' does not have a suffix")
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def suffixes(self) -> tuple[str, ...]:
|
|
39
|
+
split = self._name.split(sep=".")[1:]
|
|
40
|
+
return tuple(f"{s}" for s in split)
|
|
41
|
+
|
|
42
|
+
def __str__(self) -> str:
|
|
43
|
+
return self._name
|
|
44
|
+
|
|
45
|
+
def __repr__(self) -> str:
|
|
46
|
+
return self._name
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def make(cls, stem: "str | StateName", suffix: str) -> Self:
|
|
50
|
+
if suffix:
|
|
51
|
+
return cls(f"{stem}.{suffix}")
|
|
52
|
+
return cls(str(stem))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class State:
|
|
56
|
+
_suffix: str = ""
|
|
57
|
+
_suffixes: tuple[str, ...] = ("",)
|
|
58
|
+
|
|
59
|
+
def __init__(self, data: Payload, name: str | StateName = "", time: datetime | None = None):
|
|
60
|
+
self._data = BytesIO(data) if isinstance(data, bytes) else data
|
|
61
|
+
self._name = StateName.make(name, self._suffix)
|
|
62
|
+
self._time = time or now()
|
|
63
|
+
|
|
64
|
+
def __init_subclass__(
|
|
65
|
+
cls,
|
|
66
|
+
suffix: str | None = None,
|
|
67
|
+
suffixes: tuple[str, ...] | None = None,
|
|
68
|
+
) -> None:
|
|
69
|
+
if suffix is None and suffixes is not None:
|
|
70
|
+
if len(suffixes) == 0:
|
|
71
|
+
raise ValueError("State subclasses must define at least one suffix")
|
|
72
|
+
suffix = suffixes[0]
|
|
73
|
+
if suffix is not None and suffixes is None:
|
|
74
|
+
suffixes = (suffix,)
|
|
75
|
+
|
|
76
|
+
if suffix is not None and suffixes is not None:
|
|
77
|
+
if suffix not in suffixes:
|
|
78
|
+
suffixes = (suffix, *suffixes)
|
|
79
|
+
|
|
80
|
+
if suffix is None or suffixes is None:
|
|
81
|
+
raise ValueError("State subclasses must define a suffix or suffixes")
|
|
82
|
+
|
|
83
|
+
cls._suffix = suffix
|
|
84
|
+
cls._suffixes = suffixes
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def name(self) -> StateName:
|
|
88
|
+
return self._name
|
|
89
|
+
|
|
90
|
+
@name.setter
|
|
91
|
+
def name(self, value: str | StateName) -> None:
|
|
92
|
+
if isinstance(value, str):
|
|
93
|
+
value = StateName(value)
|
|
94
|
+
self._name = value
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def time(self) -> datetime:
|
|
98
|
+
return self._time
|
|
99
|
+
|
|
100
|
+
@time.setter
|
|
101
|
+
def time(self, value: datetime) -> None:
|
|
102
|
+
self._time = value
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def data(self) -> BytesIO:
|
|
106
|
+
self._data.seek(0)
|
|
107
|
+
return BytesIO(self._data.getvalue())
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def size(self) -> int:
|
|
111
|
+
return self._data.getbuffer().nbytes
|
|
112
|
+
|
|
113
|
+
def __repr__(self) -> str:
|
|
114
|
+
size = naturalsize(self.size, gnu=True)
|
|
115
|
+
return f"{self.name} ({size})"
|
|
116
|
+
|
|
117
|
+
def cast(self) -> "State":
|
|
118
|
+
suffix = self.name.suffix
|
|
119
|
+
for klass in State.__subclasses__():
|
|
120
|
+
if suffix in getattr(klass, "_suffixes"):
|
|
121
|
+
break
|
|
122
|
+
else:
|
|
123
|
+
raise ValueError(f"Unknown state suffix {suffix}")
|
|
124
|
+
state = klass.__new__(klass)
|
|
125
|
+
setattr(state, "_data", self.data)
|
|
126
|
+
setattr(state, "_name", self.name)
|
|
127
|
+
setattr(state, "_time", self.time)
|
|
128
|
+
return state
|
|
129
|
+
|
|
130
|
+
def load(self) -> Any:
|
|
131
|
+
if not self.name.suffix:
|
|
132
|
+
return self.data.getvalue()
|
|
133
|
+
return self.cast().load()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: iokit
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Input Output Kit
|
|
5
|
+
Author-email: "Vladislav A. Proskurov" <rilshok@pm.me>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/rilshok/iokit
|
|
8
|
+
Project-URL: Repository, https://github.com/rilshok/iokit
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: humanize>=4.9.0
|
|
13
|
+
Requires-Dist: typing-extensions>=4.8.0
|
|
14
|
+
Requires-Dist: pytz>=2024.1
|
|
15
|
+
|
|
16
|
+
# iok
|
|
17
|
+
input / output kit
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/iokit/__init__.py
|
|
5
|
+
src/iokit/state.py
|
|
6
|
+
src/iokit.egg-info/PKG-INFO
|
|
7
|
+
src/iokit.egg-info/SOURCES.txt
|
|
8
|
+
src/iokit.egg-info/dependency_links.txt
|
|
9
|
+
src/iokit.egg-info/requires.txt
|
|
10
|
+
src/iokit.egg-info/top_level.txt
|
|
11
|
+
src/iokit/extensions/__init__.py
|
|
12
|
+
src/iokit/extensions/gz.py
|
|
13
|
+
src/iokit/extensions/txt.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
iokit
|