hexkit 8.0.0__tar.gz → 8.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-8.0.0 → hexkit-8.2.0}/LICENSE +1 -1
- {hexkit-8.0.0/src/hexkit.egg-info → hexkit-8.2.0}/PKG-INFO +16 -8
- {hexkit-8.0.0 → hexkit-8.2.0}/pyproject.toml +37 -11
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/__main__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/base.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/config.py +19 -8
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/correlation.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/custom_types.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/log.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/opentelemetry.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/protocols/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/protocols/dao.py +12 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/protocols/daopub.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/protocols/daosub.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/protocols/eventpub.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/protocols/eventsub.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/protocols/kvstore.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/protocols/objstorage.py +58 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/akafka/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/akafka/config.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/akafka/provider/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/akafka/provider/daosub.py +3 -3
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/akafka/provider/eventpub.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/akafka/provider/eventsub.py +5 -3
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/akafka/provider/utils.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/akafka/testcontainer.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/akafka/testutils.py +4 -4
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/config.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/migrations/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/migrations/_manager.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/migrations/_utils.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/migrations/helpers.py +5 -5
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/provider/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/provider/client.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/provider/dao.py +27 -8
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/provider/kvstore.py +7 -3
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/provider/utils.py +2 -2
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongodb/testutils.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongokafka/__init__.py +3 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongokafka/config.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongokafka/provider/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongokafka/provider/daopub.py +48 -15
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongokafka/provider/persistent_pub.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/mongokafka/testutils.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/redis/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/redis/config.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/redis/provider/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/redis/provider/client.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/redis/provider/kvstore.py +9 -4
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/redis/testutils.py +1 -1
- hexkit-8.2.0/src/hexkit/providers/s3/__init__.py +36 -0
- hexkit-8.2.0/src/hexkit/providers/s3/config.py +68 -0
- {hexkit-8.0.0/src/hexkit/providers/s3 → hexkit-8.2.0/src/hexkit/providers/s3/provider}/__init__.py +17 -5
- hexkit-8.2.0/src/hexkit/providers/s3/provider/kvstore.py +250 -0
- hexkit-8.0.0/src/hexkit/providers/s3/provider.py → hexkit-8.2.0/src/hexkit/providers/s3/provider/objstorage.py +87 -112
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/s3/test_files/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/s3/testutils/__init__.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/s3/testutils/_fixtures.py +2 -2
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/s3/testutils/_typical_workflow.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/s3/testutils/_utils.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/testing/__init__.py +11 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/testing/dao.py +1 -1
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/testing/eventpub.py +1 -1
- hexkit-8.2.0/src/hexkit/providers/testing/kvstore.py +222 -0
- hexkit-8.0.0/src/hexkit/providers/testing/s3.py → hexkit-8.2.0/src/hexkit/providers/testing/objstorage.py +44 -17
- hexkit-8.2.0/src/hexkit/providers/vault/__init__.py +33 -0
- hexkit-8.2.0/src/hexkit/providers/vault/config.py +118 -0
- hexkit-8.2.0/src/hexkit/providers/vault/provider/__init__.py +20 -0
- hexkit-8.2.0/src/hexkit/providers/vault/provider/client.py +131 -0
- hexkit-8.2.0/src/hexkit/providers/vault/provider/kvstore.py +275 -0
- hexkit-8.2.0/src/hexkit/providers/vault/testutils.py +258 -0
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/utils.py +4 -3
- {hexkit-8.0.0 → hexkit-8.2.0/src/hexkit.egg-info}/PKG-INFO +16 -8
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit.egg-info/SOURCES.txt +12 -2
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit.egg-info/requires.txt +14 -7
- {hexkit-8.0.0 → hexkit-8.2.0}/MANIFEST.in +0 -0
- {hexkit-8.0.0 → hexkit-8.2.0}/README.md +0 -0
- {hexkit-8.0.0 → hexkit-8.2.0}/setup.cfg +0 -0
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/s3/test_files/test_file1.yaml +0 -0
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/s3/test_files/test_file2.yaml +0 -0
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/s3/test_files/test_file3.yaml +0 -0
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/providers/s3/test_files/test_file4.yaml +0 -0
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit/py.typed +0 -0
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit.egg-info/dependency_links.txt +0 -0
- {hexkit-8.0.0 → hexkit-8.2.0}/src/hexkit.egg-info/top_level.txt +0 -0
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright 2021 -
|
|
189
|
+
Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
190
190
|
for the German Human Genome-Phenome Archive (GHGA)
|
|
191
191
|
|
|
192
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hexkit
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.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
|
+
Project-URL: Documentation, https://ghga-de.github.io/hexkit/
|
|
9
|
+
Project-URL: Release Notes, https://github.com/ghga-de/hexkit/releases
|
|
10
|
+
Project-URL: Issue Tracker, https://github.com/ghga-de/hexkit/issues
|
|
8
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
9
12
|
Classifier: Operating System :: POSIX :: Linux
|
|
10
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
@@ -23,15 +26,17 @@ Requires-Dist: pydantic<3,>=2.12
|
|
|
23
26
|
Requires-Dist: pydantic_settings<3,>=2.12
|
|
24
27
|
Requires-Dist: PyYAML<7,>=6
|
|
25
28
|
Provides-Extra: akafka
|
|
26
|
-
Requires-Dist: aiokafka[lz4,snappy,zstd]~=0.
|
|
29
|
+
Requires-Dist: aiokafka[lz4,snappy,zstd]~=0.14.0; extra == "akafka"
|
|
27
30
|
Requires-Dist: jsonschema<5,>=4.25; extra == "akafka"
|
|
28
31
|
Provides-Extra: s3
|
|
29
32
|
Requires-Dist: boto3<2,>=1.42; extra == "s3"
|
|
30
33
|
Requires-Dist: botocore<2,>=1.42; extra == "s3"
|
|
31
34
|
Provides-Extra: mongodb
|
|
32
|
-
Requires-Dist: pymongo<5,>=4.
|
|
35
|
+
Requires-Dist: pymongo<5,>=4.16; extra == "mongodb"
|
|
33
36
|
Provides-Extra: redis
|
|
34
37
|
Requires-Dist: redis<8,>=7.1; extra == "redis"
|
|
38
|
+
Provides-Extra: vault
|
|
39
|
+
Requires-Dist: hvac<3,>=2.4; extra == "vault"
|
|
35
40
|
Provides-Extra: opentelemetry-base
|
|
36
41
|
Requires-Dist: opentelemetry-sdk<2,>=1.39.1; extra == "opentelemetry-base"
|
|
37
42
|
Requires-Dist: opentelemetry-exporter-otlp<2,>=1.39.1; extra == "opentelemetry-base"
|
|
@@ -64,18 +69,21 @@ Requires-Dist: hexkit[opentelemetry-fastapi]; extra == "opentelemetry"
|
|
|
64
69
|
Requires-Dist: hexkit[opentelemetry-s3]; extra == "opentelemetry"
|
|
65
70
|
Provides-Extra: test-akafka
|
|
66
71
|
Requires-Dist: hexkit[akafka]; extra == "test-akafka"
|
|
67
|
-
Requires-Dist: testcontainers[kafka]<5,>=4.
|
|
72
|
+
Requires-Dist: testcontainers[kafka]<5,>=4.14; extra == "test-akafka"
|
|
68
73
|
Provides-Extra: test-s3
|
|
69
74
|
Requires-Dist: hexkit[s3]; extra == "test-s3"
|
|
70
|
-
Requires-Dist: testcontainers<5,>=4.
|
|
75
|
+
Requires-Dist: testcontainers<5,>=4.14; extra == "test-s3"
|
|
71
76
|
Provides-Extra: test-mongodb
|
|
72
77
|
Requires-Dist: hexkit[mongodb]; extra == "test-mongodb"
|
|
73
|
-
Requires-Dist: testcontainers[mongo]<5,>=4.
|
|
78
|
+
Requires-Dist: testcontainers[mongo]<5,>=4.14; extra == "test-mongodb"
|
|
74
79
|
Provides-Extra: test-redis
|
|
75
80
|
Requires-Dist: hexkit[redis]; extra == "test-redis"
|
|
76
|
-
Requires-Dist: testcontainers[redis]<5,>=4.
|
|
81
|
+
Requires-Dist: testcontainers[redis]<5,>=4.14; extra == "test-redis"
|
|
82
|
+
Provides-Extra: test-vault
|
|
83
|
+
Requires-Dist: hexkit[vault]; extra == "test-vault"
|
|
84
|
+
Requires-Dist: testcontainers<5,>=4.14; extra == "test-vault"
|
|
77
85
|
Provides-Extra: test
|
|
78
|
-
Requires-Dist: hexkit[test-akafka,test-mongodb,test-s3]; extra == "test"
|
|
86
|
+
Requires-Dist: hexkit[test-akafka,test-mongodb,test-s3,test-vault]; extra == "test"
|
|
79
87
|
Provides-Extra: all
|
|
80
88
|
Requires-Dist: hexkit[test]; extra == "all"
|
|
81
89
|
Requires-Dist: hexkit[opentelemetry]; extra == "all"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[build-system]
|
|
2
2
|
requires = [
|
|
3
|
-
"setuptools>=
|
|
3
|
+
"setuptools>=82",
|
|
4
4
|
]
|
|
5
5
|
build-backend = "setuptools.build_meta"
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ classifiers = [
|
|
|
23
23
|
"Intended Audience :: Developers",
|
|
24
24
|
]
|
|
25
25
|
name = "hexkit"
|
|
26
|
-
version = "8.
|
|
26
|
+
version = "8.2.0"
|
|
27
27
|
description = "A Toolkit for Building Microservices using the Hexagonal Architecture"
|
|
28
28
|
dependencies = [
|
|
29
29
|
"opentelemetry-api >=1.39, <2",
|
|
@@ -37,7 +37,7 @@ text = "Apache 2.0"
|
|
|
37
37
|
|
|
38
38
|
[project.optional-dependencies]
|
|
39
39
|
akafka = [
|
|
40
|
-
"aiokafka[zstd,lz4,snappy]~=0.
|
|
40
|
+
"aiokafka[zstd,lz4,snappy]~=0.14.0",
|
|
41
41
|
"jsonschema >=4.25, <5",
|
|
42
42
|
]
|
|
43
43
|
s3 = [
|
|
@@ -45,11 +45,14 @@ s3 = [
|
|
|
45
45
|
"botocore >=1.42, <2",
|
|
46
46
|
]
|
|
47
47
|
mongodb = [
|
|
48
|
-
"pymongo >=4.
|
|
48
|
+
"pymongo >=4.16, <5",
|
|
49
49
|
]
|
|
50
50
|
redis = [
|
|
51
51
|
"redis >=7.1, <8",
|
|
52
52
|
]
|
|
53
|
+
vault = [
|
|
54
|
+
"hvac >=2.4, <3",
|
|
55
|
+
]
|
|
53
56
|
opentelemetry-base = [
|
|
54
57
|
"opentelemetry-sdk >=1.39.1, <2",
|
|
55
58
|
"opentelemetry-exporter-otlp >=1.39.1, <2",
|
|
@@ -89,22 +92,26 @@ opentelemetry = [
|
|
|
89
92
|
]
|
|
90
93
|
test-akafka = [
|
|
91
94
|
"hexkit[akafka]",
|
|
92
|
-
"testcontainers[kafka] >=4.
|
|
95
|
+
"testcontainers[kafka] >=4.14, <5",
|
|
93
96
|
]
|
|
94
97
|
test-s3 = [
|
|
95
98
|
"hexkit[s3]",
|
|
96
|
-
"testcontainers >=4.
|
|
99
|
+
"testcontainers >=4.14, <5",
|
|
97
100
|
]
|
|
98
101
|
test-mongodb = [
|
|
99
102
|
"hexkit[mongodb]",
|
|
100
|
-
"testcontainers[mongo] >=4.
|
|
103
|
+
"testcontainers[mongo] >=4.14, <5",
|
|
101
104
|
]
|
|
102
105
|
test-redis = [
|
|
103
106
|
"hexkit[redis]",
|
|
104
|
-
"testcontainers[redis] >=4.
|
|
107
|
+
"testcontainers[redis] >=4.14, <5",
|
|
108
|
+
]
|
|
109
|
+
test-vault = [
|
|
110
|
+
"hexkit[vault]",
|
|
111
|
+
"testcontainers >=4.14, <5",
|
|
105
112
|
]
|
|
106
113
|
test = [
|
|
107
|
-
"hexkit[test-akafka,test-s3,test-mongodb]",
|
|
114
|
+
"hexkit[test-akafka,test-s3,test-mongodb,test-vault]",
|
|
108
115
|
]
|
|
109
116
|
all = [
|
|
110
117
|
"hexkit[test]",
|
|
@@ -113,6 +120,9 @@ all = [
|
|
|
113
120
|
|
|
114
121
|
[project.urls]
|
|
115
122
|
Repository = "https://github.com/ghga-de/hexkit"
|
|
123
|
+
Documentation = "https://ghga-de.github.io/hexkit/"
|
|
124
|
+
"Release Notes" = "https://github.com/ghga-de/hexkit/releases"
|
|
125
|
+
"Issue Tracker" = "https://github.com/ghga-de/hexkit/issues"
|
|
116
126
|
|
|
117
127
|
[tool.setuptools.packages.find]
|
|
118
128
|
where = [
|
|
@@ -235,7 +245,7 @@ source = [
|
|
|
235
245
|
[tool.tox]
|
|
236
246
|
legacy_tox_ini = """
|
|
237
247
|
[tox]
|
|
238
|
-
env_list = py3{10,11,12,13}
|
|
248
|
+
env_list = py3{10,11,12,13}, docs
|
|
239
249
|
|
|
240
250
|
[gh-actions]
|
|
241
251
|
python =
|
|
@@ -244,6 +254,22 @@ legacy_tox_ini = """
|
|
|
244
254
|
3.12: py312
|
|
245
255
|
3.13: py313
|
|
246
256
|
|
|
257
|
+
[testenv:docs]
|
|
258
|
+
basepython = python3.13
|
|
259
|
+
allowlist_externals =
|
|
260
|
+
mv
|
|
261
|
+
rm
|
|
262
|
+
deps =
|
|
263
|
+
--no-deps -r ./lock/requirements-dev.txt
|
|
264
|
+
commands =
|
|
265
|
+
rm -rf site/api
|
|
266
|
+
pdoc -d google -o docs/api hexkit
|
|
267
|
+
mv docs/api/index.html docs/api/index.md
|
|
268
|
+
mkdocs build
|
|
269
|
+
mv docs/api/index.md docs/api/index.html
|
|
270
|
+
rm -rf site/api
|
|
271
|
+
mv docs/api site/api
|
|
272
|
+
|
|
247
273
|
[testenv]
|
|
248
274
|
pass_env =
|
|
249
275
|
TC_HOST
|
|
@@ -251,6 +277,6 @@ legacy_tox_ini = """
|
|
|
251
277
|
deps =
|
|
252
278
|
--no-deps -r ./lock/requirements-dev.txt
|
|
253
279
|
commands =
|
|
254
|
-
py310: pip install --no-deps backports.asyncio.runner==1.2.0 exceptiongroup==1.3.
|
|
280
|
+
py310: pip install --no-deps backports.asyncio.runner==1.2.0 exceptiongroup==1.3.1 tomli==2.2.1
|
|
255
281
|
pytest {posargs}
|
|
256
282
|
"""
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -29,6 +29,8 @@ from pydantic_settings import (
|
|
|
29
29
|
|
|
30
30
|
# Default config prefix:
|
|
31
31
|
DEFAULT_CONFIG_PREFIX: Final = "ghga_services"
|
|
32
|
+
# Default dotenv path:
|
|
33
|
+
DEFAULT_DOTENV_PATH: Final[Path] = Path("/secrets")
|
|
32
34
|
|
|
33
35
|
|
|
34
36
|
class ConfigYamlDoesNotExist(RuntimeError):
|
|
@@ -82,6 +84,7 @@ def get_default_config_yaml(prefix: str) -> Path | None:
|
|
|
82
84
|
|
|
83
85
|
def config_from_yaml(
|
|
84
86
|
prefix: str = DEFAULT_CONFIG_PREFIX,
|
|
87
|
+
dotenv_prefix: Path = DEFAULT_DOTENV_PATH,
|
|
85
88
|
) -> Callable:
|
|
86
89
|
"""A factory that returns decorator functions which extends a
|
|
87
90
|
pydantic BaseSettings class to read in parameters from a config yaml.
|
|
@@ -102,21 +105,23 @@ def config_from_yaml(
|
|
|
102
105
|
"{prefix}_{actual_variable_name}". Moreover, this prefix is used
|
|
103
106
|
to derive the default location for the config yaml file
|
|
104
107
|
("~/.{prefix}.yaml"). Defaults to "ghga_services".
|
|
108
|
+
dotenv_prefix: (Path, optional):
|
|
109
|
+
When defining parameters via dotenv files, this prefix is used to set the path
|
|
110
|
+
for the dotenv files. The final path used is constructed as
|
|
111
|
+
"{dotenv_prefix}/.env". Defaults to "/secrets".
|
|
105
112
|
"""
|
|
106
113
|
|
|
107
114
|
def decorator(settings) -> Callable:
|
|
108
|
-
# settings should be a pydantic BaseSetting,
|
|
109
|
-
# there is no type hint here to not restrict
|
|
110
|
-
# autocompletion for attributes of the
|
|
111
|
-
# modified settings class returned by the
|
|
112
|
-
# contructor_wrapper
|
|
113
115
|
"""The actual decorator function.
|
|
114
116
|
|
|
115
117
|
Args
|
|
116
118
|
settings (BaseSettings):
|
|
117
119
|
A pydantic BaseSettings class to be modified.
|
|
118
120
|
"""
|
|
119
|
-
#
|
|
121
|
+
# The settings argument should be a pydantic BaseSetting,
|
|
122
|
+
# there is no type hint here to not restrict autocompletion for attributes
|
|
123
|
+
# of the modified settings class returned by the constructor_wrapper.
|
|
124
|
+
# Check if settings inherits from pydantic BaseSettings:
|
|
120
125
|
if not issubclass(settings, BaseSettings):
|
|
121
126
|
raise TypeError(
|
|
122
127
|
"The specified settings class is not a subclass of pydantic_settings.BaseSettings"
|
|
@@ -141,7 +146,12 @@ def config_from_yaml(
|
|
|
141
146
|
class ModSettings(settings):
|
|
142
147
|
"""Modifies the original Settings class provided by the user"""
|
|
143
148
|
|
|
144
|
-
model_config = SettingsConfigDict(
|
|
149
|
+
model_config = SettingsConfigDict(
|
|
150
|
+
frozen=True,
|
|
151
|
+
env_prefix=f"{prefix}_",
|
|
152
|
+
env_file=(".env", dotenv_prefix / ".env"),
|
|
153
|
+
env_nested_delimiter="__",
|
|
154
|
+
)
|
|
145
155
|
|
|
146
156
|
@classmethod
|
|
147
157
|
def settings_customise_sources(
|
|
@@ -156,6 +166,7 @@ def config_from_yaml(
|
|
|
156
166
|
return (
|
|
157
167
|
init_settings,
|
|
158
168
|
env_settings,
|
|
169
|
+
dotenv_settings,
|
|
159
170
|
file_secret_settings,
|
|
160
171
|
YamlConfigSettingsSource(settings_cls, config_yaml),
|
|
161
172
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -178,6 +178,9 @@ class Dao(typing.Protocol[Dto]):
|
|
|
178
178
|
Raises:
|
|
179
179
|
ResourceNotFoundError:
|
|
180
180
|
when resource with the id specified in the dto was not found
|
|
181
|
+
UniqueConstraintViolationError:
|
|
182
|
+
when updating the dto would violate a unique index constraint over some
|
|
183
|
+
field other than the ID field.
|
|
181
184
|
"""
|
|
182
185
|
...
|
|
183
186
|
|
|
@@ -250,6 +253,9 @@ class Dao(typing.Protocol[Dto]):
|
|
|
250
253
|
Raises:
|
|
251
254
|
ResourceAlreadyExistsError:
|
|
252
255
|
when a resource with the ID specified in the dto does already exist.
|
|
256
|
+
UniqueConstraintViolationError:
|
|
257
|
+
when inserting the dto would violate a unique index constraint over some
|
|
258
|
+
field other than the ID field.
|
|
253
259
|
"""
|
|
254
260
|
...
|
|
255
261
|
|
|
@@ -260,6 +266,11 @@ class Dao(typing.Protocol[Dto]):
|
|
|
260
266
|
dto:
|
|
261
267
|
Resource content as a pydantic-based data transfer object including the
|
|
262
268
|
resource ID.
|
|
269
|
+
|
|
270
|
+
Raises:
|
|
271
|
+
UniqueConstraintViolationError:
|
|
272
|
+
when upserting the dto would violate a unique index constraint over some
|
|
273
|
+
field other than the ID field.
|
|
263
274
|
"""
|
|
264
275
|
...
|
|
265
276
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -195,6 +195,38 @@ class ObjectStorageProtocol(ABC):
|
|
|
195
195
|
bucket_id=bucket_id, object_id=object_id
|
|
196
196
|
)
|
|
197
197
|
|
|
198
|
+
async def list_parts(
|
|
199
|
+
self,
|
|
200
|
+
*,
|
|
201
|
+
bucket_id: str,
|
|
202
|
+
object_id: str,
|
|
203
|
+
upload_id: str,
|
|
204
|
+
max_parts: int | None = None,
|
|
205
|
+
first_part_no: int | None = None,
|
|
206
|
+
) -> list[dict]:
|
|
207
|
+
"""Lists the parts that have been uploaded for a specific multipart upload.
|
|
208
|
+
|
|
209
|
+
Specify `max_parts` to return a limited parts list. If not specified, all
|
|
210
|
+
parts will be returned (up to 10,000).
|
|
211
|
+
|
|
212
|
+
Specify `first_part_no` to get parts starting with that part number. If not
|
|
213
|
+
specified, retrieved parts will start with the first part. Part numbers
|
|
214
|
+
start at 1, not 0.
|
|
215
|
+
|
|
216
|
+
Raises:
|
|
217
|
+
ValueError if `max_parts` or `first_part_no` are invalid.
|
|
218
|
+
MultiPartUploadNotFoundError if no upload with `upload_id` exists.
|
|
219
|
+
"""
|
|
220
|
+
self._validate_bucket_id(bucket_id)
|
|
221
|
+
self._validate_object_id(object_id)
|
|
222
|
+
return await self._list_parts(
|
|
223
|
+
bucket_id=bucket_id,
|
|
224
|
+
object_id=object_id,
|
|
225
|
+
upload_id=upload_id,
|
|
226
|
+
max_parts=max_parts,
|
|
227
|
+
first_part_no=first_part_no,
|
|
228
|
+
)
|
|
229
|
+
|
|
198
230
|
async def get_all_multipart_uploads(self, *, bucket_id: str) -> dict[str, str]:
|
|
199
231
|
"""Gets all active multipart uploads for the given bucket ID.
|
|
200
232
|
|
|
@@ -440,6 +472,31 @@ class ObjectStorageProtocol(ABC):
|
|
|
440
472
|
"""
|
|
441
473
|
...
|
|
442
474
|
|
|
475
|
+
@abstractmethod
|
|
476
|
+
async def _list_parts(
|
|
477
|
+
self,
|
|
478
|
+
*,
|
|
479
|
+
bucket_id: str,
|
|
480
|
+
object_id: str,
|
|
481
|
+
upload_id: str,
|
|
482
|
+
max_parts: int | None = None,
|
|
483
|
+
first_part_no: int | None = None,
|
|
484
|
+
) -> list[dict]:
|
|
485
|
+
"""Lists the parts that have been uploaded for a specific multipart upload.
|
|
486
|
+
|
|
487
|
+
Specify `max_parts` to return a limited parts list. If not specified, all
|
|
488
|
+
parts will be returned (up to 10,000).
|
|
489
|
+
|
|
490
|
+
Specify `first_part_no` to get parts starting with that part number. If not
|
|
491
|
+
specified, retrieved parts will start with the first part. Part numbers
|
|
492
|
+
start at 1, not 0.
|
|
493
|
+
|
|
494
|
+
Raises:
|
|
495
|
+
ValueError if `max_parts` or `first_part_no` are invalid.
|
|
496
|
+
MultiPartUploadNotFoundError if no upload with `upload_id` exists.
|
|
497
|
+
"""
|
|
498
|
+
...
|
|
499
|
+
|
|
443
500
|
@abstractmethod
|
|
444
501
|
async def _get_all_multipart_uploads(self, *, bucket_id: str) -> dict[str, str]:
|
|
445
502
|
"""Gets all active multipart uploads for the given bucket ID.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
import logging
|
|
22
|
-
from collections.abc import Sequence
|
|
22
|
+
from collections.abc import AsyncGenerator, Sequence
|
|
23
23
|
from contextlib import asynccontextmanager
|
|
24
24
|
|
|
25
25
|
from aiokafka import AIOKafkaConsumer
|
|
@@ -57,7 +57,7 @@ class KafkaOutboxSubscriber(InboundProviderBase):
|
|
|
57
57
|
translators: Sequence[DaoSubscriberProtocol],
|
|
58
58
|
dlq_publisher: EventPublisherProtocol | None = None,
|
|
59
59
|
kafka_consumer_cls: type[KafkaConsumerCompatible] = AIOKafkaConsumer,
|
|
60
|
-
):
|
|
60
|
+
) -> AsyncGenerator["KafkaOutboxSubscriber", None]:
|
|
61
61
|
"""Setup and teardown an instance of the provider.
|
|
62
62
|
|
|
63
63
|
Args:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -331,9 +331,11 @@ class KafkaConsumerCompatible(Protocol):
|
|
|
331
331
|
An identifier for the consumer group.
|
|
332
332
|
auto_offset_reset:
|
|
333
333
|
Can be set to "earliest".
|
|
334
|
-
|
|
334
|
+
enable_auto_commit:
|
|
335
|
+
Whether to enable auto-committing of offsets.
|
|
336
|
+
key_deserializer:
|
|
335
337
|
Function to deserialize the keys into strings.
|
|
336
|
-
|
|
338
|
+
value_deserializer:
|
|
337
339
|
Function to deserialize the values into strings.
|
|
338
340
|
max_partition_fetch_bytes:
|
|
339
341
|
Maximum receivable message size
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -644,11 +644,11 @@ class KafkaContainerFixture(KafkaContainer):
|
|
|
644
644
|
"""Run the given command in the kafka testcontainer.
|
|
645
645
|
|
|
646
646
|
Args:
|
|
647
|
-
|
|
648
|
-
|
|
647
|
+
command: The full command to run.
|
|
648
|
+
run_in_shell: If True, will run the command in a shell.
|
|
649
649
|
|
|
650
650
|
Raises:
|
|
651
|
-
|
|
651
|
+
RuntimeError: when the exit code returned by the command is not zero.
|
|
652
652
|
"""
|
|
653
653
|
cmd = ["sh", "-c", command] if run_in_shell else command
|
|
654
654
|
exit_code, output = self.get_wrapped_container().exec_run(cmd)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2021 -
|
|
1
|
+
# Copyright 2021 - 2026 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
2
|
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|