python3-commons 0.18.7__tar.gz → 0.18.9__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.
Files changed (74) hide show
  1. {python3_commons-0.18.7/src/python3_commons.egg-info → python3_commons-0.18.9}/PKG-INFO +3 -3
  2. {python3_commons-0.18.7 → python3_commons-0.18.9}/pyproject.toml +2 -2
  3. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/soap_client.py +96 -102
  4. {python3_commons-0.18.7 → python3_commons-0.18.9/src/python3_commons.egg-info}/PKG-INFO +3 -3
  5. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons.egg-info/requires.txt +2 -2
  6. {python3_commons-0.18.7 → python3_commons-0.18.9}/uv.lock +31 -31
  7. {python3_commons-0.18.7 → python3_commons-0.18.9}/.coveragerc +0 -0
  8. {python3_commons-0.18.7 → python3_commons-0.18.9}/.devcontainer/Dockerfile +0 -0
  9. {python3_commons-0.18.7 → python3_commons-0.18.9}/.devcontainer/devcontainer.json +0 -0
  10. {python3_commons-0.18.7 → python3_commons-0.18.9}/.devcontainer/docker-compose.yml +0 -0
  11. {python3_commons-0.18.7 → python3_commons-0.18.9}/.env_template +0 -0
  12. {python3_commons-0.18.7 → python3_commons-0.18.9}/.github/workflows/checks.yml +0 -0
  13. {python3_commons-0.18.7 → python3_commons-0.18.9}/.github/workflows/python-publish.yaml +0 -0
  14. {python3_commons-0.18.7 → python3_commons-0.18.9}/.github/workflows/release-on-tag-push.yml +0 -0
  15. {python3_commons-0.18.7 → python3_commons-0.18.9}/.gitignore +0 -0
  16. {python3_commons-0.18.7 → python3_commons-0.18.9}/.pre-commit-config.yaml +0 -0
  17. {python3_commons-0.18.7 → python3_commons-0.18.9}/.python-version +0 -0
  18. {python3_commons-0.18.7 → python3_commons-0.18.9}/AUTHORS.rst +0 -0
  19. {python3_commons-0.18.7 → python3_commons-0.18.9}/CHANGELOG.rst +0 -0
  20. {python3_commons-0.18.7 → python3_commons-0.18.9}/LICENSE +0 -0
  21. {python3_commons-0.18.7 → python3_commons-0.18.9}/README.md +0 -0
  22. {python3_commons-0.18.7 → python3_commons-0.18.9}/README.rst +0 -0
  23. {python3_commons-0.18.7 → python3_commons-0.18.9}/docs/Makefile +0 -0
  24. {python3_commons-0.18.7 → python3_commons-0.18.9}/docs/_static/.gitignore +0 -0
  25. {python3_commons-0.18.7 → python3_commons-0.18.9}/docs/authors.rst +0 -0
  26. {python3_commons-0.18.7 → python3_commons-0.18.9}/docs/changelog.rst +0 -0
  27. {python3_commons-0.18.7 → python3_commons-0.18.9}/docs/conf.py +0 -0
  28. {python3_commons-0.18.7 → python3_commons-0.18.9}/docs/index.rst +0 -0
  29. {python3_commons-0.18.7 → python3_commons-0.18.9}/docs/license.rst +0 -0
  30. {python3_commons-0.18.7 → python3_commons-0.18.9}/setup.cfg +0 -0
  31. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/__init__.py +0 -0
  32. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/api_client.py +0 -0
  33. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/async_functools.py +0 -0
  34. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/audit.py +0 -0
  35. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/auth.py +0 -0
  36. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/cache.py +0 -0
  37. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/conf.py +0 -0
  38. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/db/__init__.py +0 -0
  39. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/db/helpers.py +0 -0
  40. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/db/models/__init__.py +0 -0
  41. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/db/models/auth.py +0 -0
  42. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/db/models/common.py +0 -0
  43. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/db/models/rbac.py +0 -0
  44. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/db/models/users.py +0 -0
  45. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/exceptions.py +0 -0
  46. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/fs.py +0 -0
  47. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/generators.py +0 -0
  48. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/helpers.py +0 -0
  49. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/log/__init__.py +0 -0
  50. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/log/filters.py +0 -0
  51. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/log/formatters.py +0 -0
  52. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/object_storage.py +0 -0
  53. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/permissions.py +0 -0
  54. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/serializers/__init__.py +0 -0
  55. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/serializers/common.py +0 -0
  56. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/serializers/json.py +0 -0
  57. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/serializers/msgpack.py +0 -0
  58. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons/serializers/msgspec.py +0 -0
  59. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons.egg-info/SOURCES.txt +0 -0
  60. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons.egg-info/dependency_links.txt +0 -0
  61. {python3_commons-0.18.7 → python3_commons-0.18.9}/src/python3_commons.egg-info/top_level.txt +0 -0
  62. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/__init__.py +0 -0
  63. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/integration/__init__.py +0 -0
  64. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/integration/test_cache.py +0 -0
  65. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/integration/test_osc.py +0 -0
  66. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/unit/__init__.py +0 -0
  67. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/unit/conftest.py +0 -0
  68. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/unit/log/__init__.py +0 -0
  69. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/unit/log/test_formatters.py +0 -0
  70. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/unit/test_async_functools.py +0 -0
  71. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/unit/test_audit.py +0 -0
  72. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/unit/test_helpers.py +0 -0
  73. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/unit/test_msgpack.py +0 -0
  74. {python3_commons-0.18.7 → python3_commons-0.18.9}/tests/unit/test_msgspec.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python3-commons
3
- Version: 0.18.7
3
+ Version: 0.18.9
4
4
  Summary: Re-usable Python3 code
5
5
  Author-email: Oleg Korsak <kamikaze.is.waiting.you@gmail.com>
6
6
  License-Expression: GPL-3.0
@@ -38,8 +38,8 @@ Provides-Extra: database
38
38
  Requires-Dist: asyncpg~=0.31.0; extra == "database"
39
39
  Requires-Dist: SQLAlchemy[asyncio]~=2.0.49; extra == "database"
40
40
  Provides-Extra: object-storage
41
- Requires-Dist: aiobotocore~=3.5.0; extra == "object-storage"
42
- Requires-Dist: object-storage-client==0.0.23; extra == "object-storage"
41
+ Requires-Dist: aiobotocore~=3.6.0; extra == "object-storage"
42
+ Requires-Dist: object-storage-client==0.0.25; extra == "object-storage"
43
43
  Provides-Extra: soap-client
44
44
  Requires-Dist: aiohttp[speedups]<3.15.0,>=3.13.5; extra == "soap-client"
45
45
  Requires-Dist: certifi==2026.4.22; extra == "soap-client"
@@ -54,8 +54,8 @@ database = [
54
54
  "SQLAlchemy[asyncio]~=2.0.49"
55
55
  ]
56
56
  object-storage = [
57
- "aiobotocore~=3.5.0",
58
- "object-storage-client==0.0.23"
57
+ "aiobotocore~=3.6.0",
58
+ "object-storage-client==0.0.25"
59
59
  ]
60
60
  soap-client = [
61
61
  "aiohttp[speedups]>=3.13.5,<3.15.0",
@@ -1,7 +1,3 @@
1
- """
2
- Async SOAP client built on aiohttp + zeep.
3
- """
4
-
5
1
  from __future__ import annotations
6
2
 
7
3
  import asyncio
@@ -13,10 +9,9 @@ from contextlib import asynccontextmanager
13
9
  from dataclasses import dataclass
14
10
  from typing import TYPE_CHECKING, Any, Self
15
11
 
16
- import certifi
17
-
18
12
  try:
19
13
  import aiohttp
14
+ import certifi
20
15
  from aiohttp import ClientSession, ClientTimeout, TCPConnector
21
16
  from requests import Response
22
17
  from requests.cookies import RequestsCookieJar
@@ -38,55 +33,48 @@ logger = logging.getLogger(__name__)
38
33
 
39
34
  def _make_ssl_context(*, verify: bool) -> ssl.SSLContext | bool:
40
35
  if not verify:
41
- return False # aiohttp accepts False to disable verification
36
+ return False
42
37
 
43
38
  return ssl.create_default_context(cafile=certifi.where())
44
39
 
45
40
 
46
41
  @dataclass(frozen=True, slots=True)
47
42
  class TransportConfig:
48
- """Immutable transport settings passed to AsyncTransport."""
49
-
50
43
  timeout: int = 300
51
- """Total timeout in seconds for WSDL fetches."""
52
-
53
44
  operation_timeout: int = 60
54
- """Total timeout in seconds for SOAP operation calls."""
55
-
56
45
  verify_ssl: bool = True
57
46
  proxy: str | None = None
58
47
 
59
48
 
60
- class AsyncTransport(Transport):
61
- """
62
- Async transport for zeep using aiohttp.
63
-
64
- Usage::
49
+ # -------------------------
50
+ # Transport
51
+ # -------------------------
65
52
 
66
- async with soap_client("https://example.com/service?wsdl") as client:
67
- result = await client.service.SomeOperation(...)
68
- """
69
53
 
54
+ class AsyncTransport(Transport):
70
55
  def __init__(
71
- self,
72
- *,
73
- session: ClientSession,
74
- config: TransportConfig,
75
- _owns_session: bool = False,
56
+ self,
57
+ *,
58
+ session: ClientSession,
59
+ config: TransportConfig,
60
+ loop: asyncio.AbstractEventLoop,
61
+ owns_session: bool = False,
76
62
  ) -> None:
77
63
  super().__init__()
78
64
  self._session = session
79
65
  self._config = config
80
- self._owns_session = _owns_session
66
+ self._loop = loop
67
+ self._owns_session = owns_session
81
68
 
82
69
  @classmethod
83
70
  def from_config(
84
- cls,
85
- config: TransportConfig | None = None,
86
- *,
87
- session: ClientSession | None = None,
88
- ) -> Self:
71
+ cls,
72
+ config: TransportConfig | None = None,
73
+ *,
74
+ session: ClientSession | None = None,
75
+ ) -> AsyncTransport:
89
76
  config = config or TransportConfig()
77
+ loop = asyncio.get_running_loop()
90
78
  owns_session = session is None
91
79
 
92
80
  if owns_session:
@@ -96,7 +84,12 @@ class AsyncTransport(Transport):
96
84
  headers={'User-Agent': f'Zeep/{get_version()} (www.python-zeep.org)'},
97
85
  )
98
86
 
99
- return cls(session=session, config=config, _owns_session=owns_session)
87
+ return cls(
88
+ session=session,
89
+ config=config,
90
+ loop=loop,
91
+ owns_session=owns_session,
92
+ )
100
93
 
101
94
  async def aclose(self) -> None:
102
95
  if self._owns_session:
@@ -110,7 +103,6 @@ class AsyncTransport(Transport):
110
103
 
111
104
  @staticmethod
112
105
  def _build_response(response: aiohttp.ClientResponse, body: bytes) -> Response:
113
- """Convert an aiohttp response into a requests.Response for zeep."""
114
106
  r = Response()
115
107
  r.status_code = response.status
116
108
  r._content = body # noqa: SLF001
@@ -127,116 +119,118 @@ class AsyncTransport(Transport):
127
119
 
128
120
  return r
129
121
 
122
+ async def _fetch(self, url: str) -> bytes:
123
+ async with self._session.get(
124
+ url,
125
+ proxy=self._config.proxy,
126
+ timeout=ClientTimeout(total=self._config.timeout),
127
+ ) as resp:
128
+ body = await resp.read()
129
+
130
+ if resp.status >= 400:
131
+ raise TransportError(
132
+ status_code=resp.status,
133
+ message=body.decode(errors='ignore'),
134
+ )
135
+
136
+ return body
137
+
130
138
  def load(self, url: str) -> bytes:
131
139
  """
132
- Sync entry-point zeep calls during WSDL document init.
133
-
134
- Creates a short-lived session confined to its own event loop so there
135
- is no cross-loop session sharing with the operational session.
140
+ Called synchronously by zeep during WSDL/XSD parsing.
141
+ Always runs in a fresh thread with its own isolated event loop —
142
+ never touches self._loop to avoid deadlock.
136
143
  """
137
144
  if not url:
138
145
  return b''
139
146
 
140
147
  async def _fetch() -> bytes:
141
- async with (
142
- ClientSession(
148
+ async with ClientSession(
143
149
  connector=TCPConnector(ssl=_make_ssl_context(verify=self._config.verify_ssl)),
144
150
  timeout=ClientTimeout(total=self._config.timeout),
145
151
  headers={'User-Agent': f'Zeep/{get_version()} (www.python-zeep.org)'},
146
- ) as session,
147
- session.get(url, proxy=self._config.proxy) as resp,
148
- ):
149
- content = await resp.read()
150
-
151
- if resp.status >= 400:
152
- raise TransportError(
153
- status_code=resp.status,
154
- message=content.decode(errors='ignore'),
155
- )
156
-
157
- return content
158
-
159
- # load() is always called from within a running event loop (during
160
- # AsyncClient.__init__ inside the soap_client context manager), so
161
- # run_until_complete on the running loop would raise. Always delegate
162
- # to a thread with its own fresh event loop.
152
+ ) as session:
153
+ async with session.get(url, proxy=self._config.proxy) as resp:
154
+ body = await resp.read()
155
+ if resp.status >= 400:
156
+ raise TransportError(
157
+ status_code=resp.status,
158
+ message=body.decode(errors='ignore'),
159
+ )
160
+ return body
161
+
163
162
  with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
164
163
  return pool.submit(asyncio.run, _fetch()).result()
165
164
 
166
- async def post(
165
+ async def post_xml(
167
166
  self,
168
167
  address: str,
169
- message: bytes,
168
+ envelope: Any,
170
169
  headers: dict[str, str],
171
- *,
172
- timeout: int | None = None,
173
170
  ) -> Response:
174
- logger.debug('SOAP POST → %s\n%s', address, message)
171
+ return await self.post(address, etree_to_string(envelope), headers)
172
+
173
+ async def post(
174
+ self,
175
+ address: str,
176
+ message: bytes,
177
+ headers: dict[str, str],
178
+ *,
179
+ timeout: int | None = None,
180
+ ) -> Response:
181
+ logger.debug('SOAP POST → %s', address)
175
182
 
176
183
  async with self._session.post(
177
- address,
178
- data=message,
179
- headers=headers,
180
- proxy=self._config.proxy,
181
- timeout=ClientTimeout(total=timeout) if timeout is not None else None,
184
+ address,
185
+ data=message,
186
+ headers=headers,
187
+ proxy=self._config.proxy,
188
+ timeout=ClientTimeout(total=timeout) if timeout is not None else None,
182
189
  ) as resp:
183
190
  body = await resp.read()
184
- logger.debug('SOAP ← %s (HTTP %d)\n%s', address, resp.status, body)
191
+ logger.debug('SOAP ← %s (%d)', address, resp.status)
185
192
  return self._build_response(resp, body)
186
193
 
187
- def post_xml(
188
- self,
189
- address: str,
190
- envelope: Any,
191
- headers: dict[str, str],
192
- ) -> Response:
193
- """
194
- Sync entry-point zeep calls from a thread executor during send_async.
195
- Bridges back into the running event loop via run_coroutine_threadsafe.
196
- """
197
- loop = asyncio.get_event_loop()
198
- future = asyncio.run_coroutine_threadsafe(
199
- self.post(address, etree_to_string(envelope), headers),
200
- loop,
201
- )
202
- return future.result()
203
-
204
194
  async def get(
205
- self,
206
- address: str,
207
- params: dict[str, str],
208
- headers: dict[str, str],
195
+ self,
196
+ address: str,
197
+ params: dict[str, str],
198
+ headers: dict[str, str],
209
199
  ) -> Response:
210
200
  async with self._session.get(
211
- address,
212
- params=params,
213
- headers=headers,
214
- proxy=self._config.proxy,
201
+ address,
202
+ params=params,
203
+ headers=headers,
204
+ proxy=self._config.proxy,
215
205
  ) as resp:
216
206
  body = await resp.read()
217
207
  return self._build_response(resp, body)
218
208
 
219
209
 
220
210
  def build_soap_client(
221
- wsdl_url: str,
222
- transport: AsyncTransport,
223
- plugins: Sequence[Plugin] | None = None,
211
+ wsdl_url: str,
212
+ transport: AsyncTransport,
213
+ plugins: Sequence[Plugin] | None = None,
224
214
  ) -> AsyncClient:
225
215
  if not wsdl_url:
226
216
  msg = 'wsdl_url must be a non-empty string.'
227
217
 
228
218
  raise ValueError(msg)
229
219
 
230
- return AsyncClient(wsdl_url, transport=transport, plugins=list(plugins or []))
220
+ return AsyncClient(
221
+ wsdl_url,
222
+ transport=transport,
223
+ plugins=list(plugins or []),
224
+ )
231
225
 
232
226
 
233
227
  @asynccontextmanager
234
228
  async def soap_client(
235
- wsdl_url: str,
236
- *,
237
- config: TransportConfig | None = None,
238
- session: ClientSession | None = None,
239
- plugins: Sequence[Plugin] | None = None,
229
+ wsdl_url: str,
230
+ *,
231
+ config: TransportConfig | None = None,
232
+ session: ClientSession | None = None,
233
+ plugins: Sequence[Plugin] | None = None,
240
234
  ) -> AsyncIterator[AsyncClient]:
241
235
  """
242
236
  Async context manager yielding a ready-to-use zeep AsyncClient.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python3-commons
3
- Version: 0.18.7
3
+ Version: 0.18.9
4
4
  Summary: Re-usable Python3 code
5
5
  Author-email: Oleg Korsak <kamikaze.is.waiting.you@gmail.com>
6
6
  License-Expression: GPL-3.0
@@ -38,8 +38,8 @@ Provides-Extra: database
38
38
  Requires-Dist: asyncpg~=0.31.0; extra == "database"
39
39
  Requires-Dist: SQLAlchemy[asyncio]~=2.0.49; extra == "database"
40
40
  Provides-Extra: object-storage
41
- Requires-Dist: aiobotocore~=3.5.0; extra == "object-storage"
42
- Requires-Dist: object-storage-client==0.0.23; extra == "object-storage"
41
+ Requires-Dist: aiobotocore~=3.6.0; extra == "object-storage"
42
+ Requires-Dist: object-storage-client==0.0.25; extra == "object-storage"
43
43
  Provides-Extra: soap-client
44
44
  Requires-Dist: aiohttp[speedups]<3.15.0,>=3.13.5; extra == "soap-client"
45
45
  Requires-Dist: certifi==2026.4.22; extra == "soap-client"
@@ -32,8 +32,8 @@ asyncpg~=0.31.0
32
32
  SQLAlchemy[asyncio]~=2.0.49
33
33
 
34
34
  [object-storage]
35
- aiobotocore~=3.5.0
36
- object-storage-client==0.0.23
35
+ aiobotocore~=3.6.0
36
+ object-storage-client==0.0.25
37
37
 
38
38
  [soap-client]
39
39
  aiohttp[speedups]<3.15.0,>=3.13.5
@@ -4,7 +4,7 @@ requires-python = "==3.14.*"
4
4
 
5
5
  [[package]]
6
6
  name = "aiobotocore"
7
- version = "3.5.0"
7
+ version = "3.6.0"
8
8
  source = { registry = "https://pypi.org/simple" }
9
9
  dependencies = [
10
10
  { name = "aiohttp" },
@@ -15,9 +15,9 @@ dependencies = [
15
15
  { name = "python-dateutil" },
16
16
  { name = "wrapt" },
17
17
  ]
18
- sdist = { url = "https://files.pythonhosted.org/packages/e6/89/9533b377e9412013cc43a539d81bc5f8feeb4b6830643821ad612f78b09b/aiobotocore-3.5.0.tar.gz", hash = "sha256:d45d1c4659ad0e48b694a5aa4ff18829100386f7de96c8d146ec7757a6f12918", size = 123061, upload-time = "2026-04-21T07:25:26.993Z" }
18
+ sdist = { url = "https://files.pythonhosted.org/packages/28/52/4689a0c2ddced3888c687a84b820da37da6abda5ec52d96a7f11f22ff6ec/aiobotocore-3.6.0.tar.gz", hash = "sha256:78e6b95b258bcdde8d681d6851f88f337ed30b2d6611fae45366e6bf7488feb3", size = 123104, upload-time = "2026-05-01T20:33:31.109Z" }
19
19
  wheels = [
20
- { url = "https://files.pythonhosted.org/packages/2d/05/6eeeadef45c24630af0ceae4d038b883e9a394786300529286ba8cc1e62d/aiobotocore-3.5.0-py3-none-any.whl", hash = "sha256:49ce35bb8b96b85d3251c2cbbb2ed7a028dc0cb0d0d0801f9ccca1ccd0d41ded", size = 88281, upload-time = "2026-04-21T07:25:25.258Z" },
20
+ { url = "https://files.pythonhosted.org/packages/72/9a/17033aaafb880932eec0b0054a8e1cf201cb74501dfb0518c6b39fc5b258/aiobotocore-3.6.0-py3-none-any.whl", hash = "sha256:bf1c2e1d8492d98c9b63b330723a44b41a5d402afd19eaca704e107b91669c09", size = 88259, upload-time = "2026-05-01T20:33:29.213Z" },
21
21
  ]
22
22
 
23
23
  [[package]]
@@ -176,16 +176,16 @@ wheels = [
176
176
 
177
177
  [[package]]
178
178
  name = "botocore"
179
- version = "1.42.91"
179
+ version = "1.43.0"
180
180
  source = { registry = "https://pypi.org/simple" }
181
181
  dependencies = [
182
182
  { name = "jmespath" },
183
183
  { name = "python-dateutil" },
184
184
  { name = "urllib3" },
185
185
  ]
186
- sdist = { url = "https://files.pythonhosted.org/packages/21/bc/a4b7c46471c2e789ad8c4c7acfd7f302fdb481d93ff870f441249b924ae6/botocore-1.42.91.tar.gz", hash = "sha256:d252e27bc454afdbf5ed3dc617aa423f2c855c081e98b7963093399483ecc698", size = 15213010, upload-time = "2026-04-17T19:30:50.793Z" }
186
+ sdist = { url = "https://files.pythonhosted.org/packages/28/79/2f4be1896db3db7ccf44504253a175d56b6bd6b669619edc5147d1aa21ea/botocore-1.43.0.tar.gz", hash = "sha256:e933b31a2d644253e1d029d7d39e99ba41b87e29300534f189744cc438cdf928", size = 15286817, upload-time = "2026-04-29T22:07:31.723Z" }
187
187
  wheels = [
188
- { url = "https://files.pythonhosted.org/packages/b1/fc/24cc0a47c824f13933e210e9ad034b4fba22f7185b8d904c0fbf5a3b2be8/botocore-1.42.91-py3-none-any.whl", hash = "sha256:7a28c3cc6bfab5724ad18899d52402b776a0de7d87fa20c3c5270bcaaf199ce8", size = 14897344, upload-time = "2026-04-17T19:30:44.245Z" },
188
+ { url = "https://files.pythonhosted.org/packages/bf/4b/afc1fef8a43bafb139f57f73bbd70df82807af5934321e8112ae50668827/botocore-1.43.0-py3-none-any.whl", hash = "sha256:cc5b15eaec3c6eac05d8012cb5ef17ebe891beb88a16ca13c374bfaece1241e6", size = 14970102, upload-time = "2026-04-29T22:07:27Z" },
189
189
  ]
190
190
 
191
191
  [[package]]
@@ -717,13 +717,13 @@ wheels = [
717
717
 
718
718
  [[package]]
719
719
  name = "object-storage-client"
720
- version = "0.0.23"
720
+ version = "0.0.25"
721
721
  source = { registry = "https://pypi.org/simple" }
722
- sdist = { url = "https://files.pythonhosted.org/packages/8d/05/2789ff2531d2f8e5be4643505dc8052f4d72cd15f635bdee160c464a6cce/object_storage_client-0.0.23.tar.gz", hash = "sha256:991ba770604c96ffdd992939a2fe2438a0250dc1cd17e3ddf3a6def436985507", size = 41641, upload-time = "2026-04-26T18:50:40.694Z" }
722
+ sdist = { url = "https://files.pythonhosted.org/packages/01/34/c6796891f4271e65c14f0ab098a0e4abd2ff0658f4d065cfc7093869e85c/object_storage_client-0.0.25.tar.gz", hash = "sha256:c29a789b9e7d8fc8c42f7a3bf0ff881cb736024c87f571693d9799d367d80e9a", size = 41697, upload-time = "2026-05-05T17:18:01.082Z" }
723
723
  wheels = [
724
- { url = "https://files.pythonhosted.org/packages/ea/26/f2a6f1d83b580d1b3fddc2aa40b3a295f4fcd34e78ef860f7d9485c8eccc/object_storage_client-0.0.23-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ef7d3736c26dcfebe5b468cd662dc19bd6f724e82dfb61b0f568d66f1fdf7a05", size = 1945209, upload-time = "2026-04-26T18:50:39.519Z" },
725
- { url = "https://files.pythonhosted.org/packages/c9/19/a41fba90759ae91dab35f98665d1895aeb193f42d2fe899977d428bb4820/object_storage_client-0.0.23-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3a6535a564e0ab97636d810bfc5ad49c10048a1f0ad241b09c91a4fc916bbf", size = 2137323, upload-time = "2026-04-26T18:50:45.91Z" },
726
- { url = "https://files.pythonhosted.org/packages/a8/20/2b309e05ad849cfc2e757c3b62030211904e82b32cb07d48648d941c72c1/object_storage_client-0.0.23-cp314-cp314-win_amd64.whl", hash = "sha256:b71e1fe22f2fc900a08b8b4a356cab4b927eaf84b483b5330f7c96157c4dd9ae", size = 2126848, upload-time = "2026-04-26T18:50:41.661Z" },
724
+ { url = "https://files.pythonhosted.org/packages/cf/84/edc997f45f4fe1df1f4b2fe1463f9c1fad3188478ab9b724fb9ceb6187fe/object_storage_client-0.0.25-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f2acc15b7987f58df609f8bb60abd02753233b440914fb42fa4456cf07126ba1", size = 1945474, upload-time = "2026-05-05T17:18:05.736Z" },
725
+ { url = "https://files.pythonhosted.org/packages/55/71/720452bb2ac7ac2943d112ffc23530eb088585a90cebec40b1f832ec4fab/object_storage_client-0.0.25-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6343bd4b63e8e7e2facf4bbd1f7227ad6b27e242be273dfbe7e60e89ae70dca0", size = 2133158, upload-time = "2026-05-05T17:17:58.554Z" },
726
+ { url = "https://files.pythonhosted.org/packages/27/84/aab307d9bc79ac48ae32b9f6fc0d644a4e577281e0583a9ac3802106def3/object_storage_client-0.0.25-cp314-cp314-win_amd64.whl", hash = "sha256:d9564f446849aa5c8d4e11bfbe9050909a1b61a7932618f5865a7c1224cf3b4f", size = 2131352, upload-time = "2026-05-05T17:17:59.937Z" },
727
727
  ]
728
728
 
729
729
  [[package]]
@@ -737,11 +737,11 @@ wheels = [
737
737
 
738
738
  [[package]]
739
739
  name = "pip"
740
- version = "26.1"
740
+ version = "26.1.1"
741
741
  source = { registry = "https://pypi.org/simple" }
742
- sdist = { url = "https://files.pythonhosted.org/packages/73/7e/d2b04004e1068ad4fdfa2f227b839b5d03e602e47cdbbf49de71137c9546/pip-26.1.tar.gz", hash = "sha256:81e13ebcca3ffa8cc85e4deff5c27e1ee26dea0aa7fc2f294a073ac208806ff3", size = 1840316, upload-time = "2026-04-26T21:00:05.406Z" }
742
+ sdist = { url = "https://files.pythonhosted.org/packages/b6/48/cb9b7a682f6fe01a4221e1728941dd4ac3cd9090a17db3779d6ff490b602/pip-26.1.1.tar.gz", hash = "sha256:d36762751d156a4ee895de8af39aa0abeeeb577f93a2eca6ab62467bbf0f8a78", size = 1840400, upload-time = "2026-05-04T19:02:21.248Z" }
743
743
  wheels = [
744
- { url = "https://files.pythonhosted.org/packages/70/7a/be4bd8bcbb24ea475856dd68159d78b03b2bb53dae369f69c9606b8888f5/pip-26.1-py3-none-any.whl", hash = "sha256:4e8486d821d814b77319acb7b9e8bf5a4ee7590a643e7cb21029f209be8573c1", size = 1812804, upload-time = "2026-04-26T21:00:03.194Z" },
744
+ { url = "https://files.pythonhosted.org/packages/3a/eb/fea4d1d51c49832120f7f285d07306db3960f423a2612c6057caf3e8196f/pip-26.1.1-py3-none-any.whl", hash = "sha256:99cb1c2899893b075ff56e4ed0af55669a955b49ad7fb8d8603ecdaf4ed653fb", size = 1812777, upload-time = "2026-05-04T19:02:18.9Z" },
745
745
  ]
746
746
 
747
747
  [[package]]
@@ -1017,15 +1017,15 @@ wheels = [
1017
1017
 
1018
1018
  [[package]]
1019
1019
  name = "python-discovery"
1020
- version = "1.2.2"
1020
+ version = "1.3.0"
1021
1021
  source = { registry = "https://pypi.org/simple" }
1022
1022
  dependencies = [
1023
1023
  { name = "filelock" },
1024
1024
  { name = "platformdirs" },
1025
1025
  ]
1026
- sdist = { url = "https://files.pythonhosted.org/packages/de/ef/3bae0e537cfe91e8431efcba4434463d2c5a65f5a89edd47c6cf2f03c55f/python_discovery-1.2.2.tar.gz", hash = "sha256:876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb", size = 58872, upload-time = "2026-04-07T17:28:49.249Z" }
1026
+ sdist = { url = "https://files.pythonhosted.org/packages/ae/e0/cc5a8653e9a24f6cf84768f05064aa8ed5a83dcefd5e2a043db14a1c5f44/python_discovery-1.3.0.tar.gz", hash = "sha256:d098f1e86be5d45fe4d14bf1029294aabbd332f4321179dec85e76cddce834b0", size = 63925, upload-time = "2026-05-05T14:38:39.769Z" }
1027
1027
  wheels = [
1028
- { url = "https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl", hash = "sha256:e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a", size = 31894, upload-time = "2026-04-07T17:28:48.09Z" },
1028
+ { url = "https://files.pythonhosted.org/packages/30/d4/24d543ab8b8158b7f5a97113c831205f5c900c92c8762b1e7f44b7ea0405/python_discovery-1.3.0-py3-none-any.whl", hash = "sha256:441d9ced3dfce36e113beb35ca302c71c7ef06f3c0f9c227a0b9bb3bd49b9e9f", size = 33124, upload-time = "2026-05-05T14:38:38.539Z" },
1029
1029
  ]
1030
1030
 
1031
1031
  [[package]]
@@ -1123,7 +1123,7 @@ testing = [
1123
1123
 
1124
1124
  [package.metadata]
1125
1125
  requires-dist = [
1126
- { name = "aiobotocore", marker = "extra == 'object-storage'", specifier = "~=3.5.0" },
1126
+ { name = "aiobotocore", marker = "extra == 'object-storage'", specifier = "~=3.6.0" },
1127
1127
  { name = "aiohttp", extras = ["speedups"], marker = "extra == 'api-client'", specifier = ">=3.13.5,<3.15.0" },
1128
1128
  { name = "aiohttp", extras = ["speedups"], marker = "extra == 'authn'", specifier = ">=3.13.5,<3.15.0" },
1129
1129
  { name = "aiohttp", extras = ["speedups"], marker = "extra == 'soap-client'", specifier = ">=3.13.5,<3.15.0" },
@@ -1135,7 +1135,7 @@ requires-dist = [
1135
1135
  { name = "lxml", marker = "extra == 'soap-client'", specifier = "~=6.1.0" },
1136
1136
  { name = "msgpack", specifier = "~=1.1.2" },
1137
1137
  { name = "msgspec", specifier = "==0.21.1" },
1138
- { name = "object-storage-client", marker = "extra == 'object-storage'", specifier = "==0.0.23" },
1138
+ { name = "object-storage-client", marker = "extra == 'object-storage'", specifier = "==0.0.25" },
1139
1139
  { name = "pydantic-settings", specifier = "~=2.14.0" },
1140
1140
  { name = "python3-commons", extras = ["api-client"], marker = "extra == 'authn'" },
1141
1141
  { name = "python3-commons", extras = ["api-client"], marker = "extra == 'authz'" },
@@ -1170,11 +1170,11 @@ testing = [
1170
1170
 
1171
1171
  [[package]]
1172
1172
  name = "pytz"
1173
- version = "2026.1.post1"
1173
+ version = "2026.2"
1174
1174
  source = { registry = "https://pypi.org/simple" }
1175
- sdist = { url = "https://files.pythonhosted.org/packages/56/db/b8721d71d945e6a8ac63c0fc900b2067181dbb50805958d4d4661cf7d277/pytz-2026.1.post1.tar.gz", hash = "sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1", size = 321088, upload-time = "2026-03-03T07:47:50.683Z" }
1175
+ sdist = { url = "https://files.pythonhosted.org/packages/ff/46/dd499ec9038423421951e4fad73051febaa13d2df82b4064f87af8b8c0c3/pytz-2026.2.tar.gz", hash = "sha256:0e60b47b29f21574376f218fe21abc009894a2321ea16c6754f3cad6eb7cdd6a", size = 320861, upload-time = "2026-05-04T01:35:29.667Z" }
1176
1176
  wheels = [
1177
- { url = "https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl", hash = "sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a", size = 510489, upload-time = "2026-03-03T07:47:49.167Z" },
1177
+ { url = "https://files.pythonhosted.org/packages/ec/dd/96da98f892250475bdf2328112d7468abdd4acc7b902b6af23f4ed958ea0/pytz-2026.2-py2.py3-none-any.whl", hash = "sha256:04156e608bee23d3792fd45c94ae47fae1036688e75032eea2e3bf0323d1f126", size = 510141, upload-time = "2026-05-04T01:35:27.408Z" },
1178
1178
  ]
1179
1179
 
1180
1180
  [[package]]
@@ -1307,14 +1307,14 @@ asyncio = [
1307
1307
 
1308
1308
  [[package]]
1309
1309
  name = "types-aiobotocore"
1310
- version = "3.5.0"
1310
+ version = "3.6.0"
1311
1311
  source = { registry = "https://pypi.org/simple" }
1312
1312
  dependencies = [
1313
1313
  { name = "botocore-stubs" },
1314
1314
  ]
1315
- sdist = { url = "https://files.pythonhosted.org/packages/d5/99/3863acdc373aa621cf56634bb08145fb54f2213e647d893c1ac7b2636c11/types_aiobotocore-3.5.0.tar.gz", hash = "sha256:8636c9e5a9837d41e45264570349d98c0cdad51fe7961ee19664a11094bb2262", size = 87983, upload-time = "2026-04-23T02:57:02.576Z" }
1315
+ sdist = { url = "https://files.pythonhosted.org/packages/b9/e4/5dd83c879eff726931ef222d3ae27f67999c3bc33dfae1ca8237ebccdf17/types_aiobotocore-3.6.0.tar.gz", hash = "sha256:e990056ce9d19094a9d9b36008ca0b2a4d69948ff58f50868dd159a81f6ad69c", size = 87978, upload-time = "2026-05-02T03:05:30.694Z" }
1316
1316
  wheels = [
1317
- { url = "https://files.pythonhosted.org/packages/ed/d7/2b2d4d5b64b81149b08cc3fde6e826788c703c012b687cd4cc4d83742afd/types_aiobotocore-3.5.0-py3-none-any.whl", hash = "sha256:7c75ff73c10098d1d885e5b061f05945afdc4e9d0d5b573274292c329abe8a62", size = 54805, upload-time = "2026-04-23T02:56:59.721Z" },
1317
+ { url = "https://files.pythonhosted.org/packages/19/7c/cadd4b4d0bdd6f1cbc601177a115966dabd9afa022287f3f25423274ab97/types_aiobotocore-3.6.0-py3-none-any.whl", hash = "sha256:e38d5340bfb7ecc17a40acfd1043f4ed91af9f8189daa5e438bda2e7d276d406", size = 54805, upload-time = "2026-05-02T03:05:27.911Z" },
1318
1318
  ]
1319
1319
 
1320
1320
  [package.optional-dependencies]
@@ -1324,11 +1324,11 @@ s3 = [
1324
1324
 
1325
1325
  [[package]]
1326
1326
  name = "types-aiobotocore-s3"
1327
- version = "3.5.0"
1327
+ version = "3.6.0"
1328
1328
  source = { registry = "https://pypi.org/simple" }
1329
- sdist = { url = "https://files.pythonhosted.org/packages/2d/6b/0d9fd45a69afbd2007480a35e8612121f6e27b988741b3a6d0b05c964229/types_aiobotocore_s3-3.5.0.tar.gz", hash = "sha256:147e2128be67de8c8a33b8a9bcca5fa8e963c6c54e52c58c17fa5c6013195a5a", size = 77175, upload-time = "2026-04-23T02:54:40.652Z" }
1329
+ sdist = { url = "https://files.pythonhosted.org/packages/66/90/eec276a418a417441a785dd394424fee87682cf34af29fe026f46883149e/types_aiobotocore_s3-3.6.0.tar.gz", hash = "sha256:5eb816af93791b7f42f58b2dd3b5ecfe24da9de414a7390c05c392cf1d9ef5b4", size = 77715, upload-time = "2026-05-02T03:03:31.274Z" }
1330
1330
  wheels = [
1331
- { url = "https://files.pythonhosted.org/packages/3b/c4/ce16af65a9227fe0ff3e737c0b4317e138fffbd06f7d631fe3a1b5a7f0f3/types_aiobotocore_s3-3.5.0-py3-none-any.whl", hash = "sha256:6fc53a6da5ec5cfb5478197fca74e1d11c389e0e20df7c0e0006a84c56224ada", size = 84930, upload-time = "2026-04-23T02:54:36.283Z" },
1331
+ { url = "https://files.pythonhosted.org/packages/e7/df/4f2dce96e6b71f3d8287351558824021a9857eb88506c6eb72c61b23bcb4/types_aiobotocore_s3-3.6.0-py3-none-any.whl", hash = "sha256:5af9f9710c9fe6ba9645852a0b13f6fca4eb44d87a35b0959063341a32f11b37", size = 85450, upload-time = "2026-05-02T03:03:29.054Z" },
1332
1332
  ]
1333
1333
 
1334
1334
  [[package]]
@@ -1398,7 +1398,7 @@ wheels = [
1398
1398
 
1399
1399
  [[package]]
1400
1400
  name = "virtualenv"
1401
- version = "21.3.0"
1401
+ version = "21.3.1"
1402
1402
  source = { registry = "https://pypi.org/simple" }
1403
1403
  dependencies = [
1404
1404
  { name = "distlib" },
@@ -1406,9 +1406,9 @@ dependencies = [
1406
1406
  { name = "platformdirs" },
1407
1407
  { name = "python-discovery" },
1408
1408
  ]
1409
- sdist = { url = "https://files.pythonhosted.org/packages/3f/8b/6331f7a7fe70131c301106ec1e7cf23e2501bf7d4ca3636805801ca191bb/virtualenv-21.3.0.tar.gz", hash = "sha256:733750db978ec95c2d8eb4feadaa57091002bce404cb39ba69899cf7bd28944e", size = 7614069, upload-time = "2026-04-27T17:05:58.927Z" }
1409
+ sdist = { url = "https://files.pythonhosted.org/packages/ec/0d/915c02c94d207b85580eb09bffab54438a709e7288524094fe781da526c2/virtualenv-21.3.1.tar.gz", hash = "sha256:c2305bc1fddeec40699b8370d13f8d431b0701f00ce895061ce493aeded4426b", size = 7613791, upload-time = "2026-05-05T01:34:31.402Z" }
1410
1410
  wheels = [
1411
- { url = "https://files.pythonhosted.org/packages/4b/eb/03bfb1299d4c4510329e470f13f9a4ce793df7fcb5a2fd3510f911066f61/virtualenv-21.3.0-py3-none-any.whl", hash = "sha256:4d28ee41f6d9ec8f1f00cd472b9ffbcedda1b3d3b9a575b5c94a2d004fd51bd7", size = 7594690, upload-time = "2026-04-27T17:05:55.468Z" },
1411
+ { url = "https://files.pythonhosted.org/packages/b1/4f/f71e641e504111a5a74e3a20bc52d01bd86788b22699dd3fee1c63253cf6/virtualenv-21.3.1-py3-none-any.whl", hash = "sha256:d1a71cf58f2f9228fff23a1f6ec15d39785c6b32e03658d104974247145edd35", size = 7594539, upload-time = "2026-05-05T01:34:28.98Z" },
1412
1412
  ]
1413
1413
 
1414
1414
  [[package]]