hexkit 7.0.0__tar.gz → 7.1.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.
Files changed (64) hide show
  1. {hexkit-7.0.0/src/hexkit.egg-info → hexkit-7.1.0}/PKG-INFO +21 -22
  2. {hexkit-7.0.0 → hexkit-7.1.0}/pyproject.toml +26 -28
  3. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/config.py +5 -4
  4. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/custom_types.py +12 -14
  5. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/log.py +3 -3
  6. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/protocols/dao.py +5 -5
  7. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/protocols/daopub.py +5 -6
  8. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/protocols/eventpub.py +2 -3
  9. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/protocols/objstorage.py +20 -24
  10. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/config.py +2 -2
  11. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/provider/daosub.py +1 -2
  12. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/provider/eventpub.py +4 -4
  13. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/provider/eventsub.py +11 -11
  14. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/provider/utils.py +1 -2
  15. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/testcontainer.py +6 -6
  16. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/testutils.py +14 -14
  17. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/migrations/_manager.py +2 -2
  18. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/migrations/_utils.py +5 -5
  19. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/migrations/helpers.py +2 -3
  20. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/provider.py +4 -4
  21. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/testutils.py +2 -3
  22. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/provider/daopub.py +5 -5
  23. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/provider/persistent_pub.py +3 -4
  24. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/provider.py +47 -46
  25. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/testutils/_fixtures.py +6 -6
  26. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/testing/eventpub.py +2 -2
  27. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/utils.py +2 -2
  28. {hexkit-7.0.0 → hexkit-7.1.0/src/hexkit.egg-info}/PKG-INFO +21 -22
  29. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit.egg-info/requires.txt +19 -19
  30. {hexkit-7.0.0 → hexkit-7.1.0}/LICENSE +0 -0
  31. {hexkit-7.0.0 → hexkit-7.1.0}/MANIFEST.in +0 -0
  32. {hexkit-7.0.0 → hexkit-7.1.0}/README.md +0 -0
  33. {hexkit-7.0.0 → hexkit-7.1.0}/setup.cfg +0 -0
  34. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/__init__.py +0 -0
  35. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/__main__.py +0 -0
  36. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/base.py +0 -0
  37. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/correlation.py +0 -0
  38. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/opentelemetry.py +0 -0
  39. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/protocols/__init__.py +0 -0
  40. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/protocols/daosub.py +0 -0
  41. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/protocols/eventsub.py +0 -0
  42. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/__init__.py +0 -0
  43. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/__init__.py +0 -0
  44. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/provider/__init__.py +0 -0
  45. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/__init__.py +0 -0
  46. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/migrations/__init__.py +0 -0
  47. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/__init__.py +0 -0
  48. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/provider/__init__.py +0 -0
  49. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/provider/config.py +0 -0
  50. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/testutils.py +0 -0
  51. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/__init__.py +0 -0
  52. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/test_files/__init__.py +0 -0
  53. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/test_files/test_file1.yaml +0 -0
  54. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/test_files/test_file2.yaml +0 -0
  55. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/test_files/test_file3.yaml +0 -0
  56. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/test_files/test_file4.yaml +0 -0
  57. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/testutils/__init__.py +0 -0
  58. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/testutils/_typical_workflow.py +0 -0
  59. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/testutils/_utils.py +0 -0
  60. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/providers/testing/__init__.py +0 -0
  61. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit/py.typed +0 -0
  62. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit.egg-info/SOURCES.txt +0 -0
  63. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit.egg-info/dependency_links.txt +0 -0
  64. {hexkit-7.0.0 → hexkit-7.1.0}/src/hexkit.egg-info/top_level.txt +0 -0
@@ -1,13 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hexkit
3
- Version: 7.0.0
3
+ Version: 7.1.0
4
4
  Summary: A Toolkit for Building Microservices using the Hexagonal Architecture
5
5
  Author-email: "German Human Genome Phenome Archive (GHGA)" <contact@ghga.de>
6
6
  License: Apache 2.0
7
7
  Project-URL: Repository, https://github.com/ghga-de/hexkit
8
8
  Classifier: Development Status :: 5 - Production/Stable
9
9
  Classifier: Operating System :: POSIX :: Linux
10
- Classifier: Programming Language :: Python :: 3.9
11
10
  Classifier: Programming Language :: Python :: 3.10
12
11
  Classifier: Programming Language :: Python :: 3.11
13
12
  Classifier: Programming Language :: Python :: 3.12
@@ -16,42 +15,42 @@ Classifier: License :: OSI Approved :: Apache Software License
16
15
  Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
17
16
  Classifier: Topic :: Software Development :: Libraries
18
17
  Classifier: Intended Audience :: Developers
19
- Requires-Python: >=3.9
18
+ Requires-Python: >=3.10
20
19
  Description-Content-Type: text/markdown
21
20
  License-File: LICENSE
22
- Requires-Dist: opentelemetry-api<2,>=1.31.1
23
- Requires-Dist: pydantic<3,>=2.10
24
- Requires-Dist: pydantic_settings<3,>=2.8
21
+ Requires-Dist: opentelemetry-api<2,>=1.37
22
+ Requires-Dist: pydantic<3,>=2.11
23
+ Requires-Dist: pydantic_settings<3,>=2.10
25
24
  Requires-Dist: PyYAML<7,>=6
26
25
  Provides-Extra: akafka
27
26
  Requires-Dist: aiokafka[lz4,snappy,zstd]~=0.12.0; extra == "akafka"
28
- Requires-Dist: jsonschema<5,>=4.23; extra == "akafka"
27
+ Requires-Dist: jsonschema<5,>=4.25; extra == "akafka"
29
28
  Provides-Extra: s3
30
- Requires-Dist: boto3<2,>=1.37; extra == "s3"
31
- Requires-Dist: botocore<2,>=1.37; extra == "s3"
29
+ Requires-Dist: boto3<2,>=1.40; extra == "s3"
30
+ Requires-Dist: botocore<2,>=1.40; extra == "s3"
32
31
  Provides-Extra: mongodb
33
- Requires-Dist: pymongo<5,>=4.13; extra == "mongodb"
32
+ Requires-Dist: pymongo<5,>=4.15; extra == "mongodb"
34
33
  Provides-Extra: opentelemetry-base
35
- Requires-Dist: opentelemetry-sdk<2,>=1.35.0; extra == "opentelemetry-base"
36
- Requires-Dist: opentelemetry-exporter-otlp<2,>=1.35.0; extra == "opentelemetry-base"
37
- Requires-Dist: opentelemetry-instrumentation>=0.56b0; extra == "opentelemetry-base"
38
- Requires-Dist: opentelemetry-instrumentation-httpx>=0.56b0; extra == "opentelemetry-base"
39
- Requires-Dist: opentelemetry-distro>=0.56b0; extra == "opentelemetry-base"
34
+ Requires-Dist: opentelemetry-sdk<2,>=1.37.0; extra == "opentelemetry-base"
35
+ Requires-Dist: opentelemetry-exporter-otlp<2,>=1.37.0; extra == "opentelemetry-base"
36
+ Requires-Dist: opentelemetry-instrumentation>=0.58b0; extra == "opentelemetry-base"
37
+ Requires-Dist: opentelemetry-instrumentation-httpx>=0.58b0; extra == "opentelemetry-base"
38
+ Requires-Dist: opentelemetry-distro>=0.58b0; extra == "opentelemetry-base"
40
39
  Provides-Extra: opentelemetry-akafka
41
40
  Requires-Dist: hexkit[opentelemetry-base]; extra == "opentelemetry-akafka"
42
41
  Requires-Dist: hexkit[akafka]; extra == "opentelemetry-akafka"
43
- Requires-Dist: opentelemetry-instrumentation-aiokafka>=0.56b0; extra == "opentelemetry-akafka"
42
+ Requires-Dist: opentelemetry-instrumentation-aiokafka>=0.58b0; extra == "opentelemetry-akafka"
44
43
  Provides-Extra: opentelemetry-mongodb
45
44
  Requires-Dist: hexkit[opentelemetry-base]; extra == "opentelemetry-mongodb"
46
45
  Requires-Dist: hexkit[mongodb]; extra == "opentelemetry-mongodb"
47
- Requires-Dist: opentelemetry-instrumentation-pymongo>=0.56b0; extra == "opentelemetry-mongodb"
46
+ Requires-Dist: opentelemetry-instrumentation-pymongo>=0.58b0; extra == "opentelemetry-mongodb"
48
47
  Provides-Extra: opentelemetry-fastapi
49
48
  Requires-Dist: hexkit[opentelemetry-base]; extra == "opentelemetry-fastapi"
50
- Requires-Dist: opentelemetry-instrumentation-fastapi>=0.56b0; extra == "opentelemetry-fastapi"
49
+ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.58b0; extra == "opentelemetry-fastapi"
51
50
  Provides-Extra: opentelemetry-s3
52
51
  Requires-Dist: hexkit[opentelemetry-base]; extra == "opentelemetry-s3"
53
52
  Requires-Dist: hexkit[s3]; extra == "opentelemetry-s3"
54
- Requires-Dist: opentelemetry-instrumentation-botocore>=0.56b0; extra == "opentelemetry-s3"
53
+ Requires-Dist: opentelemetry-instrumentation-botocore>=0.58b0; extra == "opentelemetry-s3"
55
54
  Provides-Extra: opentelemetry
56
55
  Requires-Dist: hexkit[opentelemetry-akafka]; extra == "opentelemetry"
57
56
  Requires-Dist: hexkit[opentelemetry-mongodb]; extra == "opentelemetry"
@@ -59,13 +58,13 @@ Requires-Dist: hexkit[opentelemetry-fastapi]; extra == "opentelemetry"
59
58
  Requires-Dist: hexkit[opentelemetry-s3]; extra == "opentelemetry"
60
59
  Provides-Extra: test-akafka
61
60
  Requires-Dist: hexkit[akafka]; extra == "test-akafka"
62
- Requires-Dist: testcontainers[kafka]<5,>=4.9; extra == "test-akafka"
61
+ Requires-Dist: testcontainers[kafka]<5,>=4.13; extra == "test-akafka"
63
62
  Provides-Extra: test-s3
64
63
  Requires-Dist: hexkit[s3]; extra == "test-s3"
65
- Requires-Dist: testcontainers<5,>=4.9; extra == "test-s3"
64
+ Requires-Dist: testcontainers<5,>=4.13; extra == "test-s3"
66
65
  Provides-Extra: test-mongodb
67
66
  Requires-Dist: hexkit[mongodb]; extra == "test-mongodb"
68
- Requires-Dist: testcontainers[mongo]<5,>=4.9; extra == "test-mongodb"
67
+ Requires-Dist: testcontainers[mongo]<5,>=4.13; extra == "test-mongodb"
69
68
  Provides-Extra: test
70
69
  Requires-Dist: hexkit[test-akafka,test-mongodb,test-s3]; extra == "test"
71
70
  Provides-Extra: all
@@ -1,6 +1,6 @@
1
1
  [build-system]
2
2
  requires = [
3
- "setuptools>=80.3",
3
+ "setuptools>=80.9",
4
4
  ]
5
5
  build-backend = "setuptools.build_meta"
6
6
 
@@ -9,11 +9,10 @@ readme = "README.md"
9
9
  authors = [
10
10
  { name = "German Human Genome Phenome Archive (GHGA)", email = "contact@ghga.de" },
11
11
  ]
12
- requires-python = ">=3.9"
12
+ requires-python = ">=3.10"
13
13
  classifiers = [
14
14
  "Development Status :: 5 - Production/Stable",
15
15
  "Operating System :: POSIX :: Linux",
16
- "Programming Language :: Python :: 3.9",
17
16
  "Programming Language :: Python :: 3.10",
18
17
  "Programming Language :: Python :: 3.11",
19
18
  "Programming Language :: Python :: 3.12",
@@ -24,12 +23,12 @@ classifiers = [
24
23
  "Intended Audience :: Developers",
25
24
  ]
26
25
  name = "hexkit"
27
- version = "7.0.0"
26
+ version = "7.1.0"
28
27
  description = "A Toolkit for Building Microservices using the Hexagonal Architecture"
29
28
  dependencies = [
30
- "opentelemetry-api >=1.31.1, <2",
31
- "pydantic >=2.10, <3",
32
- "pydantic_settings >=2.8, <3",
29
+ "opentelemetry-api >=1.37, <2",
30
+ "pydantic >=2.11, <3",
31
+ "pydantic_settings >=2.10, <3",
33
32
  "PyYAML >=6, <7",
34
33
  ]
35
34
 
@@ -39,40 +38,40 @@ text = "Apache 2.0"
39
38
  [project.optional-dependencies]
40
39
  akafka = [
41
40
  "aiokafka[zstd,lz4,snappy]~=0.12.0",
42
- "jsonschema >=4.23, <5",
41
+ "jsonschema >=4.25, <5",
43
42
  ]
44
43
  s3 = [
45
- "boto3 >=1.37, <2",
46
- "botocore >=1.37, <2",
44
+ "boto3 >=1.40, <2",
45
+ "botocore >=1.40, <2",
47
46
  ]
48
47
  mongodb = [
49
- "pymongo >=4.13, <5",
48
+ "pymongo >=4.15, <5",
50
49
  ]
51
50
  opentelemetry-base = [
52
- "opentelemetry-sdk >=1.35.0, <2",
53
- "opentelemetry-exporter-otlp >=1.35.0, <2",
54
- "opentelemetry-instrumentation >=0.56b0",
55
- "opentelemetry-instrumentation-httpx >=0.56b0",
56
- "opentelemetry-distro >=0.56b0",
51
+ "opentelemetry-sdk >=1.37.0, <2",
52
+ "opentelemetry-exporter-otlp >=1.37.0, <2",
53
+ "opentelemetry-instrumentation >=0.58b0",
54
+ "opentelemetry-instrumentation-httpx >=0.58b0",
55
+ "opentelemetry-distro >=0.58b0",
57
56
  ]
58
57
  opentelemetry-akafka = [
59
58
  "hexkit[opentelemetry-base]",
60
59
  "hexkit[akafka]",
61
- "opentelemetry-instrumentation-aiokafka >=0.56b0",
60
+ "opentelemetry-instrumentation-aiokafka >=0.58b0",
62
61
  ]
63
62
  opentelemetry-mongodb = [
64
63
  "hexkit[opentelemetry-base]",
65
64
  "hexkit[mongodb]",
66
- "opentelemetry-instrumentation-pymongo >=0.56b0",
65
+ "opentelemetry-instrumentation-pymongo >=0.58b0",
67
66
  ]
68
67
  opentelemetry-fastapi = [
69
68
  "hexkit[opentelemetry-base]",
70
- "opentelemetry-instrumentation-fastapi >=0.56b0",
69
+ "opentelemetry-instrumentation-fastapi >=0.58b0",
71
70
  ]
72
71
  opentelemetry-s3 = [
73
72
  "hexkit[opentelemetry-base]",
74
73
  "hexkit[s3]",
75
- "opentelemetry-instrumentation-botocore >=0.56b0",
74
+ "opentelemetry-instrumentation-botocore >=0.58b0",
76
75
  ]
77
76
  opentelemetry = [
78
77
  "hexkit[opentelemetry-akafka]",
@@ -82,15 +81,15 @@ opentelemetry = [
82
81
  ]
83
82
  test-akafka = [
84
83
  "hexkit[akafka]",
85
- "testcontainers[kafka] >=4.9, <5",
84
+ "testcontainers[kafka] >=4.13, <5",
86
85
  ]
87
86
  test-s3 = [
88
87
  "hexkit[s3]",
89
- "testcontainers >=4.9, <5",
88
+ "testcontainers >=4.13, <5",
90
89
  ]
91
90
  test-mongodb = [
92
91
  "hexkit[mongodb]",
93
- "testcontainers[mongo] >=4.9, <5",
92
+ "testcontainers[mongo] >=4.13, <5",
94
93
  ]
95
94
  test = [
96
95
  "hexkit[test-akafka,test-s3,test-mongodb]",
@@ -123,7 +122,7 @@ src = [
123
122
  "examples",
124
123
  "scripts",
125
124
  ]
126
- target-version = "py39"
125
+ target-version = "py310"
127
126
 
128
127
  [tool.ruff.lint]
129
128
  fixable = [
@@ -210,7 +209,7 @@ check_untyped_defs = true
210
209
  no_site_packages = false
211
210
 
212
211
  [tool.pytest.ini_options]
213
- minversion = "8.3"
212
+ minversion = "8.4"
214
213
  asyncio_mode = "strict"
215
214
  asyncio_default_fixture_loop_scope = "function"
216
215
 
@@ -224,11 +223,10 @@ source = [
224
223
  [tool.tox]
225
224
  legacy_tox_ini = """
226
225
  [tox]
227
- env_list = py3{9,10,11,12,13}
226
+ env_list = py3{10,11,12,13}
228
227
 
229
228
  [gh-actions]
230
229
  python =
231
- 3.9: py39
232
230
  3.10: py310
233
231
  3.11: py311
234
232
  3.12: py312
@@ -241,6 +239,6 @@ legacy_tox_ini = """
241
239
  deps =
242
240
  --no-deps -r ./lock/requirements-dev.txt
243
241
  commands =
244
- py3{9,10}: pip install --no-deps backports.asyncio.runner==1.2.0 exceptiongroup==1.3.0 tomli==2.2.1
242
+ py310: pip install --no-deps backports.asyncio.runner==1.2.0 exceptiongroup==1.3.0 tomli==2.2.1
245
243
  pytest {posargs}
246
244
  """
@@ -16,8 +16,9 @@
16
16
  """Config parsing functionality based on pydantic's BaseSettings"""
17
17
 
18
18
  import os
19
+ from collections.abc import Callable
19
20
  from pathlib import Path
20
- from typing import Callable, Final, Optional
21
+ from typing import Final
21
22
 
22
23
  from pydantic_settings import (
23
24
  BaseSettings,
@@ -33,7 +34,7 @@ DEFAULT_CONFIG_PREFIX: Final = "ghga_services"
33
34
  class ConfigYamlDoesNotExist(RuntimeError):
34
35
  """Thrown when the context manager is used out of context."""
35
36
 
36
- def __init__(self, path: Path, specified_via: Optional[str] = None):
37
+ def __init__(self, path: Path, specified_via: str | None = None):
37
38
  message = (
38
39
  "The config yaml " + ""
39
40
  if specified_via is None
@@ -42,7 +43,7 @@ class ConfigYamlDoesNotExist(RuntimeError):
42
43
  super().__init__(message)
43
44
 
44
45
 
45
- def get_default_config_yaml(prefix: str) -> Optional[Path]:
46
+ def get_default_config_yaml(prefix: str) -> Path | None:
46
47
  """Get the path to the default config function.
47
48
 
48
49
  Args:
@@ -122,7 +123,7 @@ def config_from_yaml(
122
123
  )
123
124
 
124
125
  def constructor_wrapper(
125
- config_yaml: Optional[Path] = None,
126
+ config_yaml: Path | None = None,
126
127
  **kwargs,
127
128
  ):
128
129
  """A wrapper for constructing a pydantic BaseSetting with modified sources
@@ -18,29 +18,27 @@
18
18
 
19
19
  from collections.abc import Mapping, Sequence
20
20
  from datetime import date, datetime
21
- from typing import Any, Literal, Union
21
+ from typing import Any, Literal
22
22
  from uuid import UUID
23
23
 
24
24
  # A type for fields that can be used as identifiers (primary keys).
25
- ID = Union[int, str, UUID]
25
+ ID = int | str | UUID
26
26
 
27
27
  # This is intended to type objects that are assumed to be JSON serializable.
28
28
  # (Scalar types as well as arrays are excluded from the above assumption,
29
29
  # and we serialize date, datetime and UUID objects to JSON as strings.)
30
30
  JsonObject = Mapping[
31
31
  str,
32
- Union[
33
- int,
34
- float,
35
- str,
36
- bool,
37
- date,
38
- datetime,
39
- UUID,
40
- Sequence[Any],
41
- Mapping[str, Any],
42
- None,
43
- ],
32
+ int
33
+ | float
34
+ | str
35
+ | bool
36
+ | date
37
+ | datetime
38
+ | UUID
39
+ | Sequence[Any]
40
+ | Mapping[str, Any]
41
+ | None,
44
42
  ]
45
43
 
46
44
 
@@ -19,7 +19,7 @@
19
19
  import json
20
20
  from datetime import datetime, timezone
21
21
  from logging import Formatter, Logger, LogRecord, StreamHandler, addLevelName, getLogger
22
- from typing import Any, Literal, Optional
22
+ from typing import Any, Literal
23
23
 
24
24
  from pydantic import Field
25
25
  from pydantic_settings import BaseSettings
@@ -61,7 +61,7 @@ class LoggingConfig(BaseSettings):
61
61
  + " this service. This is included in log messages."
62
62
  ),
63
63
  )
64
- log_format: Optional[str] = Field(
64
+ log_format: str | None = Field(
65
65
  default=None,
66
66
  examples=[
67
67
  "%(timestamp)s - %(service)s - %(level)s - %(message)s",
@@ -166,7 +166,7 @@ class RecordCompiler(StreamHandler):
166
166
  return super().handle(record)
167
167
 
168
168
 
169
- def configure_logging(*, config: LoggingConfig, logger: Optional[Logger] = None):
169
+ def configure_logging(*, config: LoggingConfig, logger: Logger | None = None):
170
170
  """Set up logging.
171
171
 
172
172
  Configures the root logger by default, but can be used to configure a specific
@@ -23,7 +23,7 @@ from abc import ABC, abstractmethod
23
23
  from collections.abc import AsyncIterator, Collection, Mapping
24
24
  from contextlib import AbstractAsyncContextManager
25
25
  from functools import partial
26
- from typing import Any, Optional, TypeVar
26
+ from typing import Any, TypeVar
27
27
  from uuid import uuid4
28
28
 
29
29
  from pydantic import BaseModel, Field
@@ -268,7 +268,7 @@ class DaoFactoryBase:
268
268
  cls,
269
269
  *,
270
270
  dto_model: type[Dto],
271
- fields_to_index: Optional[Collection[str]],
271
+ fields_to_index: Collection[str] | None,
272
272
  ) -> None:
273
273
  """Checks that all provided fields are present in the dto_model.
274
274
  Raises IndexFieldsInvalidError otherwise.
@@ -289,7 +289,7 @@ class DaoFactoryBase:
289
289
  *,
290
290
  dto_model: type[Dto],
291
291
  id_field: str,
292
- fields_to_index: Optional[Collection[str]],
292
+ fields_to_index: Collection[str] | None,
293
293
  ) -> None:
294
294
  """Validates the input parameters of the get_dao method."""
295
295
  cls._validate_dto_model_id(dto_model=dto_model, id_field=id_field)
@@ -309,7 +309,7 @@ class DaoFactoryProtocol(DaoFactoryBase, ABC):
309
309
  name: str,
310
310
  dto_model: type[Dto],
311
311
  id_field: str,
312
- fields_to_index: Optional[Collection[str]] = None,
312
+ fields_to_index: Collection[str] | None = None,
313
313
  ) -> Dao[Dto]:
314
314
  """Constructs a DAO for interacting with resources in a database.
315
315
 
@@ -354,7 +354,7 @@ class DaoFactoryProtocol(DaoFactoryBase, ABC):
354
354
  name: str,
355
355
  dto_model: type[Dto],
356
356
  id_field: str,
357
- fields_to_index: Optional[Collection[str]],
357
+ fields_to_index: Collection[str] | None,
358
358
  ) -> Dao[Dto]:
359
359
  """*To be implemented by the provider. Input validation is done outside of this
360
360
  method.*
@@ -23,8 +23,7 @@ of the outbox pattern.
23
23
 
24
24
  import typing
25
25
  from abc import ABC, abstractmethod
26
- from collections.abc import Collection
27
- from typing import Callable, Optional
26
+ from collections.abc import Callable, Collection
28
27
 
29
28
  from hexkit.custom_types import JsonObject
30
29
  from hexkit.protocols.dao import (
@@ -61,8 +60,8 @@ class DaoPublisherFactoryProtocol(DaoFactoryBase, ABC):
61
60
  name: str,
62
61
  dto_model: type[Dto],
63
62
  id_field: str,
64
- fields_to_index: Optional[Collection[str]] = None,
65
- dto_to_event: Callable[[Dto], Optional[JsonObject]],
63
+ fields_to_index: Collection[str] | None = None,
64
+ dto_to_event: Callable[[Dto], JsonObject | None],
66
65
  event_topic: str,
67
66
  autopublish: bool = True,
68
67
  ) -> DaoPublisher[Dto]:
@@ -121,8 +120,8 @@ class DaoPublisherFactoryProtocol(DaoFactoryBase, ABC):
121
120
  name: str,
122
121
  dto_model: type[Dto],
123
122
  id_field: str,
124
- fields_to_index: Optional[Collection[str]],
125
- dto_to_event: Callable[[Dto], Optional[JsonObject]],
123
+ fields_to_index: Collection[str] | None,
124
+ dto_to_event: Callable[[Dto], JsonObject | None],
126
125
  event_topic: str,
127
126
  autopublish: bool,
128
127
  ) -> DaoPublisher[Dto]:
@@ -18,7 +18,6 @@
18
18
 
19
19
  from abc import ABC, abstractmethod
20
20
  from collections.abc import Mapping
21
- from typing import Optional
22
21
  from uuid import UUID, uuid4
23
22
 
24
23
  from pydantic import UUID4
@@ -37,8 +36,8 @@ class EventPublisherProtocol(ABC):
37
36
  type_: Ascii,
38
37
  key: Ascii,
39
38
  topic: Ascii,
40
- event_id: Optional[UUID4] = None,
41
- headers: Optional[Mapping[str, str]] = None,
39
+ event_id: UUID4 | None = None,
40
+ headers: Mapping[str, str] | None = None,
42
41
  ) -> None:
43
42
  """Publish an event.
44
43
 
@@ -20,7 +20,7 @@
20
20
 
21
21
  import re
22
22
  from abc import ABC, abstractmethod
23
- from typing import NamedTuple, Optional
23
+ from typing import NamedTuple
24
24
 
25
25
  __all__ = ["ObjectStorageProtocol", "PresignedPostURL"]
26
26
 
@@ -85,7 +85,7 @@ class ObjectStorageProtocol(ABC):
85
85
  bucket_id: str,
86
86
  object_id: str,
87
87
  expires_after: int = DEFAULT_URL_EXPIRATION_PERIOD,
88
- max_upload_size: Optional[int] = None,
88
+ max_upload_size: int | None = None,
89
89
  ) -> PresignedPostURL:
90
90
  """Generates and returns an HTTP URL to upload a new file object with the given
91
91
  id (`object_id`) to the bucket with the specified id (`bucket_id`).
@@ -122,7 +122,7 @@ class ObjectStorageProtocol(ABC):
122
122
  object_id: str,
123
123
  part_number: int,
124
124
  expires_after: int = 3600,
125
- part_md5: Optional[str] = None,
125
+ part_md5: str | None = None,
126
126
  ) -> str:
127
127
  """Given a id of an instantiated multipart upload along with the corresponding
128
128
  bucket and object ID, it returns a presigned URL for uploading a file part with the
@@ -163,8 +163,8 @@ class ObjectStorageProtocol(ABC):
163
163
  upload_id: str,
164
164
  bucket_id: str,
165
165
  object_id: str,
166
- anticipated_part_quantity: Optional[int] = None,
167
- anticipated_part_size: Optional[int] = None,
166
+ anticipated_part_quantity: int | None = None,
167
+ anticipated_part_size: int | None = None,
168
168
  ) -> None:
169
169
  """Completes a multipart upload with the specified ID. In addition to the
170
170
  corresponding bucket and object id, you also specify an anticipated part size
@@ -196,7 +196,7 @@ class ObjectStorageProtocol(ABC):
196
196
  )
197
197
 
198
198
  async def does_object_exist(
199
- self, *, bucket_id: str, object_id: str, object_md5sum: Optional[str] = None
199
+ self, *, bucket_id: str, object_id: str, object_md5sum: str | None = None
200
200
  ) -> bool:
201
201
  """Check whether an object with specified ID (`object_id`) exists in the bucket
202
202
  with the specified id (`bucket_id`). Optionally, a md5 checksum (`object_md5sum`)
@@ -314,7 +314,7 @@ class ObjectStorageProtocol(ABC):
314
314
  bucket_id: str,
315
315
  object_id: str,
316
316
  expires_after: int = 86400,
317
- max_upload_size: Optional[int] = None,
317
+ max_upload_size: int | None = None,
318
318
  ) -> PresignedPostURL:
319
319
  """
320
320
  Generates and returns an HTTP URL to upload a new file object with the given
@@ -351,7 +351,7 @@ class ObjectStorageProtocol(ABC):
351
351
  object_id: str,
352
352
  part_number: int,
353
353
  expires_after: int = 3600,
354
- part_md5: Optional[str] = None,
354
+ part_md5: str | None = None,
355
355
  ) -> str:
356
356
  """
357
357
  Given a id of an instantiated multipart upload along with the corresponding
@@ -389,8 +389,8 @@ class ObjectStorageProtocol(ABC):
389
389
  upload_id: str,
390
390
  bucket_id: str,
391
391
  object_id: str,
392
- anticipated_part_quantity: Optional[int] = None,
393
- anticipated_part_size: Optional[int] = None,
392
+ anticipated_part_quantity: int | None = None,
393
+ anticipated_part_size: int | None = None,
394
394
  ) -> None:
395
395
  """
396
396
  Completes a multipart upload with the specified ID. In addition to the
@@ -438,7 +438,7 @@ class ObjectStorageProtocol(ABC):
438
438
 
439
439
  @abstractmethod
440
440
  async def _does_object_exist(
441
- self, *, bucket_id: str, object_id: str, object_md5sum: Optional[str] = None
441
+ self, *, bucket_id: str, object_id: str, object_md5sum: str | None = None
442
442
  ) -> bool:
443
443
  """
444
444
  Check whether an object with specified ID (`object_id`) exists in the bucket
@@ -549,7 +549,7 @@ class ObjectStorageProtocol(ABC):
549
549
  class BucketNotFoundError(BucketError):
550
550
  """Thrown when trying to access a bucket with an ID that doesn't exist."""
551
551
 
552
- def __init__(self, bucket_id: Optional[str]):
552
+ def __init__(self, bucket_id: str | None):
553
553
  with_id = f" with ID '{bucket_id}'" if bucket_id else ""
554
554
  message = f"The bucket{with_id} does not exist."
555
555
  super().__init__(message)
@@ -557,7 +557,7 @@ class ObjectStorageProtocol(ABC):
557
557
  class BucketAlreadyExistsError(BucketError):
558
558
  """Thrown when trying to create a bucket with an ID that already exists."""
559
559
 
560
- def __init__(self, bucket_id: Optional[str]):
560
+ def __init__(self, bucket_id: str | None):
561
561
  with_id = f" with ID '{bucket_id}'" if bucket_id else ""
562
562
  message = f"The bucket{with_id} already exists."
563
563
  super().__init__(message)
@@ -565,7 +565,7 @@ class ObjectStorageProtocol(ABC):
565
565
  class BucketNotEmptyError(BucketError):
566
566
  """Thrown when trying to delete a bucket that is not empty."""
567
567
 
568
- def __init__(self, bucket_id: Optional[str]):
568
+ def __init__(self, bucket_id: str | None):
569
569
  with_id = f" with ID '{bucket_id}'" if bucket_id else ""
570
570
  super().__init__(f"The bucket{with_id} is not empty.")
571
571
 
@@ -575,9 +575,7 @@ class ObjectStorageProtocol(ABC):
575
575
  class ObjectNotFoundError(ObjectError):
576
576
  """Thrown when trying to access a bucket with an ID that doesn't exist."""
577
577
 
578
- def __init__(
579
- self, bucket_id: Optional[str] = None, object_id: Optional[str] = None
580
- ):
578
+ def __init__(self, bucket_id: str | None = None, object_id: str | None = None):
581
579
  with_id = f" with ID '{object_id}'" if object_id else ""
582
580
  in_bucket = f" in bucket with ID '{bucket_id}'" if bucket_id else ""
583
581
  message = f"The object{with_id}{in_bucket} does not exist."
@@ -586,9 +584,7 @@ class ObjectStorageProtocol(ABC):
586
584
  class ObjectAlreadyExistsError(ObjectError):
587
585
  """Thrown when trying to access a file with an ID that doesn't exist."""
588
586
 
589
- def __init__(
590
- self, bucket_id: Optional[str] = None, object_id: Optional[str] = None
591
- ):
587
+ def __init__(self, bucket_id: str | None = None, object_id: str | None = None):
592
588
  with_id = f" with ID '{object_id}'" if object_id else ""
593
589
  in_bucket = f" in bucket with ID '{bucket_id}'" if bucket_id else ""
594
590
  message = f"The object{with_id}{in_bucket} already exists."
@@ -597,7 +593,7 @@ class ObjectStorageProtocol(ABC):
597
593
  class BucketIdValidationError(BucketError):
598
594
  """Thrown when a bucket ID is not valid."""
599
595
 
600
- def __init__(self, bucket_id: str, reason: Optional[str]):
596
+ def __init__(self, bucket_id: str, reason: str | None):
601
597
  with_reason = f": {reason}." if reason else "."
602
598
  message = f"The specified bucket ID '{bucket_id}' is not valid{with_reason}"
603
599
  super().__init__(message)
@@ -605,7 +601,7 @@ class ObjectStorageProtocol(ABC):
605
601
  class ObjectIdValidationError(ObjectError):
606
602
  """Thrown when an object ID is not valid."""
607
603
 
608
- def __init__(self, object_id: str, reason: Optional[str]):
604
+ def __init__(self, object_id: str, reason: str | None):
609
605
  with_reason = f": {reason}." if reason else "."
610
606
  message = f"The specified object ID '{object_id}' is not valid{with_reason}"
611
607
  super().__init__(message)
@@ -644,7 +640,7 @@ class ObjectStorageProtocol(ABC):
644
640
  upload_id: str,
645
641
  bucket_id: str,
646
642
  object_id: str,
647
- details: Optional[str] = None,
643
+ details: str | None = None,
648
644
  ):
649
645
  with_details = f": {details}." if details else "."
650
646
  message = (
@@ -661,7 +657,7 @@ class ObjectStorageProtocol(ABC):
661
657
  upload_id: str,
662
658
  bucket_id: str,
663
659
  object_id: str,
664
- reason: Optional[str] = None,
660
+ reason: str | None = None,
665
661
  ):
666
662
  with_reason = f": {reason}." if reason else "."
667
663
  message = (
@@ -16,7 +16,7 @@
16
16
 
17
17
  """Apache Kafka specific configuration."""
18
18
 
19
- from typing import Literal, Optional
19
+ from typing import Literal
20
20
 
21
21
  from pydantic import Field, NonNegativeInt, PositiveInt, SecretStr
22
22
  from pydantic_settings import BaseSettings
@@ -87,7 +87,7 @@ class KafkaConfig(BaseSettings):
87
87
  + " field, which effectively concerns the compressed message size.",
88
88
  examples=[1024 * 1024, 16 * 1024 * 1024],
89
89
  )
90
- kafka_compression_type: Optional[KafkaCompressionType] = Field(
90
+ kafka_compression_type: KafkaCompressionType | None = Field(
91
91
  default=None,
92
92
  description=(
93
93
  "The compression type used for messages. Valid values are: None, gzip,"
@@ -21,7 +21,6 @@
21
21
  import logging
22
22
  from collections.abc import Sequence
23
23
  from contextlib import asynccontextmanager
24
- from typing import Optional
25
24
 
26
25
  from aiokafka import AIOKafkaConsumer
27
26
 
@@ -56,7 +55,7 @@ class KafkaOutboxSubscriber(InboundProviderBase):
56
55
  *,
57
56
  config: KafkaConfig,
58
57
  translators: Sequence[DaoSubscriberProtocol],
59
- dlq_publisher: Optional[EventPublisherProtocol] = None,
58
+ dlq_publisher: EventPublisherProtocol | None = None,
60
59
  kafka_consumer_cls: type[KafkaConsumerCompatible] = AIOKafkaConsumer,
61
60
  ):
62
61
  """Setup and teardown an instance of the provider.