hexkit 6.0.0__tar.gz → 7.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hexkit-6.0.0/src/hexkit.egg-info → hexkit-7.1.0}/PKG-INFO +21 -21
- {hexkit-6.0.0 → hexkit-7.1.0}/pyproject.toml +28 -30
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/config.py +5 -4
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/custom_types.py +12 -14
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/log.py +3 -3
- hexkit-7.1.0/src/hexkit/opentelemetry.py +76 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/protocols/dao.py +5 -5
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/protocols/daopub.py +5 -6
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/protocols/eventpub.py +2 -3
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/protocols/objstorage.py +20 -24
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/config.py +2 -2
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/provider/daosub.py +1 -2
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/provider/eventpub.py +4 -4
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/provider/eventsub.py +11 -11
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/provider/utils.py +1 -2
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/testcontainer.py +6 -6
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/testutils.py +14 -14
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/migrations/_manager.py +2 -2
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/migrations/_utils.py +5 -5
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/migrations/helpers.py +2 -3
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/provider.py +4 -4
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/testutils.py +2 -3
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/provider/daopub.py +5 -5
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/provider/persistent_pub.py +3 -4
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/provider.py +47 -46
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/testutils/_fixtures.py +6 -6
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/testing/eventpub.py +2 -2
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/utils.py +2 -2
- {hexkit-6.0.0 → hexkit-7.1.0/src/hexkit.egg-info}/PKG-INFO +21 -21
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit.egg-info/SOURCES.txt +0 -1
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit.egg-info/requires.txt +19 -18
- hexkit-6.0.0/src/hexkit/opentelemetry.py +0 -177
- hexkit-6.0.0/src/hexkit.egg-info/entry_points.txt +0 -2
- {hexkit-6.0.0 → hexkit-7.1.0}/LICENSE +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/MANIFEST.in +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/README.md +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/setup.cfg +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/__main__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/base.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/correlation.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/protocols/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/protocols/daosub.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/protocols/eventsub.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/akafka/provider/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongodb/migrations/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/provider/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/provider/config.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/mongokafka/testutils.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/test_files/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/test_files/test_file1.yaml +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/test_files/test_file2.yaml +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/test_files/test_file3.yaml +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/test_files/test_file4.yaml +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/testutils/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/testutils/_typical_workflow.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/s3/testutils/_utils.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/providers/testing/__init__.py +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit/py.typed +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit.egg-info/dependency_links.txt +0 -0
- {hexkit-6.0.0 → hexkit-7.1.0}/src/hexkit.egg-info/top_level.txt +0 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hexkit
|
|
3
|
-
Version:
|
|
3
|
+
Version: 7.1.0
|
|
4
4
|
Summary: A Toolkit for Building Microservices using the Hexagonal Architecture
|
|
5
5
|
Author-email: "German Human Genome Phenome Archive (GHGA)" <contact@ghga.de>
|
|
6
6
|
License: Apache 2.0
|
|
7
7
|
Project-URL: Repository, https://github.com/ghga-de/hexkit
|
|
8
8
|
Classifier: Development Status :: 5 - Production/Stable
|
|
9
9
|
Classifier: Operating System :: POSIX :: Linux
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
11
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -16,41 +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.
|
|
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"
|
|
39
39
|
Provides-Extra: opentelemetry-akafka
|
|
40
40
|
Requires-Dist: hexkit[opentelemetry-base]; extra == "opentelemetry-akafka"
|
|
41
41
|
Requires-Dist: hexkit[akafka]; extra == "opentelemetry-akafka"
|
|
42
|
-
Requires-Dist: opentelemetry-instrumentation-aiokafka>=0.
|
|
42
|
+
Requires-Dist: opentelemetry-instrumentation-aiokafka>=0.58b0; extra == "opentelemetry-akafka"
|
|
43
43
|
Provides-Extra: opentelemetry-mongodb
|
|
44
44
|
Requires-Dist: hexkit[opentelemetry-base]; extra == "opentelemetry-mongodb"
|
|
45
45
|
Requires-Dist: hexkit[mongodb]; extra == "opentelemetry-mongodb"
|
|
46
|
-
Requires-Dist: opentelemetry-instrumentation-pymongo>=0.
|
|
46
|
+
Requires-Dist: opentelemetry-instrumentation-pymongo>=0.58b0; extra == "opentelemetry-mongodb"
|
|
47
47
|
Provides-Extra: opentelemetry-fastapi
|
|
48
48
|
Requires-Dist: hexkit[opentelemetry-base]; extra == "opentelemetry-fastapi"
|
|
49
|
-
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.
|
|
49
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.58b0; extra == "opentelemetry-fastapi"
|
|
50
50
|
Provides-Extra: opentelemetry-s3
|
|
51
51
|
Requires-Dist: hexkit[opentelemetry-base]; extra == "opentelemetry-s3"
|
|
52
52
|
Requires-Dist: hexkit[s3]; extra == "opentelemetry-s3"
|
|
53
|
-
Requires-Dist: opentelemetry-instrumentation-botocore>=0.
|
|
53
|
+
Requires-Dist: opentelemetry-instrumentation-botocore>=0.58b0; extra == "opentelemetry-s3"
|
|
54
54
|
Provides-Extra: opentelemetry
|
|
55
55
|
Requires-Dist: hexkit[opentelemetry-akafka]; extra == "opentelemetry"
|
|
56
56
|
Requires-Dist: hexkit[opentelemetry-mongodb]; extra == "opentelemetry"
|
|
@@ -58,13 +58,13 @@ Requires-Dist: hexkit[opentelemetry-fastapi]; extra == "opentelemetry"
|
|
|
58
58
|
Requires-Dist: hexkit[opentelemetry-s3]; extra == "opentelemetry"
|
|
59
59
|
Provides-Extra: test-akafka
|
|
60
60
|
Requires-Dist: hexkit[akafka]; extra == "test-akafka"
|
|
61
|
-
Requires-Dist: testcontainers[kafka]<5,>=4.
|
|
61
|
+
Requires-Dist: testcontainers[kafka]<5,>=4.13; extra == "test-akafka"
|
|
62
62
|
Provides-Extra: test-s3
|
|
63
63
|
Requires-Dist: hexkit[s3]; extra == "test-s3"
|
|
64
|
-
Requires-Dist: testcontainers<5,>=4.
|
|
64
|
+
Requires-Dist: testcontainers<5,>=4.13; extra == "test-s3"
|
|
65
65
|
Provides-Extra: test-mongodb
|
|
66
66
|
Requires-Dist: hexkit[mongodb]; extra == "test-mongodb"
|
|
67
|
-
Requires-Dist: testcontainers[mongo]<5,>=4.
|
|
67
|
+
Requires-Dist: testcontainers[mongo]<5,>=4.13; extra == "test-mongodb"
|
|
68
68
|
Provides-Extra: test
|
|
69
69
|
Requires-Dist: hexkit[test-akafka,test-mongodb,test-s3]; extra == "test"
|
|
70
70
|
Provides-Extra: all
|
|
@@ -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 = "
|
|
26
|
+
version = "7.1.0"
|
|
28
27
|
description = "A Toolkit for Building Microservices using the Hexagonal Architecture"
|
|
29
28
|
dependencies = [
|
|
30
|
-
"opentelemetry-api >=1.
|
|
31
|
-
"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,39 +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.
|
|
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",
|
|
56
56
|
]
|
|
57
57
|
opentelemetry-akafka = [
|
|
58
58
|
"hexkit[opentelemetry-base]",
|
|
59
59
|
"hexkit[akafka]",
|
|
60
|
-
"opentelemetry-instrumentation-aiokafka >=0.
|
|
60
|
+
"opentelemetry-instrumentation-aiokafka >=0.58b0",
|
|
61
61
|
]
|
|
62
62
|
opentelemetry-mongodb = [
|
|
63
63
|
"hexkit[opentelemetry-base]",
|
|
64
64
|
"hexkit[mongodb]",
|
|
65
|
-
"opentelemetry-instrumentation-pymongo >=0.
|
|
65
|
+
"opentelemetry-instrumentation-pymongo >=0.58b0",
|
|
66
66
|
]
|
|
67
67
|
opentelemetry-fastapi = [
|
|
68
68
|
"hexkit[opentelemetry-base]",
|
|
69
|
-
"opentelemetry-instrumentation-fastapi >=0.
|
|
69
|
+
"opentelemetry-instrumentation-fastapi >=0.58b0",
|
|
70
70
|
]
|
|
71
71
|
opentelemetry-s3 = [
|
|
72
72
|
"hexkit[opentelemetry-base]",
|
|
73
73
|
"hexkit[s3]",
|
|
74
|
-
"opentelemetry-instrumentation-botocore >=0.
|
|
74
|
+
"opentelemetry-instrumentation-botocore >=0.58b0",
|
|
75
75
|
]
|
|
76
76
|
opentelemetry = [
|
|
77
77
|
"hexkit[opentelemetry-akafka]",
|
|
@@ -81,15 +81,15 @@ opentelemetry = [
|
|
|
81
81
|
]
|
|
82
82
|
test-akafka = [
|
|
83
83
|
"hexkit[akafka]",
|
|
84
|
-
"testcontainers[kafka] >=4.
|
|
84
|
+
"testcontainers[kafka] >=4.13, <5",
|
|
85
85
|
]
|
|
86
86
|
test-s3 = [
|
|
87
87
|
"hexkit[s3]",
|
|
88
|
-
"testcontainers >=4.
|
|
88
|
+
"testcontainers >=4.13, <5",
|
|
89
89
|
]
|
|
90
90
|
test-mongodb = [
|
|
91
91
|
"hexkit[mongodb]",
|
|
92
|
-
"testcontainers[mongo] >=4.
|
|
92
|
+
"testcontainers[mongo] >=4.13, <5",
|
|
93
93
|
]
|
|
94
94
|
test = [
|
|
95
95
|
"hexkit[test-akafka,test-s3,test-mongodb]",
|
|
@@ -102,9 +102,6 @@ all = [
|
|
|
102
102
|
[project.urls]
|
|
103
103
|
Repository = "https://github.com/ghga-de/hexkit"
|
|
104
104
|
|
|
105
|
-
[project.entry-points.opentelemetry_distro]
|
|
106
|
-
hexkit_distro = "hexkit.opentelemetry:HexkitDistro"
|
|
107
|
-
|
|
108
105
|
[tool.setuptools.packages.find]
|
|
109
106
|
where = [
|
|
110
107
|
"src",
|
|
@@ -125,7 +122,7 @@ src = [
|
|
|
125
122
|
"examples",
|
|
126
123
|
"scripts",
|
|
127
124
|
]
|
|
128
|
-
target-version = "
|
|
125
|
+
target-version = "py310"
|
|
129
126
|
|
|
130
127
|
[tool.ruff.lint]
|
|
131
128
|
fixable = [
|
|
@@ -212,7 +209,7 @@ check_untyped_defs = true
|
|
|
212
209
|
no_site_packages = false
|
|
213
210
|
|
|
214
211
|
[tool.pytest.ini_options]
|
|
215
|
-
minversion = "8.
|
|
212
|
+
minversion = "8.4"
|
|
216
213
|
asyncio_mode = "strict"
|
|
217
214
|
asyncio_default_fixture_loop_scope = "function"
|
|
218
215
|
|
|
@@ -226,11 +223,10 @@ source = [
|
|
|
226
223
|
[tool.tox]
|
|
227
224
|
legacy_tox_ini = """
|
|
228
225
|
[tox]
|
|
229
|
-
env_list = py3{
|
|
226
|
+
env_list = py3{10,11,12,13}
|
|
230
227
|
|
|
231
228
|
[gh-actions]
|
|
232
229
|
python =
|
|
233
|
-
3.9: py39
|
|
234
230
|
3.10: py310
|
|
235
231
|
3.11: py311
|
|
236
232
|
3.12: py312
|
|
@@ -242,5 +238,7 @@ legacy_tox_ini = """
|
|
|
242
238
|
DOCKER_HOST
|
|
243
239
|
deps =
|
|
244
240
|
--no-deps -r ./lock/requirements-dev.txt
|
|
245
|
-
commands =
|
|
241
|
+
commands =
|
|
242
|
+
py310: pip install --no-deps backports.asyncio.runner==1.2.0 exceptiongroup==1.3.0 tomli==2.2.1
|
|
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
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Copyright 2021 - 2025 Universität Tübingen, DKFZ, EMBL, and Universität zu Köln
|
|
2
|
+
# for the German Human Genome-Phenome Archive (GHGA)
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""OpenTelemetry specific configuration code. This is gated behind the opentelemetry extra."""
|
|
16
|
+
|
|
17
|
+
import logging
|
|
18
|
+
import os
|
|
19
|
+
from typing import Annotated
|
|
20
|
+
|
|
21
|
+
from opentelemetry import trace
|
|
22
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
23
|
+
from opentelemetry.sdk.environment_variables import OTEL_SDK_DISABLED
|
|
24
|
+
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
|
|
25
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
26
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
27
|
+
from opentelemetry.sdk.trace.sampling import ParentBasedTraceIdRatio
|
|
28
|
+
from pydantic import Field
|
|
29
|
+
from pydantic_settings import BaseSettings
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class OpenTelemetryConfig(BaseSettings):
|
|
35
|
+
"""OpenTelemetry specific configuration options"""
|
|
36
|
+
|
|
37
|
+
enable_opentelemetry: bool = Field(
|
|
38
|
+
default=False,
|
|
39
|
+
description="If set to true, this will run necessary setup code."
|
|
40
|
+
"If set to false, environment variables are set that should also effectively "
|
|
41
|
+
"disable autoinstrumentation.",
|
|
42
|
+
)
|
|
43
|
+
otel_trace_sampling_rate: Annotated[float, Field(strict=True, ge=0, le=1)] = Field(
|
|
44
|
+
default=1.0,
|
|
45
|
+
description="Determines which proportion of spans should be sampled. "
|
|
46
|
+
"A value of 1.0 means all and is equivalent to the previous behaviour. "
|
|
47
|
+
"Setting this to 0 will result in no spans being sampled, but this does not "
|
|
48
|
+
"automatically set `enable_opentelemetry` to False.",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def configure_opentelemetry(*, service_name: str, config: OpenTelemetryConfig):
|
|
53
|
+
"""Configure all needed parts of OpenTelemetry.
|
|
54
|
+
|
|
55
|
+
Setup of the TracerProvider is done programmatically, while disabling OpenTelemetry
|
|
56
|
+
sets the corresponding environment variable.
|
|
57
|
+
"""
|
|
58
|
+
if config.enable_opentelemetry:
|
|
59
|
+
resource = Resource(attributes={SERVICE_NAME: service_name})
|
|
60
|
+
# Replace the default static sampler with a probabilistic one that honors parent
|
|
61
|
+
# span sampling decisions
|
|
62
|
+
# This should consistently yield full traces within a service but not necessarily
|
|
63
|
+
# across service boundaries
|
|
64
|
+
# With the default sampling rate, behaviour does not change, but this allows to
|
|
65
|
+
# introduce head sampling by adjusting a config option on the service side later on
|
|
66
|
+
sampler = ParentBasedTraceIdRatio(rate=config.otel_trace_sampling_rate)
|
|
67
|
+
|
|
68
|
+
# Initialize service specific TracerProvider
|
|
69
|
+
trace_provider = TracerProvider(resource=resource, sampler=sampler)
|
|
70
|
+
processor = BatchSpanProcessor(OTLPSpanExporter())
|
|
71
|
+
trace_provider.add_span_processor(processor)
|
|
72
|
+
trace.set_tracer_provider(trace_provider)
|
|
73
|
+
else:
|
|
74
|
+
# Currently OTEL_SDK_DISABLED doesn't seem to be honored by all implementations yet
|
|
75
|
+
# It seems to be working well enough for the Python implementation.
|
|
76
|
+
os.environ[OTEL_SDK_DISABLED] = "true"
|
|
@@ -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
|
|