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.
- {hexkit-7.0.0/src/hexkit.egg-info → hexkit-7.2.0}/PKG-INFO +34 -24
- {hexkit-7.0.0 → hexkit-7.2.0}/README.md +13 -2
- {hexkit-7.0.0 → hexkit-7.2.0}/pyproject.toml +26 -28
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/config.py +5 -4
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/custom_types.py +12 -14
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/log.py +3 -3
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/dao.py +5 -5
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/daopub.py +5 -6
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/eventpub.py +2 -3
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/objstorage.py +20 -24
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/config.py +2 -2
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/provider/daosub.py +1 -2
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/provider/eventpub.py +4 -4
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/provider/eventsub.py +11 -11
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/provider/utils.py +1 -2
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/testcontainer.py +6 -6
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/testutils.py +14 -14
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/migrations/_manager.py +2 -2
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/migrations/_utils.py +5 -5
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/migrations/helpers.py +2 -3
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/provider.py +4 -4
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/testutils.py +2 -3
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/provider/daopub.py +5 -5
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/provider/persistent_pub.py +3 -4
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/provider.py +47 -46
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/testutils/_fixtures.py +6 -6
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/testing/__init__.py +11 -0
- hexkit-7.2.0/src/hexkit/providers/testing/dao.py +146 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/testing/eventpub.py +2 -2
- hexkit-7.2.0/src/hexkit/providers/testing/s3.py +402 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/utils.py +2 -2
- {hexkit-7.0.0 → hexkit-7.2.0/src/hexkit.egg-info}/PKG-INFO +34 -24
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit.egg-info/SOURCES.txt +3 -1
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit.egg-info/requires.txt +19 -19
- {hexkit-7.0.0 → hexkit-7.2.0}/LICENSE +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/MANIFEST.in +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/setup.cfg +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/__main__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/base.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/correlation.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/opentelemetry.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/daosub.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/protocols/eventsub.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/akafka/provider/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongodb/migrations/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/provider/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/provider/config.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/mongokafka/testutils.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/test_files/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/test_files/test_file1.yaml +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/test_files/test_file2.yaml +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/test_files/test_file3.yaml +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/test_files/test_file4.yaml +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/testutils/__init__.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/testutils/_typical_workflow.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/providers/s3/testutils/_utils.py +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit/py.typed +0 -0
- {hexkit-7.0.0 → hexkit-7.2.0}/src/hexkit.egg-info/dependency_links.txt +0 -0
- {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.
|
|
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.
|
|
18
|
+
Requires-Python: >=3.10
|
|
20
19
|
Description-Content-Type: text/markdown
|
|
21
20
|
License-File: LICENSE
|
|
22
|
-
Requires-Dist: opentelemetry-api<2,>=1.
|
|
23
|
-
Requires-Dist: pydantic<3,>=2.
|
|
24
|
-
Requires-Dist: pydantic_settings<3,>=2.
|
|
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.
|
|
27
|
+
Requires-Dist: jsonschema<5,>=4.25; extra == "akafka"
|
|
29
28
|
Provides-Extra: s3
|
|
30
|
-
Requires-Dist: boto3<2,>=1.
|
|
31
|
-
Requires-Dist: botocore<2,>=1.
|
|
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.
|
|
32
|
+
Requires-Dist: pymongo<5,>=4.15; extra == "mongodb"
|
|
34
33
|
Provides-Extra: opentelemetry-base
|
|
35
|
-
Requires-Dist: opentelemetry-sdk<2,>=1.
|
|
36
|
-
Requires-Dist: opentelemetry-exporter-otlp<2,>=1.
|
|
37
|
-
Requires-Dist: opentelemetry-instrumentation>=0.
|
|
38
|
-
Requires-Dist: opentelemetry-instrumentation-httpx>=0.
|
|
39
|
-
Requires-Dist: opentelemetry-distro>=0.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
[](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
|
[](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
|
+
"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.
|
|
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.
|
|
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
|
-
"pydantic >=2.
|
|
32
|
-
"pydantic_settings >=2.
|
|
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.
|
|
41
|
+
"jsonschema >=4.25, <5",
|
|
43
42
|
]
|
|
44
43
|
s3 = [
|
|
45
|
-
"boto3 >=1.
|
|
46
|
-
"botocore >=1.
|
|
44
|
+
"boto3 >=1.40, <2",
|
|
45
|
+
"botocore >=1.40, <2",
|
|
47
46
|
]
|
|
48
47
|
mongodb = [
|
|
49
|
-
"pymongo >=4.
|
|
48
|
+
"pymongo >=4.15, <5",
|
|
50
49
|
]
|
|
51
50
|
opentelemetry-base = [
|
|
52
|
-
"opentelemetry-sdk >=1.
|
|
53
|
-
"opentelemetry-exporter-otlp >=1.
|
|
54
|
-
"opentelemetry-instrumentation >=0.
|
|
55
|
-
"opentelemetry-instrumentation-httpx >=0.
|
|
56
|
-
"opentelemetry-distro >=0.
|
|
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.
|
|
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.
|
|
65
|
+
"opentelemetry-instrumentation-pymongo >=0.58b0",
|
|
67
66
|
]
|
|
68
67
|
opentelemetry-fastapi = [
|
|
69
68
|
"hexkit[opentelemetry-base]",
|
|
70
|
-
"opentelemetry-instrumentation-fastapi >=0.
|
|
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.
|
|
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.
|
|
84
|
+
"testcontainers[kafka] >=4.13, <5",
|
|
86
85
|
]
|
|
87
86
|
test-s3 = [
|
|
88
87
|
"hexkit[s3]",
|
|
89
|
-
"testcontainers >=4.
|
|
88
|
+
"testcontainers >=4.13, <5",
|
|
90
89
|
]
|
|
91
90
|
test-mongodb = [
|
|
92
91
|
"hexkit[mongodb]",
|
|
93
|
-
"testcontainers[mongo] >=4.
|
|
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 = "
|
|
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.
|
|
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{
|
|
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
|
-
|
|
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
|
|
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:
|
|
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) ->
|
|
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:
|
|
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
|
|
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 =
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
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:
|
|
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:
|
|
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,
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
65
|
-
dto_to_event: Callable[[Dto],
|
|
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:
|
|
125
|
-
dto_to_event: Callable[[Dto],
|
|
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:
|
|
41
|
-
headers:
|
|
39
|
+
event_id: UUID4 | None = None,
|
|
40
|
+
headers: Mapping[str, str] | None = None,
|
|
42
41
|
) -> None:
|
|
43
42
|
"""Publish an event.
|
|
44
43
|
|