python3-commons 0.9.19__tar.gz → 0.9.20__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.

Potentially problematic release.


This version of python3-commons might be problematic. Click here for more details.

Files changed (58) hide show
  1. {python3_commons-0.9.19 → python3_commons-0.9.20}/PKG-INFO +1 -1
  2. {python3_commons-0.9.19 → python3_commons-0.9.20}/pyproject.toml +7 -4
  3. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/audit.py +2 -2
  4. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/auth.py +5 -5
  5. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/cache.py +22 -22
  6. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/db/__init__.py +3 -3
  7. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/helpers.py +2 -2
  8. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/object_storage.py +8 -9
  9. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons.egg-info/PKG-INFO +1 -1
  10. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons.egg-info/SOURCES.txt +1 -0
  11. python3_commons-0.9.20/tests/__init__.py +0 -0
  12. {python3_commons-0.9.19 → python3_commons-0.9.20}/.coveragerc +0 -0
  13. {python3_commons-0.9.19 → python3_commons-0.9.20}/.github/workflows/python-publish.yaml +0 -0
  14. {python3_commons-0.9.19 → python3_commons-0.9.20}/.github/workflows/release-on-tag-push.yml +0 -0
  15. {python3_commons-0.9.19 → python3_commons-0.9.20}/.gitignore +0 -0
  16. {python3_commons-0.9.19 → python3_commons-0.9.20}/.pre-commit-config.yaml +0 -0
  17. {python3_commons-0.9.19 → python3_commons-0.9.20}/.python-version +0 -0
  18. {python3_commons-0.9.19 → python3_commons-0.9.20}/AUTHORS.rst +0 -0
  19. {python3_commons-0.9.19 → python3_commons-0.9.20}/CHANGELOG.rst +0 -0
  20. {python3_commons-0.9.19 → python3_commons-0.9.20}/LICENSE +0 -0
  21. {python3_commons-0.9.19 → python3_commons-0.9.20}/README.md +0 -0
  22. {python3_commons-0.9.19 → python3_commons-0.9.20}/README.rst +0 -0
  23. {python3_commons-0.9.19 → python3_commons-0.9.20}/docs/Makefile +0 -0
  24. {python3_commons-0.9.19 → python3_commons-0.9.20}/docs/_static/.gitignore +0 -0
  25. {python3_commons-0.9.19 → python3_commons-0.9.20}/docs/authors.rst +0 -0
  26. {python3_commons-0.9.19 → python3_commons-0.9.20}/docs/changelog.rst +0 -0
  27. {python3_commons-0.9.19 → python3_commons-0.9.20}/docs/conf.py +0 -0
  28. {python3_commons-0.9.19 → python3_commons-0.9.20}/docs/index.rst +0 -0
  29. {python3_commons-0.9.19 → python3_commons-0.9.20}/docs/license.rst +0 -0
  30. {python3_commons-0.9.19 → python3_commons-0.9.20}/setup.cfg +0 -0
  31. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/__init__.py +0 -0
  32. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/api_client.py +0 -0
  33. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/conf.py +0 -0
  34. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/db/helpers.py +0 -0
  35. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/db/models/__init__.py +0 -0
  36. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/db/models/auth.py +0 -0
  37. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/db/models/common.py +0 -0
  38. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/db/models/rbac.py +0 -0
  39. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/fs.py +0 -0
  40. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/log/__init__.py +0 -0
  41. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/log/filters.py +0 -0
  42. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/log/formatters.py +0 -0
  43. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/permissions.py +0 -0
  44. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/serializers/__init__.py +0 -0
  45. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/serializers/common.py +0 -0
  46. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/serializers/json.py +0 -0
  47. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/serializers/msgpack.py +0 -0
  48. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons/serializers/msgspec.py +0 -0
  49. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons.egg-info/dependency_links.txt +0 -0
  50. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons.egg-info/requires.txt +0 -0
  51. {python3_commons-0.9.19 → python3_commons-0.9.20}/src/python3_commons.egg-info/top_level.txt +0 -0
  52. {python3_commons-0.9.19 → python3_commons-0.9.20}/tests/conftest.py +0 -0
  53. {python3_commons-0.9.19 → python3_commons-0.9.20}/tests/test_audit.py +0 -0
  54. {python3_commons-0.9.19 → python3_commons-0.9.20}/tests/test_cache.py +0 -0
  55. {python3_commons-0.9.19 → python3_commons-0.9.20}/tests/test_helpers.py +0 -0
  56. {python3_commons-0.9.19 → python3_commons-0.9.20}/tests/test_msgpack.py +0 -0
  57. {python3_commons-0.9.19 → python3_commons-0.9.20}/tests/test_msgspec.py +0 -0
  58. {python3_commons-0.9.19 → python3_commons-0.9.20}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python3-commons
3
- Version: 0.9.19
3
+ Version: 0.9.20
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
@@ -87,7 +87,7 @@ select = [
87
87
  "A",
88
88
  # "ARG",
89
89
  "ASYNC",
90
- # "B",
90
+ "B",
91
91
  "C4",
92
92
  # "DTZ",
93
93
  "EM",
@@ -99,7 +99,7 @@ select = [
99
99
  "FURB",
100
100
  # "G",
101
101
  "ICN",
102
- # "INP",
102
+ "INP",
103
103
  "ISC",
104
104
  "LOG",
105
105
  "N",
@@ -117,20 +117,23 @@ select = [
117
117
  # "RET",
118
118
  "RSE",
119
119
  # "RUF",
120
- # "S",
120
+ "S",
121
121
  "SIM",
122
122
  "SLF",
123
123
  "SLOT",
124
124
  "T20",
125
125
  "TC",
126
126
  "TID",
127
- # "TRY",
127
+ "TRY",
128
128
  "UP",
129
129
  ]
130
130
  ignore = [
131
131
  "ASYNC109",
132
132
  ]
133
133
 
134
+ [tool.ruff.lint.per-file-ignores]
135
+ "tests/*.py" = ["S101"]
136
+
134
137
  [tool.ruff.lint.flake8-quotes]
135
138
  docstring-quotes = "double"
136
139
  inline-quotes = "single"
@@ -143,8 +143,8 @@ async def write_audit_data(settings: S3Settings, key: str, data: bytes):
143
143
  absolute_path = object_storage.get_absolute_path(f'audit/{key}')
144
144
 
145
145
  await object_storage.put_object(settings.s3_bucket, absolute_path, io.BytesIO(data), len(data))
146
- except Exception as e:
147
- logger.error(f'Failed storing object in storage: {e}')
146
+ except Exception:
147
+ logger.exception('Failed storing object in storage.')
148
148
  else:
149
149
  logger.debug(f'Stored object in storage: {key}')
150
150
  else:
@@ -78,11 +78,11 @@ def get_token_verifier[T](
78
78
  payload = jwt.decode(token, jwks, algorithms=['RS256'])
79
79
 
80
80
  token_data = token_cls(**payload)
81
-
82
- return token_data
83
- except jwt.ExpiredSignatureError:
84
- raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED, detail='Token has expired')
81
+ except jwt.ExpiredSignatureError as e:
82
+ raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED, detail='Token has expired') from e
85
83
  except JWTError as e:
86
- raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED, detail=f'Token is invalid: {str(e)}')
84
+ raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED, detail=f'Token is invalid: {str(e)}') from e
85
+
86
+ return token_data
87
87
 
88
88
  return get_verified_token
@@ -131,8 +131,8 @@ async def store_sequence(name: str, data: Sequence, ttl: int = None):
131
131
 
132
132
  if ttl:
133
133
  await r.expire(name, ttl)
134
- except valkey.exceptions.ConnectionError as e:
135
- logger.error(f'Failed to store sequence in cache: {e}')
134
+ except valkey.exceptions.ConnectionError:
135
+ logger.exception('Failed to store sequence in cache.')
136
136
 
137
137
 
138
138
  async def get_sequence(name: str, _type: type = list) -> Sequence:
@@ -151,8 +151,8 @@ async def store_dict(name: str, data: Mapping, ttl: int = None):
151
151
 
152
152
  if ttl:
153
153
  await r.expire(name, ttl)
154
- except valkey.exceptions.ConnectionError as e:
155
- logger.error(f'Failed to store dict in cache: {e}')
154
+ except valkey.exceptions.ConnectionError:
155
+ logger.exception('Failed to store dict in cache.')
156
156
 
157
157
 
158
158
  async def get_dict(name: str, value_data_type=None) -> dict | None:
@@ -175,8 +175,8 @@ async def set_dict(name: str, mapping: dict, ttl: int = None):
175
175
 
176
176
  if ttl:
177
177
  await r.expire(name, ttl)
178
- except valkey.exceptions.ConnectionError as e:
179
- logger.error(f'Failed to set dict in cache: {e}')
178
+ except valkey.exceptions.ConnectionError:
179
+ logger.exception('Failed to set dict in cache.')
180
180
 
181
181
 
182
182
  async def get_dict_item(name: str, key: str, data_type=None, default=None):
@@ -185,28 +185,28 @@ async def get_dict_item(name: str, key: str, data_type=None, default=None):
185
185
 
186
186
  if data := await r.hget(name, key):
187
187
  return deserialize_msgpack_native(data, data_type)
188
+ except valkey.exceptions.ConnectionError:
189
+ logger.exception('Failed to get dict item from cache.')
188
190
 
189
- return default
190
- except valkey.exceptions.ConnectionError as e:
191
- logger.error(f'Failed to get dict item from cache: {e}')
191
+ return None
192
192
 
193
- return None
193
+ return default
194
194
 
195
195
 
196
196
  async def set_dict_item(name: str, key: str, obj: Any):
197
197
  try:
198
198
  r = get_valkey_client()
199
199
  await r.hset(name, key, serialize_msgpack_native(obj))
200
- except valkey.exceptions.ConnectionError as e:
201
- logger.error(f'Failed to set dict item in cache: {e}')
200
+ except valkey.exceptions.ConnectionError:
201
+ logger.exception('Failed to set dict item in cache.')
202
202
 
203
203
 
204
204
  async def delete_dict_item(name: str, *keys):
205
205
  try:
206
206
  r = get_valkey_client()
207
207
  await r.hdel(name, *keys)
208
- except valkey.exceptions.ConnectionError as e:
209
- logger.error(f'Failed to delete dict item from cache: {e}')
208
+ except valkey.exceptions.ConnectionError:
209
+ logger.exception('Failed to delete dict item from cache.')
210
210
 
211
211
 
212
212
  async def store_set(name: str, value: set, ttl: int = None):
@@ -216,8 +216,8 @@ async def store_set(name: str, value: set, ttl: int = None):
216
216
 
217
217
  if ttl:
218
218
  await r.expire(name, ttl)
219
- except valkey.exceptions.ConnectionError as e:
220
- logger.error(f'Failed to store set in cache: {e}')
219
+ except valkey.exceptions.ConnectionError:
220
+ logger.exception('Failed to store set in cache.')
221
221
 
222
222
 
223
223
  async def has_set_item(name: str, value: str) -> bool:
@@ -225,8 +225,8 @@ async def has_set_item(name: str, value: str) -> bool:
225
225
  r = get_valkey_client()
226
226
 
227
227
  return await r.sismember(name, serialize_msgpack_native(value)) == 1
228
- except valkey.exceptions.ConnectionError as e:
229
- logger.error(f'Failed to check if set has item in cache: {e}')
228
+ except valkey.exceptions.ConnectionError:
229
+ logger.exception('Failed to check if set has item in cache.')
230
230
 
231
231
  return False
232
232
 
@@ -235,8 +235,8 @@ async def add_set_item(name: str, *values: str):
235
235
  try:
236
236
  r = get_valkey_client()
237
237
  await r.sadd(name, *map(serialize_msgpack_native, values))
238
- except valkey.exceptions.ConnectionError as e:
239
- logger.error(f'Failed to add set item into cache: {e}')
238
+ except valkey.exceptions.ConnectionError:
239
+ logger.exception('Failed to add set item into cache.')
240
240
 
241
241
 
242
242
  async def delete_set_item(name: str, value: str):
@@ -250,8 +250,8 @@ async def get_set_members(name: str) -> set[str] | None:
250
250
  smembers = await r.smembers(name)
251
251
 
252
252
  return set(map(deserialize_msgpack_native, smembers))
253
- except valkey.exceptions.ConnectionError as e:
254
- logger.error(f'Failed to get set members from cache: {e}')
253
+ except valkey.exceptions.ConnectionError:
254
+ logger.exception('Failed to get set members from cache.')
255
255
 
256
256
  return None
257
257
 
@@ -24,7 +24,7 @@ class AsyncSessionManager:
24
24
  try:
25
25
  return self.db_settings[name]
26
26
  except KeyError:
27
- logger.error(f'Missing database settings: {name}')
27
+ logger.exception(f'Missing database settings: {name}')
28
28
 
29
29
  raise
30
30
 
@@ -83,7 +83,7 @@ async def is_healthy(engine: AsyncEngine) -> bool:
83
83
  result = await conn.execute('SELECT 1;')
84
84
 
85
85
  return result.scalar() == 1
86
- except Exception as e:
87
- logger.error(f'Database connection is not healthy: {e}')
86
+ except Exception:
87
+ logger.exception('Database connection is not healthy.')
88
88
 
89
89
  return False
@@ -67,9 +67,9 @@ def tries(times):
67
67
  # noinspection PyBroadException
68
68
  try:
69
69
  return await f(*args, **kwargs)
70
- except Exception as exc:
70
+ except Exception:
71
71
  if _time >= times:
72
- raise exc
72
+ raise
73
73
 
74
74
  return wrapper
75
75
 
@@ -67,14 +67,13 @@ async def put_object(bucket_name: str, path: str, data: io.BytesIO, length: int,
67
67
  await s3_client.put_object(Bucket=bucket_name, Key=path, Body=data, ContentLength=length)
68
68
 
69
69
  logger.debug(f'Stored object into object storage: {bucket_name}:{path}')
70
-
71
- return f's3://{bucket_name}/{path}'
72
-
73
70
  except Exception as e:
74
- logger.error(f'Failed to put object to object storage: {bucket_name}:{path}', exc_info=e)
71
+ logger.exception(f'Failed to put object to object storage: {bucket_name}:{path}', exc_info=e)
75
72
 
76
73
  raise
77
74
 
75
+ return f's3://{bucket_name}/{path}'
76
+
78
77
 
79
78
  @asynccontextmanager
80
79
  async def get_object_stream(bucket_name: str, path: str) -> AsyncGenerator[StreamingBody]:
@@ -89,7 +88,7 @@ async def get_object_stream(bucket_name: str, path: str) -> AsyncGenerator[Strea
89
88
  async with response['Body'] as stream:
90
89
  yield stream
91
90
  except Exception as e:
92
- logger.debug(f'Failed getting object from object storage: {bucket_name}:{path}', exc_info=e)
91
+ logger.exception(f'Failed getting object from object storage: {bucket_name}:{path}', exc_info=e)
93
92
 
94
93
  raise
95
94
 
@@ -145,7 +144,7 @@ async def remove_object(bucket_name: str, object_name: str):
145
144
  await s3_client.delete_object(Bucket=bucket_name, Key=object_name)
146
145
  logger.debug(f'Removed object from object storage: {bucket_name}:{object_name}')
147
146
  except Exception as e:
148
- logger.error(f'Failed to remove object from object storage: {bucket_name}:{object_name}', exc_info=e)
147
+ logger.exception(f'Failed to remove object from object storage: {bucket_name}:{object_name}', exc_info=e)
149
148
 
150
149
  raise
151
150
 
@@ -182,9 +181,9 @@ async def remove_objects(
182
181
  errors.extend(response['Errors'])
183
182
 
184
183
  logger.debug(f'Removed {len(objects_to_delete)} objects from object storage: {bucket_name}')
185
-
186
- return errors if errors else None
187
184
  except Exception as e:
188
- logger.error(f'Failed to remove objects from object storage: {bucket_name}', exc_info=e)
185
+ logger.exception(f'Failed to remove objects from object storage: {bucket_name}', exc_info=e)
189
186
 
190
187
  raise
188
+
189
+ return errors if errors else None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python3-commons
3
- Version: 0.9.19
3
+ Version: 0.9.20
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
@@ -47,6 +47,7 @@ src/python3_commons/serializers/common.py
47
47
  src/python3_commons/serializers/json.py
48
48
  src/python3_commons/serializers/msgpack.py
49
49
  src/python3_commons/serializers/msgspec.py
50
+ tests/__init__.py
50
51
  tests/conftest.py
51
52
  tests/test_audit.py
52
53
  tests/test_cache.py
File without changes