python3-commons 0.15.21__tar.gz → 0.16.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.
- {python3_commons-0.15.21 → python3_commons-0.16.1}/PKG-INFO +4 -3
- {python3_commons-0.15.21 → python3_commons-0.16.1}/pyproject.toml +3 -2
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/audit.py +1 -3
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/db/__init__.py +13 -13
- python3_commons-0.16.1/src/python3_commons/log/formatters.py +118 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/object_storage.py +29 -11
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons.egg-info/PKG-INFO +4 -3
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons.egg-info/requires.txt +3 -2
- {python3_commons-0.15.21 → python3_commons-0.16.1}/uv.lock +44 -19
- python3_commons-0.15.21/src/python3_commons/log/formatters.py +0 -35
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.coveragerc +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.devcontainer/Dockerfile +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.devcontainer/devcontainer.json +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.devcontainer/docker-compose.yml +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.env_template +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.github/workflows/checks.yml +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.github/workflows/python-publish.yaml +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.github/workflows/release-on-tag-push.yml +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.gitignore +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.pre-commit-config.yaml +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/.python-version +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/AUTHORS.rst +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/CHANGELOG.rst +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/LICENSE +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/README.md +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/README.rst +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/docs/Makefile +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/docs/_static/.gitignore +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/docs/authors.rst +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/docs/changelog.rst +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/docs/conf.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/docs/index.rst +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/docs/license.rst +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/setup.cfg +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/__init__.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/api_client.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/async_functools.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/auth.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/cache.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/conf.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/db/helpers.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/db/models/__init__.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/db/models/auth.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/db/models/common.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/db/models/rbac.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/db/models/users.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/exceptions.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/fs.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/generators.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/helpers.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/log/__init__.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/log/filters.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/permissions.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/serializers/__init__.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/serializers/common.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/serializers/json.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/serializers/msgpack.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/serializers/msgspec.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons.egg-info/SOURCES.txt +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons.egg-info/dependency_links.txt +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons.egg-info/top_level.txt +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/__init__.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/integration/__init__.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/integration/test_cache.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/integration/test_osc.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/unit/__init__.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/unit/conftest.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/unit/log/__init__.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/unit/log/test_formatters.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/unit/test_async_functools.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/unit/test_audit.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/unit/test_helpers.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/tests/unit/test_msgpack.py +0 -0
- {python3_commons-0.15.21 → python3_commons-0.16.1}/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.
|
|
3
|
+
Version: 0.16.1
|
|
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
|
|
@@ -12,13 +12,14 @@ Requires-Python: <3.15.0,>=3.14.4
|
|
|
12
12
|
Description-Content-Type: text/x-rst
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
License-File: AUTHORS.rst
|
|
15
|
-
Requires-Dist: aiobotocore~=3.
|
|
15
|
+
Requires-Dist: aiobotocore~=3.5.0
|
|
16
16
|
Requires-Dist: aiohttp[speedups]<3.15.0,>=3.13.5
|
|
17
17
|
Requires-Dist: asyncpg~=0.31.0
|
|
18
18
|
Requires-Dist: lxml~=6.1.0
|
|
19
19
|
Requires-Dist: msgpack~=1.1.2
|
|
20
20
|
Requires-Dist: msgspec==0.21.1
|
|
21
|
-
Requires-Dist: object-storage-client==0.0.
|
|
21
|
+
Requires-Dist: object-storage-client==0.0.22
|
|
22
|
+
Requires-Dist: orjson==3.11.8
|
|
22
23
|
Requires-Dist: pydantic-settings~=2.14.0
|
|
23
24
|
Requires-Dist: SQLAlchemy[asyncio]~=2.0.49
|
|
24
25
|
Requires-Dist: valkey[libvalkey]~=6.1.1
|
|
@@ -18,13 +18,14 @@ classifiers = [
|
|
|
18
18
|
keywords = []
|
|
19
19
|
requires-python = ">=3.14.4,<3.15.0"
|
|
20
20
|
dependencies = [
|
|
21
|
-
"aiobotocore~=3.
|
|
21
|
+
"aiobotocore~=3.5.0",
|
|
22
22
|
"aiohttp[speedups]>=3.13.5,<3.15.0",
|
|
23
23
|
"asyncpg~=0.31.0",
|
|
24
24
|
"lxml~=6.1.0",
|
|
25
25
|
"msgpack~=1.1.2",
|
|
26
26
|
"msgspec==0.21.1",
|
|
27
|
-
"object-storage-client==0.0.
|
|
27
|
+
"object-storage-client==0.0.22",
|
|
28
|
+
"orjson==3.11.8",
|
|
28
29
|
"pydantic-settings~=2.14.0",
|
|
29
30
|
"SQLAlchemy[asyncio]~=2.0.49",
|
|
30
31
|
"valkey[libvalkey]~=6.1.1",
|
|
@@ -20,9 +20,7 @@ logger = logging.getLogger(__name__)
|
|
|
20
20
|
async def write_audit_data(settings: S3Settings, key: str, data: bytes) -> None:
|
|
21
21
|
if settings.aws_secret_access_key:
|
|
22
22
|
try:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
await object_storage.put_object(settings.s3_bucket, absolute_path, io.BytesIO(data), len(data))
|
|
23
|
+
await object_storage.put_object(settings.s3_bucket, f'audit/{key}', io.BytesIO(data), len(data))
|
|
26
24
|
except Exception:
|
|
27
25
|
logger.exception('Failed storing object in storage.')
|
|
28
26
|
else:
|
|
@@ -17,28 +17,28 @@ Base = declarative_base(metadata=metadata)
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class AsyncSessionManager:
|
|
20
|
-
def __init__(self,
|
|
21
|
-
self.
|
|
20
|
+
def __init__(self, db_configs: Mapping[str, DBSettings]) -> None:
|
|
21
|
+
self.db_configs: Mapping[str, DBSettings] = db_configs
|
|
22
22
|
self.engines: dict[str, AsyncEngine] = {}
|
|
23
23
|
self.session_makers: dict = {}
|
|
24
24
|
|
|
25
|
-
def
|
|
25
|
+
def get_db_config(self, name: str) -> DBSettings:
|
|
26
26
|
try:
|
|
27
|
-
return self.
|
|
27
|
+
return self.db_configs[name]
|
|
28
28
|
except KeyError:
|
|
29
29
|
logger.exception('Missing database settings: %s', name)
|
|
30
30
|
|
|
31
31
|
raise
|
|
32
32
|
|
|
33
|
-
def
|
|
34
|
-
|
|
33
|
+
def async_engine_from_db_config(self, name):
|
|
34
|
+
db_config = self.get_db_config(name)
|
|
35
35
|
configuration = {
|
|
36
|
-
'url': str(
|
|
37
|
-
'echo':
|
|
38
|
-
'pool_size':
|
|
39
|
-
'max_overflow':
|
|
40
|
-
'pool_timeout':
|
|
41
|
-
'pool_recycle':
|
|
36
|
+
'url': str(db_config.dsn),
|
|
37
|
+
'echo': db_config.echo,
|
|
38
|
+
'pool_size': db_config.pool_size,
|
|
39
|
+
'max_overflow': db_config.max_overflow,
|
|
40
|
+
'pool_timeout': db_config.pool_timeout,
|
|
41
|
+
'pool_recycle': db_config.pool_recycle,
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
return async_engine_from_config(configuration, prefix='')
|
|
@@ -48,7 +48,7 @@ class AsyncSessionManager:
|
|
|
48
48
|
engine = self.engines[name]
|
|
49
49
|
except KeyError:
|
|
50
50
|
logger.debug('Creating engine: %s', name)
|
|
51
|
-
engine = self.
|
|
51
|
+
engine = self.async_engine_from_db_config(name)
|
|
52
52
|
self.engines[name] = engine
|
|
53
53
|
|
|
54
54
|
return engine
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import traceback
|
|
3
|
+
from contextvars import ContextVar
|
|
4
|
+
from datetime import UTC, datetime, date
|
|
5
|
+
from decimal import Decimal
|
|
6
|
+
from typing import Any, Final, Callable
|
|
7
|
+
|
|
8
|
+
import orjson
|
|
9
|
+
|
|
10
|
+
correlation_id: ContextVar[str | None] = ContextVar('correlation_id', default=None)
|
|
11
|
+
|
|
12
|
+
_DEFAULT_MAX_TB_CHARS: Final[int] = 8_000
|
|
13
|
+
_STD_LOG_FIELDS: Final[frozenset[str]] = frozenset(
|
|
14
|
+
{
|
|
15
|
+
'msg',
|
|
16
|
+
'args',
|
|
17
|
+
'levelname',
|
|
18
|
+
'levelno',
|
|
19
|
+
'pathname',
|
|
20
|
+
'filename',
|
|
21
|
+
'module',
|
|
22
|
+
'exc_info',
|
|
23
|
+
'exc_text',
|
|
24
|
+
'stack_info',
|
|
25
|
+
'lineno',
|
|
26
|
+
'funcName',
|
|
27
|
+
'created',
|
|
28
|
+
'msecs',
|
|
29
|
+
'relativeCreated',
|
|
30
|
+
'thread',
|
|
31
|
+
'threadName',
|
|
32
|
+
'process',
|
|
33
|
+
'processName',
|
|
34
|
+
'name',
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Keep normalization minimal and branch-based (faster than dict dispatch)
|
|
40
|
+
def _normalize(v: Any) -> Any:
|
|
41
|
+
if isinstance(v, datetime | date):
|
|
42
|
+
return v.isoformat()
|
|
43
|
+
|
|
44
|
+
if isinstance(v, bytes):
|
|
45
|
+
return v.decode('utf-8', errors='replace')
|
|
46
|
+
|
|
47
|
+
if isinstance(v, Decimal):
|
|
48
|
+
return str(v)
|
|
49
|
+
|
|
50
|
+
if isinstance(v, Exception):
|
|
51
|
+
return str(v)
|
|
52
|
+
|
|
53
|
+
return v
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class JSONFormatter(logging.Formatter):
|
|
57
|
+
__slots__ = ('_get_correlation_id', '_max_tb_chars')
|
|
58
|
+
|
|
59
|
+
def __init__(
|
|
60
|
+
self,
|
|
61
|
+
*,
|
|
62
|
+
get_correlation_id: Callable[[], str | None] = lambda: correlation_id.get(),
|
|
63
|
+
max_exc_tb_chars: int = _DEFAULT_MAX_TB_CHARS,
|
|
64
|
+
**kwargs: Any,
|
|
65
|
+
) -> None:
|
|
66
|
+
super().__init__(**kwargs)
|
|
67
|
+
self._get_correlation_id = get_correlation_id
|
|
68
|
+
self._max_tb_chars = max_exc_tb_chars
|
|
69
|
+
|
|
70
|
+
def format(self, record: logging.LogRecord) -> str:
|
|
71
|
+
# --- message (fast path, avoid Formatter.formatMessage) ---
|
|
72
|
+
try:
|
|
73
|
+
message = record.getMessage()
|
|
74
|
+
except Exception:
|
|
75
|
+
message = str(record.msg)
|
|
76
|
+
|
|
77
|
+
# --- timestamp (no Formatter.formatTime overhead) ---
|
|
78
|
+
timestamp = datetime.fromtimestamp(record.created, UTC).isoformat().replace('+00:00', 'Z')
|
|
79
|
+
|
|
80
|
+
log: dict[str, Any] = {
|
|
81
|
+
'message': message,
|
|
82
|
+
'level': record.levelname,
|
|
83
|
+
'logger': record.name,
|
|
84
|
+
'timestamp': timestamp,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (corr_id := self._get_correlation_id()) is not None:
|
|
88
|
+
log['correlation_id'] = corr_id
|
|
89
|
+
|
|
90
|
+
if (exc_info := record.exc_info) and exc_info[0] is not None:
|
|
91
|
+
exc_type, exc_value, exc_tb = exc_info
|
|
92
|
+
|
|
93
|
+
log['exc_type'] = f'{exc_type.__module__}.{exc_type.__qualname__}'
|
|
94
|
+
log['exc_value'] = str(exc_value)
|
|
95
|
+
|
|
96
|
+
tb = ''.join(traceback.format_exception(exc_type, exc_value, exc_tb)).rstrip()
|
|
97
|
+
|
|
98
|
+
cap = self._max_tb_chars
|
|
99
|
+
|
|
100
|
+
if cap and len(tb) > cap:
|
|
101
|
+
tb = tb[:cap] + '\n... <truncated>'
|
|
102
|
+
|
|
103
|
+
log['exc_traceback'] = tb
|
|
104
|
+
|
|
105
|
+
record_dict = record.__dict__
|
|
106
|
+
std_log_fields = _STD_LOG_FIELDS
|
|
107
|
+
|
|
108
|
+
if len(record_dict) > len(std_log_fields):
|
|
109
|
+
normalize = _normalize
|
|
110
|
+
out_set = log.__setitem__
|
|
111
|
+
|
|
112
|
+
for k, v in record_dict.items():
|
|
113
|
+
if k[0] == '_' or k in std_log_fields:
|
|
114
|
+
continue
|
|
115
|
+
|
|
116
|
+
out_set(k, normalize(v))
|
|
117
|
+
|
|
118
|
+
return orjson.dumps(log).decode('utf-8')
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import threading
|
|
4
5
|
from contextlib import asynccontextmanager
|
|
5
6
|
from typing import TYPE_CHECKING
|
|
6
7
|
|
|
7
8
|
import aiobotocore.session
|
|
8
9
|
from botocore.config import Config
|
|
10
|
+
from object_storage_client import ObjectStorageClient
|
|
9
11
|
|
|
10
12
|
if TYPE_CHECKING:
|
|
11
13
|
import io
|
|
@@ -19,6 +21,22 @@ from python3_commons.conf import S3Settings, s3_settings
|
|
|
19
21
|
from python3_commons.helpers import SingletonMeta
|
|
20
22
|
|
|
21
23
|
logger = logging.getLogger(__name__)
|
|
24
|
+
_CLIENT: ObjectStorageClient | None = None
|
|
25
|
+
_CLIENT_LOCK = threading.Lock()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_client() -> ObjectStorageClient:
|
|
29
|
+
global _CLIENT # noqa: PLW0603
|
|
30
|
+
|
|
31
|
+
if not _CLIENT:
|
|
32
|
+
with _CLIENT_LOCK:
|
|
33
|
+
if not _CLIENT:
|
|
34
|
+
client = ObjectStorageClient()
|
|
35
|
+
_CLIENT = client
|
|
36
|
+
else:
|
|
37
|
+
client = _CLIENT
|
|
38
|
+
|
|
39
|
+
return client
|
|
22
40
|
|
|
23
41
|
|
|
24
42
|
class ObjectStorage(metaclass=SingletonMeta):
|
|
@@ -58,21 +76,21 @@ def get_absolute_path(path: str) -> str:
|
|
|
58
76
|
|
|
59
77
|
|
|
60
78
|
async def put_object(bucket_name: str, path: str, data: io.BytesIO, length: int, part_size: int = 0) -> str | None:
|
|
61
|
-
|
|
79
|
+
try:
|
|
80
|
+
client = get_client()
|
|
81
|
+
data.seek(0)
|
|
82
|
+
absolute_path = get_absolute_path(path)
|
|
83
|
+
url = f's3://{bucket_name}/{absolute_path}'
|
|
62
84
|
|
|
63
|
-
|
|
64
|
-
try:
|
|
65
|
-
data.seek(0)
|
|
85
|
+
await client.put_object(url, data.getvalue())
|
|
66
86
|
|
|
67
|
-
|
|
87
|
+
logger.debug('Stored object into object storage: %s:%s', bucket_name, path)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
logger.exception('Failed to put object to object storage: %s:%s', bucket_name, path, exc_info=e)
|
|
68
90
|
|
|
69
|
-
|
|
70
|
-
except Exception as e:
|
|
71
|
-
logger.exception('Failed to put object to object storage: %s:%s', bucket_name, path, exc_info=e)
|
|
72
|
-
|
|
73
|
-
raise
|
|
91
|
+
raise
|
|
74
92
|
|
|
75
|
-
|
|
93
|
+
return f's3://{bucket_name}/{path}'
|
|
76
94
|
|
|
77
95
|
|
|
78
96
|
@asynccontextmanager
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python3-commons
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.1
|
|
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
|
|
@@ -12,13 +12,14 @@ Requires-Python: <3.15.0,>=3.14.4
|
|
|
12
12
|
Description-Content-Type: text/x-rst
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
License-File: AUTHORS.rst
|
|
15
|
-
Requires-Dist: aiobotocore~=3.
|
|
15
|
+
Requires-Dist: aiobotocore~=3.5.0
|
|
16
16
|
Requires-Dist: aiohttp[speedups]<3.15.0,>=3.13.5
|
|
17
17
|
Requires-Dist: asyncpg~=0.31.0
|
|
18
18
|
Requires-Dist: lxml~=6.1.0
|
|
19
19
|
Requires-Dist: msgpack~=1.1.2
|
|
20
20
|
Requires-Dist: msgspec==0.21.1
|
|
21
|
-
Requires-Dist: object-storage-client==0.0.
|
|
21
|
+
Requires-Dist: object-storage-client==0.0.22
|
|
22
|
+
Requires-Dist: orjson==3.11.8
|
|
22
23
|
Requires-Dist: pydantic-settings~=2.14.0
|
|
23
24
|
Requires-Dist: SQLAlchemy[asyncio]~=2.0.49
|
|
24
25
|
Requires-Dist: valkey[libvalkey]~=6.1.1
|
{python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons.egg-info/requires.txt
RENAMED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
aiobotocore~=3.
|
|
1
|
+
aiobotocore~=3.5.0
|
|
2
2
|
aiohttp[speedups]<3.15.0,>=3.13.5
|
|
3
3
|
asyncpg~=0.31.0
|
|
4
4
|
lxml~=6.1.0
|
|
5
5
|
msgpack~=1.1.2
|
|
6
6
|
msgspec==0.21.1
|
|
7
|
-
object-storage-client==0.0.
|
|
7
|
+
object-storage-client==0.0.22
|
|
8
|
+
orjson==3.11.8
|
|
8
9
|
pydantic-settings~=2.14.0
|
|
9
10
|
SQLAlchemy[asyncio]~=2.0.49
|
|
10
11
|
valkey[libvalkey]~=6.1.1
|
|
@@ -4,7 +4,7 @@ requires-python = ">=3.14.4, <3.15.0"
|
|
|
4
4
|
|
|
5
5
|
[[package]]
|
|
6
6
|
name = "aiobotocore"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.5.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/
|
|
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" }
|
|
19
19
|
wheels = [
|
|
20
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
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" },
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
[[package]]
|
|
@@ -164,16 +164,16 @@ wheels = [
|
|
|
164
164
|
|
|
165
165
|
[[package]]
|
|
166
166
|
name = "botocore"
|
|
167
|
-
version = "1.42.
|
|
167
|
+
version = "1.42.91"
|
|
168
168
|
source = { registry = "https://pypi.org/simple" }
|
|
169
169
|
dependencies = [
|
|
170
170
|
{ name = "jmespath" },
|
|
171
171
|
{ name = "python-dateutil" },
|
|
172
172
|
{ name = "urllib3" },
|
|
173
173
|
]
|
|
174
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
174
|
+
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" }
|
|
175
175
|
wheels = [
|
|
176
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
176
|
+
{ 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" },
|
|
177
177
|
]
|
|
178
178
|
|
|
179
179
|
[[package]]
|
|
@@ -478,11 +478,11 @@ wheels = [
|
|
|
478
478
|
|
|
479
479
|
[[package]]
|
|
480
480
|
name = "idna"
|
|
481
|
-
version = "3.
|
|
481
|
+
version = "3.12"
|
|
482
482
|
source = { registry = "https://pypi.org/simple" }
|
|
483
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
483
|
+
sdist = { url = "https://files.pythonhosted.org/packages/22/12/2948fbe5513d062169bd91f7d7b1cd97bc8894f32946b71fa39f6e63ca0c/idna-3.12.tar.gz", hash = "sha256:724e9952cc9e2bd7550ea784adb098d837ab5267ef67a1ab9cf7846bdbdd8254", size = 194350, upload-time = "2026-04-21T13:32:48.916Z" }
|
|
484
484
|
wheels = [
|
|
485
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
485
|
+
{ url = "https://files.pythonhosted.org/packages/53/b2/acc33950394b3becb2b664741a0c0889c7ef9f9ffbfa8d47eddb53a50abd/idna-3.12-py3-none-any.whl", hash = "sha256:60ffaa1858fac94c9c124728c24fcde8160f3fb4a7f79aa8cdd33a9d1af60a67", size = 68634, upload-time = "2026-04-21T13:32:47.403Z" },
|
|
486
486
|
]
|
|
487
487
|
|
|
488
488
|
[[package]]
|
|
@@ -668,13 +668,36 @@ wheels = [
|
|
|
668
668
|
|
|
669
669
|
[[package]]
|
|
670
670
|
name = "object-storage-client"
|
|
671
|
-
version = "0.0.
|
|
671
|
+
version = "0.0.22"
|
|
672
|
+
source = { registry = "https://pypi.org/simple" }
|
|
673
|
+
sdist = { url = "https://files.pythonhosted.org/packages/1a/49/9af56487b380cef1132c1aa718702095a0ab3ddb3e82bb4eab9593dde316/object_storage_client-0.0.22.tar.gz", hash = "sha256:00535617e1f50c0dab066e7dc6bdc9d1690e989febcfaacc27737988dd5a4101", size = 40622, upload-time = "2026-04-21T12:36:41.782Z" }
|
|
674
|
+
wheels = [
|
|
675
|
+
{ url = "https://files.pythonhosted.org/packages/e3/0b/c9a4dc7ae9bc8f67877190d97c0efb94a0a9e7aef6423feaa45d93232215/object_storage_client-0.0.22-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:db7d843f11e1d281ba16533bc573343ec9e0a8d2cf779cd43464df6adca0a5a8", size = 1922610, upload-time = "2026-04-21T12:36:40.278Z" },
|
|
676
|
+
{ url = "https://files.pythonhosted.org/packages/7e/f3/3e34cc1e70e9f48ad0be5d7af1771d864a3ee618c07aad43978e2d3a131c/object_storage_client-0.0.22-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d7c92c2ca19f9d734be99162df7dc573535e7022e5a9b5c1dce121a102a85ae", size = 2114290, upload-time = "2026-04-21T12:36:37.82Z" },
|
|
677
|
+
{ url = "https://files.pythonhosted.org/packages/ee/73/4af6bf9dc086e9c0a69988d2258d2f6f5d02d00ef891d9df3d6d08c3355a/object_storage_client-0.0.22-cp314-cp314-win_amd64.whl", hash = "sha256:df863a2a3f8f1c77d06bdc547d674b321878dca7cb7db94606b763cb9cc7e508", size = 2095414, upload-time = "2026-04-21T12:36:38.966Z" },
|
|
678
|
+
]
|
|
679
|
+
|
|
680
|
+
[[package]]
|
|
681
|
+
name = "orjson"
|
|
682
|
+
version = "3.11.8"
|
|
672
683
|
source = { registry = "https://pypi.org/simple" }
|
|
673
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
684
|
+
sdist = { url = "https://files.pythonhosted.org/packages/9d/1b/2024d06792d0779f9dbc51531b61c24f76c75b9f4ce05e6f3377a1814cea/orjson-3.11.8.tar.gz", hash = "sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e", size = 5603832, upload-time = "2026-03-31T16:16:27.878Z" }
|
|
674
685
|
wheels = [
|
|
675
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
676
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
677
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
686
|
+
{ url = "https://files.pythonhosted.org/packages/6d/35/b01910c3d6b85dc882442afe5060cbf719c7d1fc85749294beda23d17873/orjson-3.11.8-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ec795530a73c269a55130498842aaa762e4a939f6ce481a7e986eeaa790e9da4", size = 229171, upload-time = "2026-03-31T16:16:00.651Z" },
|
|
687
|
+
{ url = "https://files.pythonhosted.org/packages/c2/56/c9ec97bd11240abef39b9e5d99a15462809c45f677420fd148a6c5e6295e/orjson-3.11.8-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c492a0e011c0f9066e9ceaa896fbc5b068c54d365fea5f3444b697ee01bc8625", size = 128746, upload-time = "2026-03-31T16:16:02.673Z" },
|
|
688
|
+
{ url = "https://files.pythonhosted.org/packages/3b/e4/66d4f30a90de45e2f0cbd9623588e8ae71eef7679dbe2ae954ed6d66a41f/orjson-3.11.8-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:883206d55b1bd5f5679ad5e6ddd3d1a5e3cac5190482927fdb8c78fb699193b5", size = 131867, upload-time = "2026-03-31T16:16:04.342Z" },
|
|
689
|
+
{ url = "https://files.pythonhosted.org/packages/19/30/2a645fc9286b928675e43fa2a3a16fb7b6764aa78cc719dc82141e00f30b/orjson-3.11.8-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5774c1fdcc98b2259800b683b19599c133baeb11d60033e2095fd9d4667b82db", size = 124664, upload-time = "2026-03-31T16:16:05.837Z" },
|
|
690
|
+
{ url = "https://files.pythonhosted.org/packages/db/44/77b9a86d84a28d52ba3316d77737f6514e17118119ade3f91b639e859029/orjson-3.11.8-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7381c83dd3d4a6347e6635950aa448f54e7b8406a27c7ecb4a37e9f1ae08b", size = 129701, upload-time = "2026-03-31T16:16:07.407Z" },
|
|
691
|
+
{ url = "https://files.pythonhosted.org/packages/b3/ea/eff3d9bfe47e9bc6969c9181c58d9f71237f923f9c86a2d2f490cd898c82/orjson-3.11.8-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14439063aebcb92401c11afc68ee4e407258d2752e62d748b6942dad20d2a70d", size = 141202, upload-time = "2026-03-31T16:16:09.48Z" },
|
|
692
|
+
{ url = "https://files.pythonhosted.org/packages/52/c8/90d4b4c60c84d62068d0cf9e4d8f0a4e05e76971d133ac0c60d818d4db20/orjson-3.11.8-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa72e71977bff96567b0f500fc5bfd2fdf915f34052c782a4c6ebbdaa97aa858", size = 127194, upload-time = "2026-03-31T16:16:11.02Z" },
|
|
693
|
+
{ url = "https://files.pythonhosted.org/packages/8d/c7/ea9e08d1f0ba981adffb629811148b44774d935171e7b3d780ae43c4c254/orjson-3.11.8-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7679bc2f01bb0d219758f1a5f87bb7c8a81c0a186824a393b366876b4948e14f", size = 133639, upload-time = "2026-03-31T16:16:13.434Z" },
|
|
694
|
+
{ url = "https://files.pythonhosted.org/packages/6c/8c/ddbbfd6ba59453c8fc7fe1d0e5983895864e264c37481b2a791db635f046/orjson-3.11.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:14f7b8fcb35ef403b42fa5ecfa4ed032332a91f3dc7368fbce4184d59e1eae0d", size = 141914, upload-time = "2026-03-31T16:16:14.955Z" },
|
|
695
|
+
{ url = "https://files.pythonhosted.org/packages/4e/31/dbfbefec9df060d34ef4962cd0afcb6fa7a9ec65884cb78f04a7859526c3/orjson-3.11.8-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:c2bdf7b2facc80b5e34f48a2d557727d5c5c57a8a450de122ae81fa26a81c1bc", size = 423800, upload-time = "2026-03-31T16:16:16.594Z" },
|
|
696
|
+
{ url = "https://files.pythonhosted.org/packages/87/cf/f74e9ae9803d4ab46b163494adba636c6d7ea955af5cc23b8aaa94cfd528/orjson-3.11.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ccd7ba1b0605813a0715171d39ec4c314cb97a9c85893c2c5c0c3a3729df38bf", size = 147837, upload-time = "2026-03-31T16:16:18.585Z" },
|
|
697
|
+
{ url = "https://files.pythonhosted.org/packages/64/e6/9214f017b5db85e84e68602792f742e5dc5249e963503d1b356bee611e01/orjson-3.11.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cdbc8c9c02463fef4d3c53a9ba3336d05496ec8e1f1c53326a1e4acc11f5c600", size = 136441, upload-time = "2026-03-31T16:16:20.151Z" },
|
|
698
|
+
{ url = "https://files.pythonhosted.org/packages/24/dd/3590348818f58f837a75fb969b04cdf187ae197e14d60b5e5a794a38b79d/orjson-3.11.8-cp314-cp314-win32.whl", hash = "sha256:0b57f67710a8cd459e4e54eb96d5f77f3624eba0c661ba19a525807e42eccade", size = 131983, upload-time = "2026-03-31T16:16:21.823Z" },
|
|
699
|
+
{ url = "https://files.pythonhosted.org/packages/3f/0f/b6cb692116e05d058f31ceee819c70f097fa9167c82f67fabe7516289abc/orjson-3.11.8-cp314-cp314-win_amd64.whl", hash = "sha256:735e2262363dcbe05c35e3a8869898022af78f89dde9e256924dc02e99fe69ca", size = 127396, upload-time = "2026-03-31T16:16:23.685Z" },
|
|
700
|
+
{ url = "https://files.pythonhosted.org/packages/c0/d1/facb5b5051fabb0ef9d26c6544d87ef19a939a9a001198655d0d891062dd/orjson-3.11.8-cp314-cp314-win_arm64.whl", hash = "sha256:6ccdea2c213cf9f3d9490cbd5d427693c870753df41e6cb375bd79bcbafc8817", size = 127330, upload-time = "2026-03-31T16:16:25.496Z" },
|
|
678
701
|
]
|
|
679
702
|
|
|
680
703
|
[[package]]
|
|
@@ -715,7 +738,7 @@ wheels = [
|
|
|
715
738
|
|
|
716
739
|
[[package]]
|
|
717
740
|
name = "pre-commit"
|
|
718
|
-
version = "4.
|
|
741
|
+
version = "4.6.0"
|
|
719
742
|
source = { registry = "https://pypi.org/simple" }
|
|
720
743
|
dependencies = [
|
|
721
744
|
{ name = "cfgv" },
|
|
@@ -724,9 +747,9 @@ dependencies = [
|
|
|
724
747
|
{ name = "pyyaml" },
|
|
725
748
|
{ name = "virtualenv" },
|
|
726
749
|
]
|
|
727
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
750
|
+
sdist = { url = "https://files.pythonhosted.org/packages/8e/22/2de9408ac81acbb8a7d05d4cc064a152ccf33b3d480ebe0cd292153db239/pre_commit-4.6.0.tar.gz", hash = "sha256:718d2208cef53fdc38206e40524a6d4d9576d103eb16f0fec11c875e7716e9d9", size = 198525, upload-time = "2026-04-21T20:31:41.613Z" }
|
|
728
751
|
wheels = [
|
|
729
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
752
|
+
{ url = "https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl", hash = "sha256:e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b", size = 226472, upload-time = "2026-04-21T20:31:40.092Z" },
|
|
730
753
|
]
|
|
731
754
|
|
|
732
755
|
[[package]]
|
|
@@ -999,6 +1022,7 @@ dependencies = [
|
|
|
999
1022
|
{ name = "msgpack" },
|
|
1000
1023
|
{ name = "msgspec" },
|
|
1001
1024
|
{ name = "object-storage-client" },
|
|
1025
|
+
{ name = "orjson" },
|
|
1002
1026
|
{ name = "pydantic-settings" },
|
|
1003
1027
|
{ name = "sqlalchemy", extra = ["asyncio"] },
|
|
1004
1028
|
{ name = "valkey", extra = ["libvalkey"] },
|
|
@@ -1024,13 +1048,14 @@ testing = [
|
|
|
1024
1048
|
|
|
1025
1049
|
[package.metadata]
|
|
1026
1050
|
requires-dist = [
|
|
1027
|
-
{ name = "aiobotocore", specifier = "~=3.
|
|
1051
|
+
{ name = "aiobotocore", specifier = "~=3.5.0" },
|
|
1028
1052
|
{ name = "aiohttp", extras = ["speedups"], specifier = ">=3.13.5,<3.15.0" },
|
|
1029
1053
|
{ name = "asyncpg", specifier = "~=0.31.0" },
|
|
1030
1054
|
{ name = "lxml", specifier = "~=6.1.0" },
|
|
1031
1055
|
{ name = "msgpack", specifier = "~=1.1.2" },
|
|
1032
1056
|
{ name = "msgspec", specifier = "==0.21.1" },
|
|
1033
|
-
{ name = "object-storage-client", specifier = "==0.0.
|
|
1057
|
+
{ name = "object-storage-client", specifier = "==0.0.22" },
|
|
1058
|
+
{ name = "orjson", specifier = "==3.11.8" },
|
|
1034
1059
|
{ name = "pydantic-settings", specifier = "~=2.14.0" },
|
|
1035
1060
|
{ name = "sqlalchemy", extras = ["asyncio"], specifier = "~=2.0.49" },
|
|
1036
1061
|
{ name = "valkey", extras = ["libvalkey"], specifier = "~=6.1.1" },
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import logging
|
|
3
|
-
import traceback
|
|
4
|
-
from contextvars import ContextVar
|
|
5
|
-
|
|
6
|
-
from python3_commons.serializers.json import CustomJSONEncoder
|
|
7
|
-
|
|
8
|
-
correlation_id: ContextVar[str | None] = ContextVar('correlation_id', default=None)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class JSONFormatter(logging.Formatter):
|
|
12
|
-
@staticmethod
|
|
13
|
-
def format_exception(exc_info: logging._SysExcInfoType) -> str:
|
|
14
|
-
return ''.join(traceback.format_exception(*exc_info))
|
|
15
|
-
|
|
16
|
-
def format(self, record: logging.LogRecord) -> str:
|
|
17
|
-
if corr_id := correlation_id.get():
|
|
18
|
-
record.correlation_id = corr_id
|
|
19
|
-
|
|
20
|
-
try:
|
|
21
|
-
record.message = record.getMessage()
|
|
22
|
-
except TypeError:
|
|
23
|
-
record.message = str(record.msg)
|
|
24
|
-
|
|
25
|
-
if record.exc_info:
|
|
26
|
-
record.exc_text = self.format_exception(record.exc_info)
|
|
27
|
-
else:
|
|
28
|
-
record.exc_text = None
|
|
29
|
-
|
|
30
|
-
record_dict = record.__dict__
|
|
31
|
-
|
|
32
|
-
del record_dict['args']
|
|
33
|
-
del record_dict['msg']
|
|
34
|
-
|
|
35
|
-
return json.dumps(record_dict, cls=CustomJSONEncoder)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python3_commons-0.15.21 → python3_commons-0.16.1}/.github/workflows/release-on-tag-push.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/db/models/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/serializers/__init__.py
RENAMED
|
File without changes
|
{python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/serializers/common.py
RENAMED
|
File without changes
|
|
File without changes
|
{python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/serializers/msgpack.py
RENAMED
|
File without changes
|
{python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons/serializers/msgspec.py
RENAMED
|
File without changes
|
|
File without changes
|
{python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{python3_commons-0.15.21 → python3_commons-0.16.1}/src/python3_commons.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|