python3-commons 0.8.36__py3-none-any.whl → 0.9.1__py3-none-any.whl

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/audit.py CHANGED
@@ -5,23 +5,21 @@ import tarfile
5
5
  from bz2 import BZ2Compressor
6
6
  from collections import deque
7
7
  from datetime import UTC, datetime, timedelta
8
- from typing import Generator, Iterable
8
+ from typing import AsyncGenerator
9
9
  from uuid import uuid4
10
10
 
11
11
  from lxml import etree
12
- from minio import S3Error
13
12
  from zeep.plugins import Plugin
14
13
  from zeep.wsdl.definitions import AbstractOperation
15
14
 
16
15
  from python3_commons import object_storage
17
16
  from python3_commons.conf import S3Settings, s3_settings
18
- from python3_commons.object_storage import ObjectStorage
19
17
 
20
18
  logger = logging.getLogger(__name__)
21
19
 
22
20
 
23
21
  class GeneratedStream(io.BytesIO):
24
- def __init__(self, generator: Generator[bytes, None, None], *args, **kwargs):
22
+ def __init__(self, generator: AsyncGenerator[bytes], *args, **kwargs):
25
23
  super().__init__(*args, **kwargs)
26
24
  self.generator = generator
27
25
 
@@ -29,7 +27,7 @@ class GeneratedStream(io.BytesIO):
29
27
  if size < 0:
30
28
  while True:
31
29
  try:
32
- chunk = next(self.generator)
30
+ chunk = anext(self.generator)
33
31
  except StopIteration:
34
32
  break
35
33
  else:
@@ -39,7 +37,7 @@ class GeneratedStream(io.BytesIO):
39
37
 
40
38
  while total_written_size < size:
41
39
  try:
42
- chunk = next(self.generator)
40
+ chunk = anext(self.generator)
43
41
  except StopIteration:
44
42
  break
45
43
  else:
@@ -67,17 +65,17 @@ class GeneratedStream(io.BytesIO):
67
65
  return True
68
66
 
69
67
 
70
- def generate_archive(
71
- objects: Iterable[tuple[str, datetime, bytes]], chunk_size: int = 4096
72
- ) -> Generator[bytes, None, None]:
68
+ async def generate_archive(
69
+ objects: AsyncGenerator[tuple[str, datetime, bytes]], chunk_size: int = 4096
70
+ ) -> AsyncGenerator[bytes]:
73
71
  buffer = deque()
74
72
 
75
73
  with tarfile.open(fileobj=buffer, mode='w') as archive:
76
- for name, last_modified, content in objects:
74
+ async for name, last_modified, content in objects:
77
75
  logger.info(f'Adding {name} to archive')
78
76
  info = tarfile.TarInfo(name)
79
77
  info.size = len(content)
80
- info.mtime = last_modified.timestamp()
78
+ info.mtime = int(last_modified.timestamp())
81
79
  archive.addfile(info, io.BytesIO(content))
82
80
 
83
81
  buffer_length = buffer.tell()
@@ -109,10 +107,10 @@ def generate_archive(
109
107
  buffer.truncate(0)
110
108
 
111
109
 
112
- def generate_bzip2(chunks: Generator[bytes, None, None]) -> Generator[bytes, None, None]:
110
+ async def generate_bzip2(chunks: AsyncGenerator[bytes]) -> AsyncGenerator[bytes]:
113
111
  compressor = BZ2Compressor()
114
112
 
115
- for chunk in chunks:
113
+ async for chunk in chunks:
116
114
  if compressed_chunk := compressor.compress(chunk):
117
115
  yield compressed_chunk
118
116
 
@@ -120,14 +118,13 @@ def generate_bzip2(chunks: Generator[bytes, None, None]) -> Generator[bytes, Non
120
118
  yield compressed_chunk
121
119
 
122
120
 
123
- def write_audit_data_sync(settings: S3Settings, key: str, data: bytes):
121
+ async def write_audit_data(settings: S3Settings, key: str, data: bytes):
124
122
  if settings.s3_secret_access_key:
125
123
  try:
126
- client = ObjectStorage(settings).get_client()
127
124
  absolute_path = object_storage.get_absolute_path(f'audit/{key}')
128
125
 
129
- client.put_object(settings.s3_bucket, absolute_path, io.BytesIO(data), len(data))
130
- except S3Error as e:
126
+ await object_storage.put_object(settings.s3_bucket, absolute_path, io.BytesIO(data), len(data))
127
+ except Exception as e:
131
128
  logger.error(f'Failed storing object in storage: {e}')
132
129
  else:
133
130
  logger.debug(f'Stored object in storage: {key}')
@@ -135,10 +132,6 @@ def write_audit_data_sync(settings: S3Settings, key: str, data: bytes):
135
132
  logger.debug(f'S3 is not configured, not storing object in storage: {key}')
136
133
 
137
134
 
138
- async def write_audit_data(settings: S3Settings, key: str, data: bytes):
139
- await asyncio.to_thread(write_audit_data_sync, settings, key, data)
140
-
141
-
142
135
  async def archive_audit_data(root_path: str = 'audit'):
143
136
  now = datetime.now(tz=UTC) - timedelta(days=1)
144
137
  year = now.year
@@ -155,9 +148,9 @@ async def archive_audit_data(root_path: str = 'audit'):
155
148
  archive_stream = GeneratedStream(bzip2_generator)
156
149
 
157
150
  archive_path = object_storage.get_absolute_path(f'audit/.archive/{year}_{month:02}_{day:02}.tar.bz2')
158
- object_storage.put_object(bucket_name, archive_path, archive_stream, -1, part_size=5 * 1024 * 1024)
151
+ await object_storage.put_object(bucket_name, archive_path, archive_stream, -1, part_size=5 * 1024 * 1024)
159
152
 
160
- if errors := object_storage.remove_objects(bucket_name, date_path):
153
+ if errors := await object_storage.remove_objects(bucket_name, date_path):
161
154
  for error in errors:
162
155
  logger.error(f'Failed to delete object in {bucket_name=}: {error}')
163
156
 
python3_commons/conf.py CHANGED
@@ -64,8 +64,8 @@ class DBSettings(BaseSettings):
64
64
  class S3Settings(BaseSettings):
65
65
  s3_endpoint_url: str | None = None
66
66
  s3_region_name: str | None = None
67
- s3_access_key_id: SecretStr = ''
68
- s3_secret_access_key: SecretStr = ''
67
+ s3_access_key_id: SecretStr = SecretStr('')
68
+ s3_secret_access_key: SecretStr = SecretStr('')
69
69
  s3_secure: bool = True
70
70
  s3_bucket: str | None = None
71
71
  s3_bucket_root: str | None = None
@@ -65,7 +65,7 @@ async def put_object(bucket_name: str, path: str, data: io.BytesIO, length: int,
65
65
  except Exception as e:
66
66
  logger.error(f'Failed to put object to object storage: {bucket_name}:{path}', exc_info=e)
67
67
 
68
- return None
68
+ raise
69
69
 
70
70
 
71
71
  @asynccontextmanager
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python3-commons
3
- Version: 0.8.36
3
+ Version: 0.9.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
@@ -1,12 +1,12 @@
1
1
  python3_commons/__init__.py,sha256=0KgaYU46H_IMKn-BuasoRN3C4Hi45KlkHHoPbU9cwiA,189
2
2
  python3_commons/api_client.py,sha256=LT7_YmnYVHK2ucKxIhUJCZrmxgfy-lfOxx08-R0WvW0,4505
3
- python3_commons/audit.py,sha256=osx2ywZXf-V0zOkrhlNgSyzCBvojXQwSYBQ4-ze1xiM,6249
3
+ python3_commons/audit.py,sha256=-jYGjkQ2r8rg3gj-C-5uTQ1lXhK3dRXkktonZxOs1PM,5994
4
4
  python3_commons/auth.py,sha256=vVaiJ5MHUMSbiLF6TIxe4dqVPhBlLttf940jjODL3a4,2934
5
5
  python3_commons/cache.py,sha256=lf27LTD4Z9Iqi5GaK8jH8UC0cL9sHH8wicZ88YDp6Mg,7725
6
- python3_commons/conf.py,sha256=JenspXyTqTlYeEb8X9Njfje1AiLCee23nm0k8zhYLfs,2283
6
+ python3_commons/conf.py,sha256=K3GuXDp7iopHms_E-rNR4OzTBIoWSEZmMwRjxKYltTk,2305
7
7
  python3_commons/fs.py,sha256=wfLjybXndwLqNlOxTpm_HRJnuTcC4wbrHEOaEeCo9Wc,337
8
8
  python3_commons/helpers.py,sha256=qSBQ1A02BEmIY8UPJkCoO28aZq0BPsMg6AGW9k-CThM,3166
9
- python3_commons/object_storage.py,sha256=eF0EOB29yFn3oVr8y0SegEVJLo1W5gJT3IYcINEtLOU,6301
9
+ python3_commons/object_storage.py,sha256=FET3R5gI_v1UB0z9a0K-aC-mhvA6AuOEd-Wav6kgjCk,6295
10
10
  python3_commons/permissions.py,sha256=bhjTp-tq-oaTGFMHNnSBlcVX5XQCTL0nWcu6SdPEAB4,1555
11
11
  python3_commons/db/__init__.py,sha256=5nArsGm17e-pelpOwAeBKy2n_Py20XqklZsNgkcJ-DQ,2947
12
12
  python3_commons/db/helpers.py,sha256=PY0h08aLiGx-J54wmP3GHPCgGCcLd60rayAUnR3aWdI,1742
@@ -21,9 +21,9 @@ python3_commons/serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
21
21
  python3_commons/serializers/json.py,sha256=91UaXLGKGj0yPyrnuMeNrkG2GuPUgcgAsmIokUgEwpU,808
22
22
  python3_commons/serializers/msgpack.py,sha256=WrvaPE187shSK8zkH4UHHMimEZNMv9RaDSwsBE2HlCw,1269
23
23
  python3_commons/serializers/msgspec.py,sha256=0AliXlEl5sewi0UENjI8St5ZScXE5DNRERKzqWKy2Ps,2674
24
- python3_commons-0.8.36.dist-info/licenses/AUTHORS.rst,sha256=3R9JnfjfjH5RoPWOeqKFJgxVShSSfzQPIrEr1nxIo9Q,90
25
- python3_commons-0.8.36.dist-info/licenses/LICENSE,sha256=xxILuojHm4fKQOrMHPSslbyy6WuKAN2RiG74HbrYfzM,34575
26
- python3_commons-0.8.36.dist-info/METADATA,sha256=SRAoOrNJjXa2lxTv7ncHdEq6yMyPCVhsoggAHQp_rwE,1134
27
- python3_commons-0.8.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
- python3_commons-0.8.36.dist-info/top_level.txt,sha256=lJI6sCBf68eUHzupCnn2dzG10lH3jJKTWM_hrN1cQ7M,16
29
- python3_commons-0.8.36.dist-info/RECORD,,
24
+ python3_commons-0.9.1.dist-info/licenses/AUTHORS.rst,sha256=3R9JnfjfjH5RoPWOeqKFJgxVShSSfzQPIrEr1nxIo9Q,90
25
+ python3_commons-0.9.1.dist-info/licenses/LICENSE,sha256=xxILuojHm4fKQOrMHPSslbyy6WuKAN2RiG74HbrYfzM,34575
26
+ python3_commons-0.9.1.dist-info/METADATA,sha256=dv7fEarrTDewpnOVFIHk_Mud2nWcanfkMyQa4GWjGNk,1133
27
+ python3_commons-0.9.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ python3_commons-0.9.1.dist-info/top_level.txt,sha256=lJI6sCBf68eUHzupCnn2dzG10lH3jJKTWM_hrN1cQ7M,16
29
+ python3_commons-0.9.1.dist-info/RECORD,,