python3-commons 0.16.8__tar.gz → 0.17.0__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.17.0/PKG-INFO +42 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/pyproject.toml +30 -9
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/api_client.py +6 -2
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/audit.py +6 -2
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/auth.py +10 -5
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/cache.py +8 -4
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/db/__init__.py +8 -4
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/db/helpers.py +6 -2
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/db/models/auth.py +6 -2
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/db/models/common.py +10 -6
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/db/models/rbac.py +7 -3
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/db/models/users.py +6 -2
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/log/formatters.py +6 -6
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/object_storage.py +11 -7
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/permissions.py +6 -2
- python3_commons-0.17.0/src/python3_commons.egg-info/PKG-INFO +42 -0
- python3_commons-0.17.0/src/python3_commons.egg-info/requires.txt +29 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/uv.lock +49 -18
- python3_commons-0.16.8/PKG-INFO +0 -31
- python3_commons-0.16.8/src/python3_commons.egg-info/PKG-INFO +0 -31
- python3_commons-0.16.8/src/python3_commons.egg-info/requires.txt +0 -11
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.coveragerc +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.devcontainer/Dockerfile +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.devcontainer/devcontainer.json +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.devcontainer/docker-compose.yml +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.env_template +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.github/workflows/checks.yml +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.github/workflows/python-publish.yaml +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.github/workflows/release-on-tag-push.yml +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.gitignore +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.pre-commit-config.yaml +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/.python-version +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/AUTHORS.rst +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/CHANGELOG.rst +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/LICENSE +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/README.md +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/README.rst +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/docs/Makefile +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/docs/_static/.gitignore +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/docs/authors.rst +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/docs/changelog.rst +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/docs/conf.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/docs/index.rst +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/docs/license.rst +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/setup.cfg +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/__init__.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/async_functools.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/conf.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/db/models/__init__.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/exceptions.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/fs.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/generators.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/helpers.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/log/__init__.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/log/filters.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/serializers/__init__.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/serializers/common.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/serializers/json.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/serializers/msgpack.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/serializers/msgspec.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons.egg-info/SOURCES.txt +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons.egg-info/dependency_links.txt +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons.egg-info/top_level.txt +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/__init__.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/integration/__init__.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/integration/test_cache.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/integration/test_osc.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/unit/__init__.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/unit/conftest.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/unit/log/__init__.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/unit/log/test_formatters.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/unit/test_async_functools.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/unit/test_audit.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/unit/test_helpers.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/unit/test_msgpack.py +0 -0
- {python3_commons-0.16.8 → python3_commons-0.17.0}/tests/unit/test_msgspec.py +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python3-commons
|
|
3
|
+
Version: 0.17.0
|
|
4
|
+
Summary: Re-usable Python3 code
|
|
5
|
+
Author-email: Oleg Korsak <kamikaze.is.waiting.you@gmail.com>
|
|
6
|
+
License-Expression: GPL-3.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/kamikaze/python3-commons
|
|
8
|
+
Project-URL: Documentation, https://github.com/kamikaze/python3-commons/wiki
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Requires-Python: <3.15.0,>=3.14.0
|
|
12
|
+
Description-Content-Type: text/x-rst
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
License-File: AUTHORS.rst
|
|
15
|
+
Requires-Dist: msgpack~=1.1.2
|
|
16
|
+
Requires-Dist: msgspec==0.21.1
|
|
17
|
+
Requires-Dist: pydantic-settings~=2.14.0
|
|
18
|
+
Provides-Extra: all
|
|
19
|
+
Requires-Dist: python3_commons[audit,authn,authz,database,object-storage,valkey]; extra == "all"
|
|
20
|
+
Provides-Extra: api-client
|
|
21
|
+
Requires-Dist: aiohttp[speedups]<3.15.0,>=3.13.5; extra == "api-client"
|
|
22
|
+
Requires-Dist: lxml~=6.1.0; extra == "api-client"
|
|
23
|
+
Requires-Dist: zeep~=4.3.2; extra == "api-client"
|
|
24
|
+
Requires-Dist: python3_commons[object-storage]; extra == "api-client"
|
|
25
|
+
Provides-Extra: authn
|
|
26
|
+
Requires-Dist: aiohttp[speedups]<3.15.0,>=3.13.5; extra == "authn"
|
|
27
|
+
Provides-Extra: authz
|
|
28
|
+
Requires-Dist: python3_commons[database]; extra == "authz"
|
|
29
|
+
Provides-Extra: cache
|
|
30
|
+
Requires-Dist: valkey[libvalkey]~=6.1.1; extra == "cache"
|
|
31
|
+
Provides-Extra: database
|
|
32
|
+
Requires-Dist: asyncpg~=0.31.0; extra == "database"
|
|
33
|
+
Requires-Dist: SQLAlchemy[asyncio]~=2.0.49; extra == "database"
|
|
34
|
+
Provides-Extra: object-storage
|
|
35
|
+
Requires-Dist: aiobotocore~=3.5.0; extra == "object-storage"
|
|
36
|
+
Requires-Dist: object-storage-client==0.0.22; extra == "object-storage"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
Re-usable Python3 code
|
|
40
|
+
======================
|
|
41
|
+
|
|
42
|
+
Some description here
|
|
@@ -18,18 +18,39 @@ classifiers = [
|
|
|
18
18
|
keywords = []
|
|
19
19
|
requires-python = ">=3.14.0,<3.15.0"
|
|
20
20
|
dependencies = [
|
|
21
|
-
"aiobotocore~=3.5.0",
|
|
22
|
-
"aiohttp[speedups]>=3.13.5,<3.15.0",
|
|
23
|
-
"asyncpg~=0.31.0",
|
|
24
|
-
"lxml~=6.1.0",
|
|
25
21
|
"msgpack~=1.1.2",
|
|
26
22
|
"msgspec==0.21.1",
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
"pydantic-settings~=2.14.0"
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.optional-dependencies]
|
|
27
|
+
all = [
|
|
28
|
+
"python3_commons[audit,authn,authz,database,object-storage,valkey]"
|
|
29
|
+
]
|
|
30
|
+
api-client = [
|
|
31
|
+
"aiohttp[speedups]>=3.13.5,<3.15.0",
|
|
32
|
+
"lxml~=6.1.0",
|
|
33
|
+
"zeep~=4.3.2",
|
|
34
|
+
"python3_commons[object-storage]"
|
|
32
35
|
]
|
|
36
|
+
authn = [
|
|
37
|
+
"aiohttp[speedups]>=3.13.5,<3.15.0",
|
|
38
|
+
]
|
|
39
|
+
authz = [
|
|
40
|
+
"python3_commons[database]"
|
|
41
|
+
]
|
|
42
|
+
cache = [
|
|
43
|
+
"valkey[libvalkey]~=6.1.1"
|
|
44
|
+
]
|
|
45
|
+
database = [
|
|
46
|
+
"asyncpg~=0.31.0",
|
|
47
|
+
"SQLAlchemy[asyncio]~=2.0.49"
|
|
48
|
+
]
|
|
49
|
+
object-storage = [
|
|
50
|
+
"aiobotocore~=3.5.0",
|
|
51
|
+
"object-storage-client==0.0.22"
|
|
52
|
+
]
|
|
53
|
+
|
|
33
54
|
|
|
34
55
|
[dependency-groups]
|
|
35
56
|
dev = [
|
|
@@ -9,8 +9,12 @@ from json import dumps
|
|
|
9
9
|
from typing import Literal
|
|
10
10
|
from uuid import uuid4
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
from aiohttp
|
|
12
|
+
try:
|
|
13
|
+
from aiohttp import ClientResponse, ClientSession, ClientTimeout, client_exceptions
|
|
14
|
+
from aiohttp.abc import URL
|
|
15
|
+
except ImportError as e:
|
|
16
|
+
msg = 'Install python3_commons[api-client] to use this feature'
|
|
17
|
+
raise RuntimeError(msg) from e
|
|
14
18
|
|
|
15
19
|
from python3_commons import audit
|
|
16
20
|
from python3_commons.conf import s3_settings
|
|
@@ -5,8 +5,12 @@ from datetime import UTC, datetime
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
from uuid import uuid4
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
from
|
|
8
|
+
try:
|
|
9
|
+
from lxml import etree
|
|
10
|
+
from zeep.plugins import Plugin
|
|
11
|
+
except ImportError as e:
|
|
12
|
+
msg = 'Install python3_commons[api-client] to use this feature'
|
|
13
|
+
raise RuntimeError(msg) from e
|
|
10
14
|
|
|
11
15
|
from python3_commons import object_storage
|
|
12
16
|
from python3_commons.conf import S3Settings, s3_settings
|
|
@@ -5,7 +5,12 @@ from collections.abc import Sequence
|
|
|
5
5
|
from http import HTTPStatus
|
|
6
6
|
from typing import TypeVar
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
try:
|
|
9
|
+
import aiohttp
|
|
10
|
+
except ImportError as e:
|
|
11
|
+
msg = 'Install python3_commons[authn] to use this feature'
|
|
12
|
+
raise RuntimeError(msg) from e
|
|
13
|
+
|
|
9
14
|
import msgspec
|
|
10
15
|
|
|
11
16
|
from python3_commons.conf import oidc_settings
|
|
@@ -51,9 +56,9 @@ async def fetch_openid_config() -> dict:
|
|
|
51
56
|
"""
|
|
52
57
|
async with aiohttp.ClientSession() as session, session.get(OIDC_CONFIG_URL) as response:
|
|
53
58
|
if response.status != HTTPStatus.OK:
|
|
54
|
-
|
|
59
|
+
_msg = 'Failed to fetch OpenID configuration'
|
|
55
60
|
|
|
56
|
-
raise RuntimeError(
|
|
61
|
+
raise RuntimeError(_msg)
|
|
57
62
|
|
|
58
63
|
return await response.json()
|
|
59
64
|
|
|
@@ -67,8 +72,8 @@ async def fetch_jwks(jwks_uri: str) -> dict:
|
|
|
67
72
|
|
|
68
73
|
async with aiohttp.ClientSession() as session, session.get(jwks_uri) as response:
|
|
69
74
|
if response.status != HTTPStatus.OK:
|
|
70
|
-
|
|
75
|
+
_msg = 'Failed to fetch JWKS'
|
|
71
76
|
|
|
72
|
-
raise RuntimeError(
|
|
77
|
+
raise RuntimeError(_msg)
|
|
73
78
|
|
|
74
79
|
return await response.json()
|
|
@@ -4,10 +4,14 @@ from collections.abc import Mapping, Sequence
|
|
|
4
4
|
from platform import platform
|
|
5
5
|
from typing import TYPE_CHECKING, Any
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
from valkey.asyncio
|
|
10
|
-
from valkey.
|
|
7
|
+
try:
|
|
8
|
+
import valkey
|
|
9
|
+
from valkey.asyncio import ConnectionPool, Sentinel, StrictValkey, Valkey
|
|
10
|
+
from valkey.asyncio.retry import Retry
|
|
11
|
+
from valkey.backoff import FullJitterBackoff
|
|
12
|
+
except ImportError as e:
|
|
13
|
+
msg = 'Install python3_commons[cache] to use this feature'
|
|
14
|
+
raise RuntimeError(msg) from e
|
|
11
15
|
|
|
12
16
|
from python3_commons.conf import valkey_settings
|
|
13
17
|
from python3_commons.helpers import SingletonMeta
|
|
@@ -3,10 +3,14 @@ import logging
|
|
|
3
3
|
from collections.abc import AsyncGenerator, Callable, Mapping
|
|
4
4
|
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
from sqlalchemy
|
|
8
|
-
from sqlalchemy.ext.asyncio
|
|
9
|
-
from sqlalchemy.
|
|
6
|
+
try:
|
|
7
|
+
from sqlalchemy import MetaData
|
|
8
|
+
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_engine_from_config
|
|
9
|
+
from sqlalchemy.ext.asyncio.session import async_sessionmaker
|
|
10
|
+
from sqlalchemy.orm import declarative_base
|
|
11
|
+
except ImportError as e:
|
|
12
|
+
msg = 'Install python3_commons[database] to use this feature'
|
|
13
|
+
raise RuntimeError(msg) from e
|
|
10
14
|
|
|
11
15
|
if TYPE_CHECKING:
|
|
12
16
|
from python3_commons.conf import DBSettings
|
|
@@ -2,8 +2,12 @@ import logging
|
|
|
2
2
|
from collections.abc import Mapping
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
try:
|
|
6
|
+
import sqlalchemy as sa
|
|
7
|
+
from sqlalchemy import asc, desc, func
|
|
8
|
+
except ImportError as e:
|
|
9
|
+
msg = 'Install python3_commons[database] to use this feature'
|
|
10
|
+
raise RuntimeError(msg) from e
|
|
7
11
|
|
|
8
12
|
if TYPE_CHECKING:
|
|
9
13
|
from sqlalchemy.sql.elements import ColumnElement
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import uuid
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
from sqlalchemy
|
|
4
|
+
try:
|
|
5
|
+
from sqlalchemy import UUID, DateTime, ForeignKey, String
|
|
6
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
7
|
+
except ImportError as e:
|
|
8
|
+
msg = 'Install python3_commons[database] to use this feature'
|
|
9
|
+
raise RuntimeError(msg) from e
|
|
6
10
|
|
|
7
11
|
from python3_commons.db import Base
|
|
8
12
|
from python3_commons.db.models.common import BaseDBUUIDModel
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import uuid
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
from sqlalchemy
|
|
6
|
-
from sqlalchemy.
|
|
7
|
-
from sqlalchemy.
|
|
8
|
-
from sqlalchemy.
|
|
9
|
-
from sqlalchemy.sql
|
|
4
|
+
try:
|
|
5
|
+
from sqlalchemy import BIGINT, DateTime
|
|
6
|
+
from sqlalchemy.dialects.postgresql import UUID
|
|
7
|
+
from sqlalchemy.ext.compiler import compiles
|
|
8
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
9
|
+
from sqlalchemy.sql import expression
|
|
10
|
+
from sqlalchemy.sql.ddl import CreateColumn
|
|
11
|
+
except ImportError as e:
|
|
12
|
+
msg = 'Install python3_commons[database] to use this feature'
|
|
13
|
+
raise RuntimeError(msg) from e
|
|
10
14
|
|
|
11
15
|
|
|
12
16
|
class UTCNow(expression.FunctionElement):
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import uuid
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
from sqlalchemy
|
|
6
|
-
from sqlalchemy.
|
|
4
|
+
try:
|
|
5
|
+
from sqlalchemy import CheckConstraint, DateTime, ForeignKey, PrimaryKeyConstraint, String
|
|
6
|
+
from sqlalchemy.dialects.postgresql import UUID
|
|
7
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
8
|
+
except ImportError as e:
|
|
9
|
+
msg = 'Install python3_commons[database] to use this feature'
|
|
10
|
+
raise RuntimeError(msg) from e
|
|
7
11
|
|
|
8
12
|
from python3_commons.db import Base
|
|
9
13
|
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import uuid
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
from sqlalchemy
|
|
3
|
+
try:
|
|
4
|
+
from sqlalchemy import UUID, ForeignKey, String
|
|
5
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
6
|
+
except ImportError as e:
|
|
7
|
+
msg = 'Install python3_commons[database] to use this feature'
|
|
8
|
+
raise RuntimeError(msg) from e
|
|
5
9
|
|
|
6
10
|
from python3_commons.db import Base
|
|
7
11
|
from python3_commons.db.models.common import BaseDBUUIDModel
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import traceback
|
|
3
|
-
from datetime import UTC,
|
|
3
|
+
from datetime import UTC, date, datetime
|
|
4
4
|
from decimal import Decimal
|
|
5
5
|
from typing import Any, Final
|
|
6
6
|
|
|
@@ -51,13 +51,13 @@ def _normalize(v: Any) -> Any:
|
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
class JSONFormatter(logging.Formatter):
|
|
54
|
-
__slots__ = ('
|
|
54
|
+
__slots__ = ('_encoder', '_max_tb_chars')
|
|
55
55
|
|
|
56
56
|
def __init__(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
self,
|
|
58
|
+
*,
|
|
59
|
+
max_exc_tb_chars: int = _DEFAULT_MAX_TB_CHARS,
|
|
60
|
+
**kwargs: Any,
|
|
61
61
|
) -> None:
|
|
62
62
|
super().__init__(**kwargs)
|
|
63
63
|
|
|
@@ -5,9 +5,13 @@ import threading
|
|
|
5
5
|
from contextlib import asynccontextmanager
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
from
|
|
8
|
+
try:
|
|
9
|
+
import aiobotocore.session
|
|
10
|
+
from botocore.config import Config
|
|
11
|
+
from object_storage_client import ObjectStorageClient
|
|
12
|
+
except ImportError as e:
|
|
13
|
+
msg = 'Install python3_commons[object-storage] to use this feature'
|
|
14
|
+
raise RuntimeError(msg) from e
|
|
11
15
|
|
|
12
16
|
if TYPE_CHECKING:
|
|
13
17
|
import io
|
|
@@ -132,7 +136,7 @@ async def list_objects(bucket_name: str, prefix: str, *, recursive: bool = True)
|
|
|
132
136
|
|
|
133
137
|
|
|
134
138
|
async def get_object_streams(
|
|
135
|
-
|
|
139
|
+
bucket_name: str, path: str, *, recursive: bool = True
|
|
136
140
|
) -> AsyncGenerator[tuple[str, datetime, StreamingBody]]:
|
|
137
141
|
async for obj in list_objects(bucket_name, path, recursive=recursive):
|
|
138
142
|
object_name = obj['Key']
|
|
@@ -143,7 +147,7 @@ async def get_object_streams(
|
|
|
143
147
|
|
|
144
148
|
|
|
145
149
|
async def get_objects(
|
|
146
|
-
|
|
150
|
+
bucket_name: str, path: str, *, recursive: bool = True
|
|
147
151
|
) -> AsyncGenerator[tuple[str, datetime, bytes]]:
|
|
148
152
|
async for object_name, last_modified, stream in get_object_streams(bucket_name, path, recursive=recursive):
|
|
149
153
|
data = await stream.read()
|
|
@@ -165,7 +169,7 @@ async def remove_object(bucket_name: str, object_name: str) -> None:
|
|
|
165
169
|
|
|
166
170
|
|
|
167
171
|
async def remove_objects(
|
|
168
|
-
|
|
172
|
+
bucket_name: str, prefix: str | None = None, object_names: Iterable[str] | None = None
|
|
169
173
|
) -> Sequence[Mapping] | None:
|
|
170
174
|
storage = ObjectStorage(s3_settings)
|
|
171
175
|
|
|
@@ -188,7 +192,7 @@ async def remove_objects(
|
|
|
188
192
|
chunk_size = 1000
|
|
189
193
|
|
|
190
194
|
for i in range(0, len(objects_to_delete), chunk_size):
|
|
191
|
-
chunk = objects_to_delete[i: i + chunk_size]
|
|
195
|
+
chunk = objects_to_delete[i : i + chunk_size]
|
|
192
196
|
|
|
193
197
|
response = await s3_client.delete_objects(Bucket=bucket_name, Delete={'Objects': chunk})
|
|
194
198
|
|
|
@@ -2,8 +2,12 @@ import logging
|
|
|
2
2
|
from typing import TYPE_CHECKING
|
|
3
3
|
from uuid import UUID
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
try:
|
|
6
|
+
import sqlalchemy as sa
|
|
7
|
+
from sqlalchemy import and_, exists, func
|
|
8
|
+
except ImportError as e:
|
|
9
|
+
msg = 'Install python3_commons[authz] to use this feature'
|
|
10
|
+
raise RuntimeError(msg) from e
|
|
7
11
|
|
|
8
12
|
from python3_commons.db.models.rbac import RBACApiKeyRole, RBACPermission, RBACRolePermission, RBACUserRole
|
|
9
13
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python3-commons
|
|
3
|
+
Version: 0.17.0
|
|
4
|
+
Summary: Re-usable Python3 code
|
|
5
|
+
Author-email: Oleg Korsak <kamikaze.is.waiting.you@gmail.com>
|
|
6
|
+
License-Expression: GPL-3.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/kamikaze/python3-commons
|
|
8
|
+
Project-URL: Documentation, https://github.com/kamikaze/python3-commons/wiki
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Requires-Python: <3.15.0,>=3.14.0
|
|
12
|
+
Description-Content-Type: text/x-rst
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
License-File: AUTHORS.rst
|
|
15
|
+
Requires-Dist: msgpack~=1.1.2
|
|
16
|
+
Requires-Dist: msgspec==0.21.1
|
|
17
|
+
Requires-Dist: pydantic-settings~=2.14.0
|
|
18
|
+
Provides-Extra: all
|
|
19
|
+
Requires-Dist: python3_commons[audit,authn,authz,database,object-storage,valkey]; extra == "all"
|
|
20
|
+
Provides-Extra: api-client
|
|
21
|
+
Requires-Dist: aiohttp[speedups]<3.15.0,>=3.13.5; extra == "api-client"
|
|
22
|
+
Requires-Dist: lxml~=6.1.0; extra == "api-client"
|
|
23
|
+
Requires-Dist: zeep~=4.3.2; extra == "api-client"
|
|
24
|
+
Requires-Dist: python3_commons[object-storage]; extra == "api-client"
|
|
25
|
+
Provides-Extra: authn
|
|
26
|
+
Requires-Dist: aiohttp[speedups]<3.15.0,>=3.13.5; extra == "authn"
|
|
27
|
+
Provides-Extra: authz
|
|
28
|
+
Requires-Dist: python3_commons[database]; extra == "authz"
|
|
29
|
+
Provides-Extra: cache
|
|
30
|
+
Requires-Dist: valkey[libvalkey]~=6.1.1; extra == "cache"
|
|
31
|
+
Provides-Extra: database
|
|
32
|
+
Requires-Dist: asyncpg~=0.31.0; extra == "database"
|
|
33
|
+
Requires-Dist: SQLAlchemy[asyncio]~=2.0.49; extra == "database"
|
|
34
|
+
Provides-Extra: object-storage
|
|
35
|
+
Requires-Dist: aiobotocore~=3.5.0; extra == "object-storage"
|
|
36
|
+
Requires-Dist: object-storage-client==0.0.22; extra == "object-storage"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
Re-usable Python3 code
|
|
40
|
+
======================
|
|
41
|
+
|
|
42
|
+
Some description here
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
msgpack~=1.1.2
|
|
2
|
+
msgspec==0.21.1
|
|
3
|
+
pydantic-settings~=2.14.0
|
|
4
|
+
|
|
5
|
+
[all]
|
|
6
|
+
python3_commons[audit,authn,authz,database,object-storage,valkey]
|
|
7
|
+
|
|
8
|
+
[api-client]
|
|
9
|
+
aiohttp[speedups]<3.15.0,>=3.13.5
|
|
10
|
+
lxml~=6.1.0
|
|
11
|
+
zeep~=4.3.2
|
|
12
|
+
python3_commons[object-storage]
|
|
13
|
+
|
|
14
|
+
[authn]
|
|
15
|
+
aiohttp[speedups]<3.15.0,>=3.13.5
|
|
16
|
+
|
|
17
|
+
[authz]
|
|
18
|
+
python3_commons[database]
|
|
19
|
+
|
|
20
|
+
[cache]
|
|
21
|
+
valkey[libvalkey]~=6.1.1
|
|
22
|
+
|
|
23
|
+
[database]
|
|
24
|
+
asyncpg~=0.31.0
|
|
25
|
+
SQLAlchemy[asyncio]~=2.0.49
|
|
26
|
+
|
|
27
|
+
[object-storage]
|
|
28
|
+
aiobotocore~=3.5.0
|
|
29
|
+
object-storage-client==0.0.22
|
|
@@ -992,17 +992,43 @@ wheels = [
|
|
|
992
992
|
name = "python3-commons"
|
|
993
993
|
source = { editable = "." }
|
|
994
994
|
dependencies = [
|
|
995
|
+
{ name = "msgpack" },
|
|
996
|
+
{ name = "msgspec" },
|
|
997
|
+
{ name = "pydantic-settings" },
|
|
998
|
+
]
|
|
999
|
+
|
|
1000
|
+
[package.optional-dependencies]
|
|
1001
|
+
all = [
|
|
995
1002
|
{ name = "aiobotocore" },
|
|
996
1003
|
{ name = "aiohttp", extra = ["speedups"] },
|
|
997
1004
|
{ name = "asyncpg" },
|
|
1005
|
+
{ name = "object-storage-client" },
|
|
1006
|
+
{ name = "sqlalchemy", extra = ["asyncio"] },
|
|
1007
|
+
]
|
|
1008
|
+
api-client = [
|
|
1009
|
+
{ name = "aiobotocore" },
|
|
1010
|
+
{ name = "aiohttp", extra = ["speedups"] },
|
|
998
1011
|
{ name = "lxml" },
|
|
999
|
-
{ name = "msgpack" },
|
|
1000
|
-
{ name = "msgspec" },
|
|
1001
1012
|
{ name = "object-storage-client" },
|
|
1002
|
-
{ name = "
|
|
1013
|
+
{ name = "zeep" },
|
|
1014
|
+
]
|
|
1015
|
+
authn = [
|
|
1016
|
+
{ name = "aiohttp", extra = ["speedups"] },
|
|
1017
|
+
]
|
|
1018
|
+
authz = [
|
|
1019
|
+
{ name = "asyncpg" },
|
|
1003
1020
|
{ name = "sqlalchemy", extra = ["asyncio"] },
|
|
1021
|
+
]
|
|
1022
|
+
cache = [
|
|
1004
1023
|
{ name = "valkey", extra = ["libvalkey"] },
|
|
1005
|
-
|
|
1024
|
+
]
|
|
1025
|
+
database = [
|
|
1026
|
+
{ name = "asyncpg" },
|
|
1027
|
+
{ name = "sqlalchemy", extra = ["asyncio"] },
|
|
1028
|
+
]
|
|
1029
|
+
object-storage = [
|
|
1030
|
+
{ name = "aiobotocore" },
|
|
1031
|
+
{ name = "object-storage-client" },
|
|
1006
1032
|
]
|
|
1007
1033
|
|
|
1008
1034
|
[package.dev-dependencies]
|
|
@@ -1024,18 +1050,23 @@ testing = [
|
|
|
1024
1050
|
|
|
1025
1051
|
[package.metadata]
|
|
1026
1052
|
requires-dist = [
|
|
1027
|
-
{ name = "aiobotocore", specifier = "~=3.5.0" },
|
|
1028
|
-
{ name = "aiohttp", extras = ["speedups"], specifier = ">=3.13.5,<3.15.0" },
|
|
1029
|
-
{ name = "
|
|
1030
|
-
{ name = "
|
|
1053
|
+
{ name = "aiobotocore", marker = "extra == 'object-storage'", specifier = "~=3.5.0" },
|
|
1054
|
+
{ name = "aiohttp", extras = ["speedups"], marker = "extra == 'api-client'", specifier = ">=3.13.5,<3.15.0" },
|
|
1055
|
+
{ name = "aiohttp", extras = ["speedups"], marker = "extra == 'authn'", specifier = ">=3.13.5,<3.15.0" },
|
|
1056
|
+
{ name = "asyncpg", marker = "extra == 'database'", specifier = "~=0.31.0" },
|
|
1057
|
+
{ name = "lxml", marker = "extra == 'api-client'", specifier = "~=6.1.0" },
|
|
1031
1058
|
{ name = "msgpack", specifier = "~=1.1.2" },
|
|
1032
1059
|
{ name = "msgspec", specifier = "==0.21.1" },
|
|
1033
|
-
{ name = "object-storage-client", specifier = "==0.0.22" },
|
|
1060
|
+
{ name = "object-storage-client", marker = "extra == 'object-storage'", specifier = "==0.0.22" },
|
|
1034
1061
|
{ name = "pydantic-settings", specifier = "~=2.14.0" },
|
|
1035
|
-
{ name = "
|
|
1036
|
-
{ name = "
|
|
1037
|
-
{ name = "
|
|
1062
|
+
{ name = "python3-commons", extras = ["audit", "authn", "authz", "database", "object-storage", "valkey"], marker = "extra == 'all'" },
|
|
1063
|
+
{ name = "python3-commons", extras = ["database"], marker = "extra == 'authz'" },
|
|
1064
|
+
{ name = "python3-commons", extras = ["object-storage"], marker = "extra == 'api-client'" },
|
|
1065
|
+
{ name = "sqlalchemy", extras = ["asyncio"], marker = "extra == 'database'", specifier = "~=2.0.49" },
|
|
1066
|
+
{ name = "valkey", extras = ["libvalkey"], marker = "extra == 'cache'", specifier = "~=6.1.1" },
|
|
1067
|
+
{ name = "zeep", marker = "extra == 'api-client'", specifier = "~=4.3.2" },
|
|
1038
1068
|
]
|
|
1069
|
+
provides-extras = ["all", "api-client", "authn", "authz", "cache", "database", "object-storage"]
|
|
1039
1070
|
|
|
1040
1071
|
[package.metadata.requires-dev]
|
|
1041
1072
|
dev = [
|
|
@@ -1193,14 +1224,14 @@ asyncio = [
|
|
|
1193
1224
|
|
|
1194
1225
|
[[package]]
|
|
1195
1226
|
name = "types-aiobotocore"
|
|
1196
|
-
version = "3.
|
|
1227
|
+
version = "3.5.0"
|
|
1197
1228
|
source = { registry = "https://pypi.org/simple" }
|
|
1198
1229
|
dependencies = [
|
|
1199
1230
|
{ name = "botocore-stubs" },
|
|
1200
1231
|
]
|
|
1201
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1232
|
+
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" }
|
|
1202
1233
|
wheels = [
|
|
1203
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1234
|
+
{ 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" },
|
|
1204
1235
|
]
|
|
1205
1236
|
|
|
1206
1237
|
[package.optional-dependencies]
|
|
@@ -1210,11 +1241,11 @@ s3 = [
|
|
|
1210
1241
|
|
|
1211
1242
|
[[package]]
|
|
1212
1243
|
name = "types-aiobotocore-s3"
|
|
1213
|
-
version = "3.
|
|
1244
|
+
version = "3.5.0"
|
|
1214
1245
|
source = { registry = "https://pypi.org/simple" }
|
|
1215
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1246
|
+
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" }
|
|
1216
1247
|
wheels = [
|
|
1217
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1248
|
+
{ 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" },
|
|
1218
1249
|
]
|
|
1219
1250
|
|
|
1220
1251
|
[[package]]
|
python3_commons-0.16.8/PKG-INFO
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: python3-commons
|
|
3
|
-
Version: 0.16.8
|
|
4
|
-
Summary: Re-usable Python3 code
|
|
5
|
-
Author-email: Oleg Korsak <kamikaze.is.waiting.you@gmail.com>
|
|
6
|
-
License-Expression: GPL-3.0
|
|
7
|
-
Project-URL: Homepage, https://github.com/kamikaze/python3-commons
|
|
8
|
-
Project-URL: Documentation, https://github.com/kamikaze/python3-commons/wiki
|
|
9
|
-
Classifier: Development Status :: 4 - Beta
|
|
10
|
-
Classifier: Programming Language :: Python
|
|
11
|
-
Requires-Python: <3.15.0,>=3.14.0
|
|
12
|
-
Description-Content-Type: text/x-rst
|
|
13
|
-
License-File: LICENSE
|
|
14
|
-
License-File: AUTHORS.rst
|
|
15
|
-
Requires-Dist: aiobotocore~=3.5.0
|
|
16
|
-
Requires-Dist: aiohttp[speedups]<3.15.0,>=3.13.5
|
|
17
|
-
Requires-Dist: asyncpg~=0.31.0
|
|
18
|
-
Requires-Dist: lxml~=6.1.0
|
|
19
|
-
Requires-Dist: msgpack~=1.1.2
|
|
20
|
-
Requires-Dist: msgspec==0.21.1
|
|
21
|
-
Requires-Dist: object-storage-client==0.0.22
|
|
22
|
-
Requires-Dist: pydantic-settings~=2.14.0
|
|
23
|
-
Requires-Dist: SQLAlchemy[asyncio]~=2.0.49
|
|
24
|
-
Requires-Dist: valkey[libvalkey]~=6.1.1
|
|
25
|
-
Requires-Dist: zeep~=4.3.2
|
|
26
|
-
Dynamic: license-file
|
|
27
|
-
|
|
28
|
-
Re-usable Python3 code
|
|
29
|
-
======================
|
|
30
|
-
|
|
31
|
-
Some description here
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: python3-commons
|
|
3
|
-
Version: 0.16.8
|
|
4
|
-
Summary: Re-usable Python3 code
|
|
5
|
-
Author-email: Oleg Korsak <kamikaze.is.waiting.you@gmail.com>
|
|
6
|
-
License-Expression: GPL-3.0
|
|
7
|
-
Project-URL: Homepage, https://github.com/kamikaze/python3-commons
|
|
8
|
-
Project-URL: Documentation, https://github.com/kamikaze/python3-commons/wiki
|
|
9
|
-
Classifier: Development Status :: 4 - Beta
|
|
10
|
-
Classifier: Programming Language :: Python
|
|
11
|
-
Requires-Python: <3.15.0,>=3.14.0
|
|
12
|
-
Description-Content-Type: text/x-rst
|
|
13
|
-
License-File: LICENSE
|
|
14
|
-
License-File: AUTHORS.rst
|
|
15
|
-
Requires-Dist: aiobotocore~=3.5.0
|
|
16
|
-
Requires-Dist: aiohttp[speedups]<3.15.0,>=3.13.5
|
|
17
|
-
Requires-Dist: asyncpg~=0.31.0
|
|
18
|
-
Requires-Dist: lxml~=6.1.0
|
|
19
|
-
Requires-Dist: msgpack~=1.1.2
|
|
20
|
-
Requires-Dist: msgspec==0.21.1
|
|
21
|
-
Requires-Dist: object-storage-client==0.0.22
|
|
22
|
-
Requires-Dist: pydantic-settings~=2.14.0
|
|
23
|
-
Requires-Dist: SQLAlchemy[asyncio]~=2.0.49
|
|
24
|
-
Requires-Dist: valkey[libvalkey]~=6.1.1
|
|
25
|
-
Requires-Dist: zeep~=4.3.2
|
|
26
|
-
Dynamic: license-file
|
|
27
|
-
|
|
28
|
-
Re-usable Python3 code
|
|
29
|
-
======================
|
|
30
|
-
|
|
31
|
-
Some description here
|
|
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
|
|
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.16.8 → python3_commons-0.17.0}/src/python3_commons/serializers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/serializers/msgpack.py
RENAMED
|
File without changes
|
{python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons/serializers/msgspec.py
RENAMED
|
File without changes
|
|
File without changes
|
{python3_commons-0.16.8 → python3_commons-0.17.0}/src/python3_commons.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{python3_commons-0.16.8 → python3_commons-0.17.0}/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
|