python3-commons 0.14.16__tar.gz → 0.14.18__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. {python3_commons-0.14.16 → python3_commons-0.14.18}/PKG-INFO +1 -1
  2. {python3_commons-0.14.16 → python3_commons-0.14.18}/pyproject.toml +1 -1
  3. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/api_client.py +1 -1
  4. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/audit.py +2 -2
  5. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/db/__init__.py +3 -3
  6. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/helpers.py +1 -1
  7. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/log/formatters.py +6 -3
  8. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/object_storage.py +9 -9
  9. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons.egg-info/PKG-INFO +1 -1
  10. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons.egg-info/SOURCES.txt +3 -1
  11. python3_commons-0.14.18/tests/unit/log/__init__.py +0 -0
  12. python3_commons-0.14.18/tests/unit/log/test_formatters.py +34 -0
  13. {python3_commons-0.14.16 → python3_commons-0.14.18}/.coveragerc +0 -0
  14. {python3_commons-0.14.16 → python3_commons-0.14.18}/.devcontainer/Dockerfile +0 -0
  15. {python3_commons-0.14.16 → python3_commons-0.14.18}/.devcontainer/devcontainer.json +0 -0
  16. {python3_commons-0.14.16 → python3_commons-0.14.18}/.devcontainer/docker-compose.yml +0 -0
  17. {python3_commons-0.14.16 → python3_commons-0.14.18}/.env_template +0 -0
  18. {python3_commons-0.14.16 → python3_commons-0.14.18}/.github/workflows/checks.yml +0 -0
  19. {python3_commons-0.14.16 → python3_commons-0.14.18}/.github/workflows/python-publish.yaml +0 -0
  20. {python3_commons-0.14.16 → python3_commons-0.14.18}/.github/workflows/release-on-tag-push.yml +0 -0
  21. {python3_commons-0.14.16 → python3_commons-0.14.18}/.gitignore +0 -0
  22. {python3_commons-0.14.16 → python3_commons-0.14.18}/.pre-commit-config.yaml +0 -0
  23. {python3_commons-0.14.16 → python3_commons-0.14.18}/.python-version +0 -0
  24. {python3_commons-0.14.16 → python3_commons-0.14.18}/AUTHORS.rst +0 -0
  25. {python3_commons-0.14.16 → python3_commons-0.14.18}/CHANGELOG.rst +0 -0
  26. {python3_commons-0.14.16 → python3_commons-0.14.18}/LICENSE +0 -0
  27. {python3_commons-0.14.16 → python3_commons-0.14.18}/README.md +0 -0
  28. {python3_commons-0.14.16 → python3_commons-0.14.18}/README.rst +0 -0
  29. {python3_commons-0.14.16 → python3_commons-0.14.18}/docs/Makefile +0 -0
  30. {python3_commons-0.14.16 → python3_commons-0.14.18}/docs/_static/.gitignore +0 -0
  31. {python3_commons-0.14.16 → python3_commons-0.14.18}/docs/authors.rst +0 -0
  32. {python3_commons-0.14.16 → python3_commons-0.14.18}/docs/changelog.rst +0 -0
  33. {python3_commons-0.14.16 → python3_commons-0.14.18}/docs/conf.py +0 -0
  34. {python3_commons-0.14.16 → python3_commons-0.14.18}/docs/index.rst +0 -0
  35. {python3_commons-0.14.16 → python3_commons-0.14.18}/docs/license.rst +0 -0
  36. {python3_commons-0.14.16 → python3_commons-0.14.18}/setup.cfg +0 -0
  37. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/__init__.py +0 -0
  38. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/auth.py +0 -0
  39. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/cache.py +0 -0
  40. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/conf.py +0 -0
  41. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/db/helpers.py +0 -0
  42. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/db/models/__init__.py +0 -0
  43. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/db/models/auth.py +0 -0
  44. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/db/models/common.py +0 -0
  45. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/exceptions.py +0 -0
  46. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/fs.py +0 -0
  47. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/generators.py +0 -0
  48. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/log/__init__.py +0 -0
  49. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/log/filters.py +0 -0
  50. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/serializers/__init__.py +0 -0
  51. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/serializers/common.py +0 -0
  52. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/serializers/json.py +0 -0
  53. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/serializers/msgpack.py +0 -0
  54. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons/serializers/msgspec.py +0 -0
  55. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons.egg-info/dependency_links.txt +0 -0
  56. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons.egg-info/requires.txt +0 -0
  57. {python3_commons-0.14.16 → python3_commons-0.14.18}/src/python3_commons.egg-info/top_level.txt +0 -0
  58. {python3_commons-0.14.16 → python3_commons-0.14.18}/tests/__init__.py +0 -0
  59. {python3_commons-0.14.16 → python3_commons-0.14.18}/tests/integration/__init__.py +0 -0
  60. {python3_commons-0.14.16 → python3_commons-0.14.18}/tests/integration/test_cache.py +0 -0
  61. {python3_commons-0.14.16 → python3_commons-0.14.18}/tests/unit/__init__.py +0 -0
  62. {python3_commons-0.14.16 → python3_commons-0.14.18}/tests/unit/conftest.py +0 -0
  63. {python3_commons-0.14.16 → python3_commons-0.14.18}/tests/unit/test_audit.py +0 -0
  64. {python3_commons-0.14.16 → python3_commons-0.14.18}/tests/unit/test_helpers.py +0 -0
  65. {python3_commons-0.14.16 → python3_commons-0.14.18}/tests/unit/test_msgpack.py +0 -0
  66. {python3_commons-0.14.16 → python3_commons-0.14.18}/tests/unit/test_msgspec.py +0 -0
  67. {python3_commons-0.14.16 → python3_commons-0.14.18}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python3-commons
3
- Version: 0.14.16
3
+ Version: 0.14.18
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
@@ -94,7 +94,7 @@ select = [
94
94
  "FBT",
95
95
  "FLY",
96
96
  "FURB",
97
- # "G",
97
+ "G",
98
98
  "ICN",
99
99
  "INP",
100
100
  "ISC",
@@ -79,7 +79,7 @@ async def request(
79
79
 
80
80
  client_method = getattr(client, method)
81
81
 
82
- logger.debug(f'Requesting {method} {url}')
82
+ logger.debug('Requesting %s %s', method, url)
83
83
 
84
84
  try:
85
85
  if method == 'get':
@@ -26,9 +26,9 @@ async def write_audit_data(settings: S3Settings, key: str, data: bytes) -> None:
26
26
  except Exception:
27
27
  logger.exception('Failed storing object in storage.')
28
28
  else:
29
- logger.debug(f'Stored object in storage: {key}')
29
+ logger.debug('Stored object in storage: %s', key)
30
30
  else:
31
- logger.debug(f'S3 is not configured, not storing object in storage: {key}')
31
+ logger.debug('S3 is not configured, not storing object in storage: %s', key)
32
32
 
33
33
 
34
34
  class ZeepAuditPlugin(Plugin):
@@ -26,7 +26,7 @@ class AsyncSessionManager:
26
26
  try:
27
27
  return self.db_settings[name]
28
28
  except KeyError:
29
- logger.exception(f'Missing database settings: {name}')
29
+ logger.exception('Missing database settings: %s', name)
30
30
 
31
31
  raise
32
32
 
@@ -47,7 +47,7 @@ class AsyncSessionManager:
47
47
  try:
48
48
  engine = self.engines[name]
49
49
  except KeyError:
50
- logger.debug(f'Creating engine: {name}')
50
+ logger.debug('Creating engine: %s', name)
51
51
  engine = self.async_engine_from_db_settings(name)
52
52
  self.engines[name] = engine
53
53
 
@@ -57,7 +57,7 @@ class AsyncSessionManager:
57
57
  try:
58
58
  session_maker = self.session_makers[name]
59
59
  except KeyError:
60
- logger.debug(f'Creating session maker: {name}')
60
+ logger.debug('Creating session maker: %s', name)
61
61
  engine = self.get_engine(name)
62
62
  session_maker = async_sessionmaker(engine, expire_on_commit=False)
63
63
  self.session_makers[name] = session_maker
@@ -133,7 +133,7 @@ def log_execution_time(func):
133
133
  return await func(*args, **kwargs)
134
134
  finally:
135
135
  elapsed = time.monotonic() - start_time
136
- _logger.info(f'{func.__module__}.{func.__name__} executed in {elapsed:.4f} seconds')
136
+ _logger.info('%s.%s executed in %.4f seconds', func.__module__, func.__name__, elapsed)
137
137
 
138
138
  wrapper.__signature__ = inspect.signature(func)
139
139
 
@@ -10,14 +10,17 @@ correlation_id: ContextVar[str | None] = ContextVar('correlation_id', default=No
10
10
 
11
11
  class JSONFormatter(logging.Formatter):
12
12
  @staticmethod
13
- def format_exception(exc_info):
13
+ def format_exception(exc_info: logging._SysExcInfoType) -> str:
14
14
  return ''.join(traceback.format_exception(*exc_info))
15
15
 
16
- def format(self, record):
16
+ def format(self, record: logging.LogRecord) -> str:
17
17
  if corr_id := correlation_id.get():
18
18
  record.correlation_id = corr_id
19
19
 
20
- record.message = record.getMessage()
20
+ try:
21
+ record.message = record.getMessage()
22
+ except TypeError:
23
+ record.message = str(record.msg)
21
24
 
22
25
  if record.exc_info:
23
26
  record.exc_text = self.format_exception(record.exc_info)
@@ -66,9 +66,9 @@ async def put_object(bucket_name: str, path: str, data: io.BytesIO, length: int,
66
66
 
67
67
  await s3_client.put_object(Bucket=bucket_name, Key=path, Body=data, ContentLength=length)
68
68
 
69
- logger.debug(f'Stored object into object storage: {bucket_name}:{path}')
69
+ logger.debug('Stored object into object storage: %s:%s', bucket_name, path)
70
70
  except Exception as e:
71
- logger.exception(f'Failed to put object to object storage: {bucket_name}:{path}', exc_info=e)
71
+ logger.exception('Failed to put object to object storage: %s:%s', bucket_name, path, exc_info=e)
72
72
 
73
73
  raise
74
74
 
@@ -80,7 +80,7 @@ async def get_object_stream(bucket_name: str, path: str) -> AsyncGenerator[Strea
80
80
  storage = ObjectStorage(s3_settings)
81
81
 
82
82
  async with storage.get_client() as s3_client:
83
- logger.debug(f'Getting object from object storage: {bucket_name}:{path}')
83
+ logger.debug('Getting object from object storage: %s:%s', bucket_name, path)
84
84
 
85
85
  try:
86
86
  response = await s3_client.get_object(Bucket=bucket_name, Key=path)
@@ -88,7 +88,7 @@ async def get_object_stream(bucket_name: str, path: str) -> AsyncGenerator[Strea
88
88
  async with response['Body'] as stream:
89
89
  yield stream
90
90
  except Exception as e:
91
- logger.exception(f'Failed getting object from object storage: {bucket_name}:{path}', exc_info=e)
91
+ logger.exception('Failed getting object from object storage: %s:%s', bucket_name, path, exc_info=e)
92
92
 
93
93
  raise
94
94
 
@@ -97,7 +97,7 @@ async def get_object(bucket_name: str, path: str) -> bytes:
97
97
  async with get_object_stream(bucket_name, path) as stream:
98
98
  body = await stream.read()
99
99
 
100
- logger.debug(f'Loaded object from object storage: {bucket_name}:{path}')
100
+ logger.debug('Loaded object from object storage: %s:%s', bucket_name, path)
101
101
 
102
102
  return body
103
103
 
@@ -142,9 +142,9 @@ async def remove_object(bucket_name: str, object_name: str) -> None:
142
142
  async with storage.get_client() as s3_client:
143
143
  try:
144
144
  await s3_client.delete_object(Bucket=bucket_name, Key=object_name)
145
- logger.debug(f'Removed object from object storage: {bucket_name}:{object_name}')
145
+ logger.debug('Removed object from object storage: %s:%s', bucket_name, object_name)
146
146
  except Exception as e:
147
- logger.exception(f'Failed to remove object from object storage: {bucket_name}:{object_name}', exc_info=e)
147
+ logger.exception('Failed to remove object from object storage: %s:%s', bucket_name, object_name, exc_info=e)
148
148
 
149
149
  raise
150
150
 
@@ -180,9 +180,9 @@ async def remove_objects(
180
180
  if 'Errors' in response:
181
181
  errors.extend(response['Errors'])
182
182
 
183
- logger.debug(f'Removed {len(objects_to_delete)} objects from object storage: {bucket_name}')
183
+ logger.debug('Removed %d objects from object storage: %s', len(objects_to_delete), bucket_name)
184
184
  except Exception as e:
185
- logger.exception(f'Failed to remove objects from object storage: {bucket_name}', exc_info=e)
185
+ logger.exception('Failed to remove objects from object storage: %s', bucket_name, exc_info=e)
186
186
 
187
187
  raise
188
188
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python3-commons
3
- Version: 0.14.16
3
+ Version: 0.14.18
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
@@ -60,4 +60,6 @@ tests/unit/conftest.py
60
60
  tests/unit/test_audit.py
61
61
  tests/unit/test_helpers.py
62
62
  tests/unit/test_msgpack.py
63
- tests/unit/test_msgspec.py
63
+ tests/unit/test_msgspec.py
64
+ tests/unit/log/__init__.py
65
+ tests/unit/log/test_formatters.py
File without changes
@@ -0,0 +1,34 @@
1
+ import json
2
+ from logging import INFO, LogRecord
3
+
4
+ import pytest
5
+
6
+ from python3_commons.log.formatters import JSONFormatter
7
+
8
+
9
+ def test_json_formatter_info_record() -> None:
10
+ formatter = JSONFormatter()
11
+ record = LogRecord(
12
+ name='test.log',
13
+ level=INFO,
14
+ pathname='/dev/null',
15
+ lineno=12345,
16
+ msg='This is a %s, %d, %s',
17
+ args=(
18
+ 'test',
19
+ 1234,
20
+ 'magic',
21
+ ),
22
+ exc_info=None,
23
+ )
24
+ expected_message = 'This is a test, 1234, magic'
25
+ formatted_record_str = formatter.format(record)
26
+ formatted_record = json.loads(formatted_record_str)
27
+
28
+ with pytest.raises(KeyError):
29
+ _ = formatted_record['msg']
30
+
31
+ with pytest.raises(KeyError):
32
+ _ = formatted_record['args']
33
+
34
+ assert formatted_record['message'] == expected_message