pyquoks 2.7.2__tar.gz → 2.7.3__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.
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Denis Titovets
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.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Denis Titovets
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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyquoks
3
- Version: 2.7.2
3
+ Version: 2.7.3
4
4
  Summary: Пакет PyPI для часто используемых модулей в проектах diquoks
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -9,7 +9,7 @@ Author-email: den232titovets@yandex.ru>
9
9
  Requires-Python: >=3.14.0,<4.0.0
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.14
12
- Requires-Dist: pillow (>=12.2.0,<13.0.0)
12
+ Requires-Dist: pillow (>=12.3.0,<13.0.0)
13
13
  Requires-Dist: psutil (>=7.2.2,<8.0.0)
14
14
  Requires-Dist: pydantic (>=2.13.4,<3.0.0)
15
15
  Requires-Dist: requests (>=2.34.2,<3.0.0)
@@ -17,14 +17,9 @@ Description-Content-Type: text/markdown
17
17
 
18
18
  # pyquoks
19
19
 
20
- #### Пакет PyPI для часто используемых модулей в проектах diquoks
21
-
22
- ---
20
+ [![Continuous Integration](https://github.com/diquoks/pyquoks/actions/workflows/continuous-integration.yaml/badge.svg?event=push)](https://github.com/diquoks/pyquoks/actions/workflows/continuous-integration.yaml)
23
21
 
24
- ## Оглавление
25
-
26
- - [Контакты](#контакты)
27
- - [Связь с разработчиком](#связь-с-разработчиком)
22
+ #### Пакет PyPI для часто используемых модулей в проектах diquoks
28
23
 
29
24
  ---
30
25
 
@@ -1,19 +1,14 @@
1
- # pyquoks
2
-
3
- #### Пакет PyPI для часто используемых модулей в проектах diquoks
4
-
5
- ---
6
-
7
- ## Оглавление
8
-
9
- - [Контакты](#контакты)
10
- - [Связь с разработчиком](#связь-с-разработчиком)
11
-
12
- ---
13
-
14
- ## Контакты
15
-
16
- #### Связь с разработчиком
17
-
18
- - [Telegram для связи](https://t.me/diquoks)
19
- - [Почта для связи](mailto:den232titovets@yandex.ru)
1
+ # pyquoks
2
+
3
+ [![Continuous Integration](https://github.com/diquoks/pyquoks/actions/workflows/continuous-integration.yaml/badge.svg?event=push)](https://github.com/diquoks/pyquoks/actions/workflows/continuous-integration.yaml)
4
+
5
+ #### Пакет PyPI для часто используемых модулей в проектах diquoks
6
+
7
+ ---
8
+
9
+ ## Контакты
10
+
11
+ #### Связь с разработчиком
12
+
13
+ - [Telegram для связи](https://t.me/diquoks)
14
+ - [Почта для связи](mailto:den232titovets@yandex.ru)
@@ -1,31 +1,31 @@
1
- [project]
2
- name = "pyquoks"
3
- version = "2.7.2"
4
- dependencies = [
5
- "pillow (>=12.2.0,<13.0.0)",
6
- "psutil (>=7.2.2,<8.0.0)",
7
- "pydantic (>=2.13.4,<3.0.0)",
8
- "requests (>=2.34.2,<3.0.0)",
9
- ]
10
- requires-python = ">=3.14.0,<4.0.0"
11
- authors = [
12
- { name = "Denis Titovets", email = "den232titovets@yandex.ru>" }
13
- ]
14
- description = "Пакет PyPI для часто используемых модулей в проектах diquoks"
15
- readme = "README.md"
16
- license = "MIT"
17
- license-files = ["LICENSE"]
18
-
19
- [dependency-groups]
20
- dev = [
21
- "poetry (>=2.4.1,<3.0.0)",
22
- "pytest (>=9.0.3,<10.0.0)",
23
- "twine (>=6.2.0,<7.0.0)",
24
- ]
25
-
26
- [tool.pytest]
27
- pythonpath = ["src"]
28
-
29
- [build-system]
30
- requires = ["poetry-core (>=2.4.0,<3.0.0)"]
31
- build-backend = "poetry.core.masonry.api"
1
+ [project]
2
+ name = "pyquoks"
3
+ version = "2.7.3"
4
+ dependencies = [
5
+ "pillow (>=12.3.0,<13.0.0)",
6
+ "psutil (>=7.2.2,<8.0.0)",
7
+ "pydantic (>=2.13.4,<3.0.0)",
8
+ "requests (>=2.34.2,<3.0.0)",
9
+ ]
10
+ requires-python = ">=3.14.0,<4.0.0"
11
+ authors = [
12
+ { name = "Denis Titovets", email = "den232titovets@yandex.ru>" }
13
+ ]
14
+ description = "Пакет PyPI для часто используемых модулей в проектах diquoks"
15
+ readme = "README.md"
16
+ license = "MIT"
17
+ license-files = ["LICENSE"]
18
+
19
+ [dependency-groups]
20
+ dev = [
21
+ "poetry (>=2.4.1,<3.0.0)",
22
+ "pytest (>=9.1.1,<10.0.0)",
23
+ "twine (>=6.2.0,<7.0.0)",
24
+ ]
25
+
26
+ [tool.pytest]
27
+ pythonpath = ["src"]
28
+
29
+ [build-system]
30
+ requires = ["poetry-core (>=2.4.0,<3.0.0)"]
31
+ build-backend = "poetry.core.masonry.api"
@@ -1,6 +1,6 @@
1
- __all__ = [
2
- "managers",
3
- "providers",
4
- "services",
5
- "utils",
6
- ]
1
+ __all__ = [
2
+ "managers",
3
+ "providers",
4
+ "services",
5
+ "utils",
6
+ ]
@@ -1,4 +1,4 @@
1
- __all__ = [
2
- "config",
3
- "database",
4
- ]
1
+ __all__ = [
2
+ "config",
3
+ "database",
4
+ ]
@@ -1,151 +1,145 @@
1
- import configparser
2
- import json
3
- import typing
4
-
5
- from .. import utils
6
-
7
-
8
- class ConfigManager(utils._HasRequiredAttributes):
9
- """
10
- Class for managing data in configuration file
11
-
12
- **Required attributes**::
13
-
14
- # Predefined
15
-
16
- _PATH = pyquoks.utils.get_path("config.ini")
17
-
18
- Attributes:
19
- _PATH: Path to the configuration file
20
- """
21
-
22
- _REQUIRED_ATTRIBUTES = {
23
- "_PATH",
24
- }
25
-
26
- _PATH: str = utils.get_path("config.ini")
27
-
28
- def __init__(self) -> None:
29
- self._check_attributes()
30
-
31
- for attribute, object_type in self.__class__.__annotations__.items():
32
- if not issubclass(object_type, Config):
33
- continue
34
-
35
- setattr(self, attribute, object_type(self))
36
-
37
-
38
- class Config(utils._HasRequiredAttributes):
39
- """
40
- Class that represents a section in configuration file
41
-
42
- **Required attributes**::
43
-
44
- _SECTION = "Settings"
45
-
46
- Attributes:
47
- _SECTION: Name of the section in configuration file
48
- _parent: Parent object
49
- """
50
-
51
- _REQUIRED_ATTRIBUTES = {
52
- "_SECTION",
53
- }
54
-
55
- _SECTION: str
56
-
57
- _incorrect_content_exception = configparser.ParsingError(
58
- source="configuration file is filled incorrectly",
59
- )
60
-
61
- _parent: ConfigManager
62
-
63
- def __init__(self, parent: ConfigManager) -> None:
64
- self._check_attributes()
65
-
66
- self._parent = parent
67
-
68
- self._config = configparser.ConfigParser()
69
- self._config.read(self._parent._PATH)
70
-
71
- if not self._config.has_section(self._SECTION):
72
- self._config.add_section(self._SECTION)
73
-
74
- for attribute, object_type in self.__class__.__annotations__.items():
75
- try:
76
- setattr(self, attribute, self._config.get(self._SECTION, attribute))
77
- except Exception:
78
- self._config.set(self._SECTION, attribute, object_type.__name__)
79
- with open(self._parent._PATH, "w", encoding="utf-8") as file:
80
- self._config.write(file)
81
-
82
- for attribute, object_type in self.__class__.__annotations__.items():
83
- try:
84
- match object_type():
85
- case bool():
86
- if getattr(self, attribute) not in [str(True), str(False)]:
87
- setattr(self, attribute, None)
88
- raise self._incorrect_content_exception
89
-
90
- setattr(self, attribute, getattr(self, attribute) == str(True))
91
- case int():
92
- setattr(self, attribute, int(getattr(self, attribute)))
93
- case float():
94
- setattr(self, attribute, float(getattr(self, attribute)))
95
- case str():
96
- pass
97
- case dict() | list():
98
- setattr(self, attribute, json.loads(getattr(self, attribute)))
99
- case _:
100
- raise ValueError(f"{object_type.__name__} type is not supported!")
101
- except Exception:
102
- setattr(self, attribute, None)
103
-
104
- raise self._incorrect_content_exception
105
-
106
- @property
107
- def _values(self) -> dict | None:
108
- """
109
- :return: Values stored in this section
110
- """
111
-
112
- try:
113
- return {
114
- attribute: getattr(self, attribute) for attribute in self.__class__.__annotations__.keys()
115
- }
116
- except Exception:
117
- return None
118
-
119
- def update(self, **kwargs) -> None:
120
- """
121
- Updates provided attributes in object
122
- """
123
-
124
- for attribute, value in kwargs.items():
125
-
126
- if attribute not in self.__class__.__annotations__.keys():
127
- raise AttributeError(f"{attribute} is not specified!")
128
-
129
- object_type = self.__class__.__annotations__.get(attribute)
130
-
131
- # noinspection PyTypeChecker
132
- if not isinstance(value, typing.get_origin(object_type) or object_type):
133
- raise AttributeError(
134
- f"{attribute} has incorrect type! (must be {object_type.__name__})",
135
- )
136
-
137
- setattr(self, attribute, value)
138
-
139
- try:
140
- match object_type():
141
- case bool() | int() | float() | str():
142
- self._config.set(self._SECTION, attribute, str(value))
143
- case dict() | list():
144
- self._config.set(self._SECTION, attribute, json.dumps(value))
145
- case _:
146
- raise ValueError()
147
- except:
148
- raise ValueError(f"{object_type.__name__} type is not supported!")
149
-
150
- with open(self._parent._PATH, "w", encoding="utf-8") as file:
151
- self._config.write(file)
1
+ import configparser
2
+ import json
3
+ import typing
4
+
5
+ from .. import utils
6
+
7
+
8
+ class ConfigManager(utils._HasRequiredAttributes):
9
+ """
10
+ Class for managing data in configuration file
11
+
12
+ **Required attributes**::
13
+
14
+ # Predefined
15
+
16
+ _PATH = pyquoks.utils.get_path("config.ini")
17
+
18
+ Attributes:
19
+ _PATH: Path to the configuration file
20
+ """
21
+
22
+ _REQUIRED_ATTRIBUTES = {
23
+ "_PATH",
24
+ }
25
+
26
+ _PATH: str = utils.get_path("config.ini")
27
+
28
+ def __init__(self) -> None:
29
+ self._check_attributes()
30
+
31
+ for attribute, object_type in self.__class__.__annotations__.items():
32
+ if not issubclass(object_type, Config):
33
+ continue
34
+
35
+ setattr(self, attribute, object_type(self))
36
+
37
+
38
+ class Config(utils._HasRequiredAttributes):
39
+ """
40
+ Class that represents a section in configuration file
41
+
42
+ **Required attributes**::
43
+
44
+ _SECTION = "Settings"
45
+
46
+ Attributes:
47
+ _SECTION: Name of the section in configuration file
48
+ _parent: Parent object
49
+ """
50
+
51
+ _REQUIRED_ATTRIBUTES = {
52
+ "_SECTION",
53
+ }
54
+
55
+ _SECTION: str
56
+
57
+ _parent: ConfigManager
58
+
59
+ def __init__(self, parent: ConfigManager) -> None:
60
+ self._check_attributes()
61
+
62
+ self._parent = parent
63
+
64
+ self._config = configparser.ConfigParser()
65
+ self._config.read(self._parent._PATH)
66
+
67
+ if not self._config.has_section(self._SECTION):
68
+ self._config.add_section(self._SECTION)
69
+
70
+ for attribute, object_type in self.__class__.__annotations__.items():
71
+ try:
72
+ setattr(self, attribute, self._config.get(self._SECTION, attribute))
73
+ except Exception:
74
+ self._config.set(self._SECTION, attribute, object_type.__name__)
75
+ with open(self._parent._PATH, "w", encoding="utf-8") as file:
76
+ self._config.write(file)
77
+
78
+ for attribute, object_type in self.__class__.__annotations__.items():
79
+ try:
80
+ match object_type():
81
+ case bool():
82
+ if getattr(self, attribute) not in [str(True), str(False)]:
83
+ setattr(self, attribute, None)
84
+ raise configparser.ParsingError("configuration file is filled incorrectly!")
85
+
86
+ setattr(self, attribute, getattr(self, attribute) == str(True))
87
+ case int():
88
+ setattr(self, attribute, int(getattr(self, attribute)))
89
+ case float():
90
+ setattr(self, attribute, float(getattr(self, attribute)))
91
+ case str():
92
+ pass
93
+ case dict() | list():
94
+ setattr(self, attribute, json.loads(getattr(self, attribute)))
95
+ case _:
96
+ raise ValueError(f"{object_type.__name__} type is not supported!")
97
+ except Exception:
98
+ setattr(self, attribute, None)
99
+
100
+ raise configparser.ParsingError("configuration file is filled incorrectly!")
101
+
102
+ @property
103
+ def _values(self) -> dict | None:
104
+ """
105
+ :return: Values stored in this section
106
+ """
107
+
108
+ try:
109
+ return {
110
+ attribute: getattr(self, attribute) for attribute in self.__class__.__annotations__.keys()
111
+ }
112
+ except Exception:
113
+ return None
114
+
115
+ def update(self, **kwargs) -> None:
116
+ """
117
+ Updates provided attributes in object
118
+ """
119
+
120
+ for attribute, value in kwargs.items():
121
+ if attribute not in self.__class__.__annotations__.keys():
122
+ raise AttributeError(f"{attribute} is not specified!")
123
+
124
+ object_type = self.__class__.__annotations__.get(attribute)
125
+
126
+ # noinspection PyTypeChecker
127
+ if not isinstance(value, typing.get_origin(object_type) or object_type):
128
+ raise AttributeError(f"{attribute} has incorrect type! (must be {object_type.__name__})")
129
+
130
+ setattr(self, attribute, value)
131
+
132
+ try:
133
+ # noinspection calling-non-callable
134
+ match object_type():
135
+ case bool() | int() | float() | str():
136
+ self._config.set(self._SECTION, attribute, str(value))
137
+ case dict() | list():
138
+ self._config.set(self._SECTION, attribute, json.dumps(value))
139
+ case _:
140
+ raise ValueError()
141
+ except:
142
+ raise ValueError(f"{object_type.__name__} type is not supported!")
143
+
144
+ with open(self._parent._PATH, "w", encoding="utf-8") as file:
145
+ self._config.write(file)