hexkit 7.0.0__tar.gz → 7.2.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 (66) hide show
  1. {hexkit-7.0.0/src/hexkit.egg-info → hexkit-7.2.0}/PKG-INFO +34 -24
  2. {hexkit-7.0.0 → hexkit-7.2.0}/README.md +13 -2
  3. {hexkit-7.0.0 → hexkit-7.2.0}/pyproject.toml +26 -28
  4. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/config.py +5 -4
  5. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/custom_types.py +12 -14
  6. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/log.py +3 -3
  7. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/dao.py +5 -5
  8. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/daopub.py +5 -6
  9. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/eventpub.py +2 -3
  10. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/objstorage.py +20 -24
  11. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/config.py +2 -2
  12. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/provider/daosub.py +1 -2
  13. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/provider/eventpub.py +4 -4
  14. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/provider/eventsub.py +11 -11
  15. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/provider/utils.py +1 -2
  16. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/testcontainer.py +6 -6
  17. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/testutils.py +14 -14
  18. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/migrations/_manager.py +2 -2
  19. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/migrations/_utils.py +5 -5
  20. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/migrations/helpers.py +2 -3
  21. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/provider.py +4 -4
  22. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/testutils.py +2 -3
  23. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/provider/daopub.py +5 -5
  24. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/provider/persistent_pub.py +3 -4
  25. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/provider.py +47 -46
  26. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/testutils/_fixtures.py +6 -6
  27. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/testing/__init__.py +11 -0
  28. hexkit-7.2.0/src/hexkit/providers/testing/dao.py +146 -0
  29. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/testing/eventpub.py +2 -2
  30. hexkit-7.2.0/src/hexkit/providers/testing/s3.py +402 -0
  31. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/utils.py +2 -2
  32. {hexkit-7.0.0 → hexkit-7.2.0/src/hexkit.egg-info}/PKG-INFO +34 -24
  33. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit.egg-info/SOURCES.txt +3 -1
  34. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit.egg-info/requires.txt +19 -19
  35. {hexkit-7.0.0 → hexkit-7.2.0}/LICENSE +0 -0
  36. {hexkit-7.0.0 → hexkit-7.2.0}/MANIFEST.in +0 -0
  37. {hexkit-7.0.0 → hexkit-7.2.0}/setup.cfg +0 -0
  38. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/__init__.py +0 -0
  39. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/__main__.py +0 -0
  40. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/base.py +0 -0
  41. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/correlation.py +0 -0
  42. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/opentelemetry.py +0 -0
  43. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/__init__.py +0 -0
  44. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/daosub.py +0 -0
  45. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/eventsub.py +0 -0
  46. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/__init__.py +0 -0
  47. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/__init__.py +0 -0
  48. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/provider/__init__.py +0 -0
  49. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/__init__.py +0 -0
  50. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/migrations/__init__.py +0 -0
  51. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/__init__.py +0 -0
  52. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/provider/__init__.py +0 -0
  53. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/provider/config.py +0 -0
  54. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/testutils.py +0 -0
  55. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/__init__.py +0 -0
  56. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/test_files/__init__.py +0 -0
  57. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/test_files/test_file1.yaml +0 -0
  58. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/test_files/test_file2.yaml +0 -0
  59. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/test_files/test_file3.yaml +0 -0
  60. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/test_files/test_file4.yaml +0 -0
  61. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/testutils/__init__.py +0 -0
  62. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/testutils/_typical_workflow.py +0 -0
  63. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/testutils/_utils.py +0 -0
  64. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/py.typed +0 -0
  65. {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit.egg-info/dependency_links.txt +0 -0
  66. {hexkit-7.0.0 → hexkit-7.2.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.2.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
@@ -79,10 +78,12 @@ Dynamic: license-file
79
78
  [![Coverage Status](https://coveralls.io/repos/github/ghga-de/hexkit/badge.svg?branch=main)](https://coveralls.io/github/ghga-de/hexkit?branch=main)
80
79
 
81
80
  # hexkit
81
+
82
82
  A chassis library for building domain-focused, infrastructure-agnostic, and event-driven
83
83
  microservices in Python.
84
84
 
85
85
  ## In a Nutshell
86
+
86
87
  This project implements the Triple Hexagonal Architecture pattern which is an
87
88
  optimization of the ordinary
88
89
  [Hexagonal Architecture](https://alistair.cockburn.us/hexagonal-architecture/) for
@@ -111,6 +112,7 @@ a limited collection of protocol-provider pairs that are of immediate interest t
111
112
  authors. We like to add support for more protocols and technologies over time.
112
113
 
113
114
  The following protocols and providers are currently available:
115
+
114
116
  | Protocol | Providers |
115
117
  |---|---|
116
118
  | Event Publishing | Apache Kafka |
@@ -141,15 +143,18 @@ of jumping directly into it. You can find the protocols being defined at
141
143
  A more elaborate documentation and tutorial is on the way.
142
144
 
143
145
  ## Installation
146
+
144
147
  This package is available at PyPI:
145
- https://pypi.org/project/hexkit
148
+ <https://pypi.org/project/hexkit>
146
149
 
147
150
  You can install it from there using:
148
- ```
151
+
152
+ ```sh
149
153
  pip install hexkit
150
154
  ```
151
155
 
152
156
  The following extras are available:
157
+
153
158
  - `akafka`: when using the Apache Kafka-based event publishing or subscription
154
159
  - `s3`: when interacting with S3-compatible Object Storages
155
160
  - `mongodb`: when using mongodb as backend for the DAO protocol
@@ -159,6 +164,7 @@ The following extras are available:
159
164
  - `all`: a union of all the above
160
165
 
161
166
  ## Development
167
+
162
168
  For setting up the development environment, we rely on the
163
169
  [devcontainer feature](https://code.visualstudio.com/docs/remote/containers) of vscode.
164
170
 
@@ -168,6 +174,7 @@ Then, you just have to open this repo in vscode and run the command
168
174
  `Remote-Containers: Reopen in Container` from the vscode "Command Palette".
169
175
 
170
176
  This will give you a full-fledged, pre-configured development environment including:
177
+
171
178
  - infrastructural dependencies of the service (databases, etc.)
172
179
  - all relevant vscode extensions pre-installed
173
180
  - pre-configured linting and auto-formatting
@@ -176,12 +183,14 @@ This will give you a full-fledged, pre-configured development environment includ
176
183
 
177
184
  Additionally, the following convenience command is available inside the devcontainer
178
185
  (type it in the integrated terminal of VS Code):
186
+
179
187
  - `dev_install` - install the lib with all development dependencies and pre-commit hooks
180
188
  (please run that if you are starting the devcontainer for the first time
181
189
  or if added any python dependencies to the [`./pyproject.toml`](./pyproject.toml))
182
190
 
183
191
  If you prefer not to use vscode, you could get a similar setup (without the editor
184
192
  specific features) by running the following commands:
193
+
185
194
  ``` bash
186
195
  # Execute in the repo's root dir:
187
196
  cd ./.devcontainer
@@ -193,4 +202,5 @@ docker run -it hexkit /bin/bash
193
202
  ```
194
203
 
195
204
  ## License
205
+
196
206
  This repository is free to use and modify according to the [Apache 2.0 License](./LICENSE).
@@ -4,10 +4,12 @@
4
4
  [![Coverage Status](https://coveralls.io/repos/github/ghga-de/hexkit/badge.svg?branch=main)](https://coveralls.io/github/ghga-de/hexkit?branch=main)
5
5
 
6
6
  # hexkit
7
+
7
8
  A chassis library for building domain-focused, infrastructure-agnostic, and event-driven
8
9
  microservices in Python.
9
10
 
10
11
  ## In a Nutshell
12
+
11
13
  This project implements the Triple Hexagonal Architecture pattern which is an
12
14
  optimization of the ordinary
13
15
  [Hexagonal Architecture](https://alistair.cockburn.us/hexagonal-architecture/) for
@@ -36,6 +38,7 @@ a limited collection of protocol-provider pairs that are of immediate interest t
36
38
  authors. We like to add support for more protocols and technologies over time.
37
39
 
38
40
  The following protocols and providers are currently available:
41
+
39
42
  | Protocol | Providers |
40
43
  |---|---|
41
44
  | Event Publishing | Apache Kafka |
@@ -66,15 +69,18 @@ of jumping directly into it. You can find the protocols being defined at
66
69
  A more elaborate documentation and tutorial is on the way.
67
70
 
68
71
  ## Installation
72
+
69
73
  This package is available at PyPI:
70
- https://pypi.org/project/hexkit
74
+ <https://pypi.org/project/hexkit>
71
75
 
72
76
  You can install it from there using:
73
- ```
77
+
78
+ ```sh
74
79
  pip install hexkit
75
80
  ```
76
81
 
77
82
  The following extras are available:
83
+
78
84
  - `akafka`: when using the Apache Kafka-based event publishing or subscription
79
85
  - `s3`: when interacting with S3-compatible Object Storages
80
86
  - `mongodb`: when using mongodb as backend for the DAO protocol
@@ -84,6 +90,7 @@ The following extras are available:
84
90
  - `all`: a union of all the above
85
91
 
86
92
  ## Development
93
+
87
94
  For setting up the development environment, we rely on the
88
95
  [devcontainer feature](https://code.visualstudio.com/docs/remote/containers) of vscode.
89
96
 
@@ -93,6 +100,7 @@ Then, you just have to open this repo in vscode and run the command
93
100
  `Remote-Containers: Reopen in Container` from the vscode "Command Palette".
94
101
 
95
102
  This will give you a full-fledged, pre-configured development environment including:
103
+
96
104
  - infrastructural dependencies of the service (databases, etc.)
97
105
  - all relevant vscode extensions pre-installed
98
106
  - pre-configured linting and auto-formatting
@@ -101,12 +109,14 @@ This will give you a full-fledged, pre-configured development environment includ
101
109
 
102
110
  Additionally, the following convenience command is available inside the devcontainer
103
111
  (type it in the integrated terminal of VS Code):
112
+
104
113
  - `dev_install` - install the lib with all development dependencies and pre-commit hooks
105
114
  (please run that if you are starting the devcontainer for the first time
106
115
  or if added any python dependencies to the [`./pyproject.toml`](./pyproject.toml))
107
116
 
108
117
  If you prefer not to use vscode, you could get a similar setup (without the editor
109
118
  specific features) by running the following commands:
119
+
110
120
  ``` bash
111
121
  # Execute in the repo's root dir:
112
122
  cd ./.devcontainer
@@ -118,4 +128,5 @@ docker run -it hexkit /bin/bash
118
128
  ```
119
129
 
120
130
  ## License
131
+
121
132
  This repository is free to use and modify according to the [Apache 2.0 License](./LICENSE).
@@ -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.2.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