intersect-sdk 0.9.0__tar.gz → 0.9.2__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.
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/PKG-INFO +11 -13
- intersect_sdk-0.9.2/pyproject.toml +199 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/__init__.py +74 -42
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/interfaces.py +2 -1
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/pydantic_schema_generator.py +45 -12
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/schema.py +11 -8
- intersect_sdk-0.9.2/src/intersect_sdk/_internal/service_queue_name.py +14 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/capability/universal_capability/status.py +0 -2
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/client.py +21 -23
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/config/client.py +3 -3
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/config/service.py +7 -4
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/exceptions.py +2 -2
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/schema.py +1 -1
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/service.py +92 -40
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/service_definitions.py +1 -1
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/shared_callback_definitions.py +5 -3
- intersect_sdk-0.9.2/src/intersect_sdk/version.py +9 -0
- intersect_sdk-0.9.0/LICENSE +0 -29
- intersect_sdk-0.9.0/pyproject.toml +0 -253
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/control_plane/__init__.py +0 -0
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/control_plane/brokers/__init__.py +0 -0
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/control_plane/brokers/amqp_client.py +0 -627
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/control_plane/brokers/broker_client.py +0 -76
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/control_plane/brokers/mqtt_client.py +0 -288
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/control_plane/control_plane_manager.py +0 -182
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/control_plane/definitions.py +0 -10
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/control_plane/topic_handler.py +0 -17
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/data_plane/__init__.py +0 -0
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/data_plane/data_plane_manager.py +0 -113
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/data_plane/minio_utils.py +0 -154
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/exceptions.py +0 -17
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/messages/__init__.py +0 -0
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/messages/event.py +0 -145
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/messages/lifecycle.py +0 -107
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/messages/userspace.py +0 -183
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/multi_flag_thread_event.py +0 -77
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/version.py +0 -18
- intersect_sdk-0.9.0/src/intersect_sdk/_internal/version_resolver.py +0 -59
- intersect_sdk-0.9.0/src/intersect_sdk/config/shared.py +0 -168
- intersect_sdk-0.9.0/src/intersect_sdk/constants.py +0 -28
- intersect_sdk-0.9.0/src/intersect_sdk/core_definitions.py +0 -47
- intersect_sdk-0.9.0/src/intersect_sdk/version.py +0 -19
- intersect_sdk-0.9.0/tests/__init__.py +0 -0
- intersect_sdk-0.9.0/tests/conftest.py +0 -0
- intersect_sdk-0.9.0/tests/e2e/__init__.py +0 -0
- intersect_sdk-0.9.0/tests/e2e/test_examples.py +0 -152
- intersect_sdk-0.9.0/tests/fixtures/__init__.py +0 -0
- intersect_sdk-0.9.0/tests/fixtures/example_schema.json +0 -1275
- intersect_sdk-0.9.0/tests/fixtures/example_schema.py +0 -622
- intersect_sdk-0.9.0/tests/fixtures/return_type_mismatch.py +0 -7
- intersect_sdk-0.9.0/tests/integration/__init__.py +0 -0
- intersect_sdk-0.9.0/tests/integration/test_return_type_mismatch.py +0 -126
- intersect_sdk-0.9.0/tests/integration/test_service.py +0 -510
- intersect_sdk-0.9.0/tests/unit/__init__.py +0 -0
- intersect_sdk-0.9.0/tests/unit/test_annotations.py +0 -103
- intersect_sdk-0.9.0/tests/unit/test_base_capability_implementation.py +0 -169
- intersect_sdk-0.9.0/tests/unit/test_config.py +0 -194
- intersect_sdk-0.9.0/tests/unit/test_event_message_headers.py +0 -119
- intersect_sdk-0.9.0/tests/unit/test_imports.py +0 -7
- intersect_sdk-0.9.0/tests/unit/test_invalid_schema_runtime.py +0 -48
- intersect_sdk-0.9.0/tests/unit/test_lifecycle_message_headers.py +0 -101
- intersect_sdk-0.9.0/tests/unit/test_schema_invalids.py +0 -929
- intersect_sdk-0.9.0/tests/unit/test_schema_ref_resolution.py +0 -55
- intersect_sdk-0.9.0/tests/unit/test_schema_valid.py +0 -157
- intersect_sdk-0.9.0/tests/unit/test_userspace_message_headers.py +0 -139
- intersect_sdk-0.9.0/tests/unit/test_version_resolver.py +0 -123
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/README.md +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/__init__.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/constants.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/event_metadata.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/function_metadata.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/generic_serializer.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/logger.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/status_metadata.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/stoppable_thread.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/utils.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/app_lifecycle.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/capability/__init__.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/capability/base.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/capability/universal_capability/__init__.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/capability/universal_capability/universal_capability.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/client_callback_definitions.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/config/__init__.py +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/py.typed +0 -0
- {intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/service_callback_definitions.py +0 -0
|
@@ -1,30 +1,28 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: intersect-sdk
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.2
|
|
4
4
|
Summary: Python SDK to interact with INTERSECT
|
|
5
5
|
Keywords: intersect
|
|
6
|
-
Author
|
|
6
|
+
Author: Lance Drane, Marshall McDonnell, Seth Hitefield, Andrew Ayres, Gregory Cage, Jesse McGaha, Robert Smith, Gavin Wiggins, Michael Brim, Rick Archibald, Addi Malviya Thakur
|
|
7
|
+
Author-email: Lance Drane <dranelt@ornl.gov>, Marshall McDonnell <mcdonnellmt@ornl.gov>, Seth Hitefield <hitefieldsd@ornl.gov>, Andrew Ayres <ayresaf@ornl.gov>, Gregory Cage <cagege@ornl.gov>, Jesse McGaha <mcgahajr@ornl.gov>, Robert Smith <smithrw@ornl.gov>, Gavin Wiggins <wigginsg@ornl.gov>, Michael Brim <brimmj@ornl.gov>, Rick Archibald <archibaldrk@ornl.gov>, Addi Malviya Thakur <malviyaa@ornl.gov>
|
|
7
8
|
License: BSD-3-Clause
|
|
8
9
|
Classifier: Programming Language :: Python :: 3
|
|
9
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
10
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Requires-Dist: pydantic>=2.7.0
|
|
15
|
+
Requires-Dist: intersect-sdk-common>=0.9.6,<0.10.0
|
|
16
|
+
Requires-Dist: jsonschema[format-nongpl]>=4.21.1
|
|
17
|
+
Requires-Dist: psutil>=7.0.0
|
|
18
|
+
Requires-Dist: sphinx>=5.3.0 ; extra == 'docs'
|
|
19
|
+
Requires-Dist: furo>=2023.3.27 ; extra == 'docs'
|
|
20
|
+
Requires-Python: >=3.10, <4.0
|
|
13
21
|
Project-URL: Homepage, https://github.com/INTERSECT-SDK/python-sdk/
|
|
14
22
|
Project-URL: Changelog, https://github.com/INTERSECT-SDK/python-sdk/blob/main/CHANGELOG.md
|
|
15
23
|
Project-URL: Documentation, https://intersect-python-sdk.readthedocs.io/en/latest/
|
|
16
24
|
Project-URL: Issues, https://github.com/INTERSECT-SDK/python-sdk/issues
|
|
17
|
-
Requires-Python: <4.0,>=3.10
|
|
18
|
-
Requires-Dist: pydantic>=2.7.0
|
|
19
|
-
Requires-Dist: retrying<2.0.0,>=1.3.4
|
|
20
|
-
Requires-Dist: paho-mqtt<3.0.0,>=2.1.0
|
|
21
|
-
Requires-Dist: pika<2.0.0,>=1.3.2
|
|
22
|
-
Requires-Dist: minio>=7.2.3
|
|
23
|
-
Requires-Dist: jsonschema[format-nongpl]>=4.21.1
|
|
24
|
-
Requires-Dist: psutil>=7.0.0
|
|
25
25
|
Provides-Extra: docs
|
|
26
|
-
Requires-Dist: sphinx>=5.3.0; extra == "docs"
|
|
27
|
-
Requires-Dist: furo>=2023.3.27; extra == "docs"
|
|
28
26
|
Description-Content-Type: text/markdown
|
|
29
27
|
|
|
30
28
|
[](https://doi.org/10.11578/dc.20240927.1)
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "intersect-sdk"
|
|
3
|
+
description = "Python SDK to interact with INTERSECT"
|
|
4
|
+
authors = [
|
|
5
|
+
{ name = "Lance Drane", email = "dranelt@ornl.gov" },
|
|
6
|
+
{ name = "Marshall McDonnell", email = "mcdonnellmt@ornl.gov" },
|
|
7
|
+
{ name = "Seth Hitefield", email = "hitefieldsd@ornl.gov" },
|
|
8
|
+
{ name = "Andrew Ayres", email = "ayresaf@ornl.gov" },
|
|
9
|
+
{ name = "Gregory Cage", email = "cagege@ornl.gov" },
|
|
10
|
+
{ name = "Jesse McGaha", email = "mcgahajr@ornl.gov" },
|
|
11
|
+
{ name = "Robert Smith", email = "smithrw@ornl.gov" },
|
|
12
|
+
{ name = "Gavin Wiggins", email = "wigginsg@ornl.gov" },
|
|
13
|
+
{ name = "Michael Brim", email = "brimmj@ornl.gov" },
|
|
14
|
+
{ name = "Rick Archibald", email = "archibaldrk@ornl.gov" },
|
|
15
|
+
{ name = "Addi Malviya Thakur", email = "malviyaa@ornl.gov" },
|
|
16
|
+
]
|
|
17
|
+
version = "0.9.2"
|
|
18
|
+
readme = "README.md"
|
|
19
|
+
license = { text = "BSD-3-Clause" }
|
|
20
|
+
requires-python = ">=3.10,<4.0"
|
|
21
|
+
keywords = ["intersect"]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"pydantic>=2.7.0",
|
|
31
|
+
"intersect-sdk-common>=0.9.6,<0.10.0",
|
|
32
|
+
"jsonschema[format-nongpl]>=4.21.1", # extras necessary for enforcing formats
|
|
33
|
+
#"brotli>=1.1.0", # TODO - add this dependency when we add compression
|
|
34
|
+
"psutil>=7.0.0",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://github.com/INTERSECT-SDK/python-sdk/"
|
|
39
|
+
Changelog = "https://github.com/INTERSECT-SDK/python-sdk/blob/main/CHANGELOG.md"
|
|
40
|
+
Documentation = "https://intersect-python-sdk.readthedocs.io/en/latest/"
|
|
41
|
+
Issues = "https://github.com/INTERSECT-SDK/python-sdk/issues"
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
docs = ["sphinx>=5.3.0", "furo>=2023.3.27"]
|
|
45
|
+
|
|
46
|
+
[dependency-groups]
|
|
47
|
+
dev = [
|
|
48
|
+
"pre-commit>=3.3.1",
|
|
49
|
+
"ruff==0.12.7",
|
|
50
|
+
"mypy>=1.10.0",
|
|
51
|
+
"codespell>=2.3.0",
|
|
52
|
+
"pytest>=7.3.2",
|
|
53
|
+
"pytest-cov>=4.1.0",
|
|
54
|
+
"fastapi",
|
|
55
|
+
"uvicorn",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[build-system]
|
|
59
|
+
requires = ["uv_build>=0.10.2,<0.11.0"]
|
|
60
|
+
build-backend = "uv_build"
|
|
61
|
+
|
|
62
|
+
[tool.ruff]
|
|
63
|
+
line-length = 100
|
|
64
|
+
format = { quote-style = 'single' }
|
|
65
|
+
|
|
66
|
+
[tool.ruff.lint]
|
|
67
|
+
isort = { known-first-party = ['src'] }
|
|
68
|
+
pydocstyle = { convention = 'google' }
|
|
69
|
+
flake8-quotes = { inline-quotes = 'single', multiline-quotes = 'double' }
|
|
70
|
+
mccabe = { max-complexity = 20 }
|
|
71
|
+
pylint = { max-args = 10, max-branches = 20, max-returns = 15, max-statements = 75 }
|
|
72
|
+
# pyflakes and the relevant pycodestyle rules are already configured
|
|
73
|
+
extend-select = [
|
|
74
|
+
'C90', # mccabe complexity
|
|
75
|
+
'I', # isort
|
|
76
|
+
'N', # pep8-naming
|
|
77
|
+
'D', # pydocstyle
|
|
78
|
+
'UP', # pyupgrade
|
|
79
|
+
'YTT', # flake8-2020
|
|
80
|
+
'ANN', # flake8-annotations
|
|
81
|
+
'ASYNC', # flake8-async
|
|
82
|
+
'S', # flake8-bandit
|
|
83
|
+
'BLE', # flake8-blind-except
|
|
84
|
+
'B', # flake8-bugbear
|
|
85
|
+
'A', # flake8-builtins
|
|
86
|
+
'COM', # flake8-commas
|
|
87
|
+
'C4', # flake8-comprehensions
|
|
88
|
+
'DTZ', # flake8-datetimez
|
|
89
|
+
'T10', # flake8-debugger
|
|
90
|
+
'EM', # flake8-error-message
|
|
91
|
+
'FA', # flake8-future-annotations
|
|
92
|
+
'ISC', # flake8-implicit-string-concat
|
|
93
|
+
'ICN', # flake8-import-conventions
|
|
94
|
+
'G', # flake8-logging-format
|
|
95
|
+
'INP', # flake8-no-pep420
|
|
96
|
+
'PIE', # flake8-PIE
|
|
97
|
+
'T20', # flake8-T20
|
|
98
|
+
'PYI', # flake8-pyi
|
|
99
|
+
'PT', # flake8-pytest-style
|
|
100
|
+
'Q', # flake8-quotes
|
|
101
|
+
'RSE', # flake8-raise
|
|
102
|
+
'RET', # flake8-return
|
|
103
|
+
'SLF', # flake8-self
|
|
104
|
+
'SLOT', # flake8-slots
|
|
105
|
+
'SIM', # flake8-simplify
|
|
106
|
+
'TC', # flake8-type-checking
|
|
107
|
+
'ARG', # flake8-unused-arguments
|
|
108
|
+
'PTH', # flake8-use-pathlib
|
|
109
|
+
'PGH', # pygrep-hooks
|
|
110
|
+
'PL', # pylint
|
|
111
|
+
'TRY', # tryceratops
|
|
112
|
+
'FLY', # flynt
|
|
113
|
+
'RUF', # RUFF additional rules
|
|
114
|
+
'INT', # flake8-gettext
|
|
115
|
+
]
|
|
116
|
+
# If you're seeking to disable a rule, first consider whether the rule is overbearing, or if it should only be turned off for your usecase.
|
|
117
|
+
ignore = [
|
|
118
|
+
'COM812', # formatter, handled by Ruff format
|
|
119
|
+
'ISC001', # formatter, handled by Ruff format
|
|
120
|
+
'SIM105', # "with contextlib.suppress():" is slower than try-except-pass
|
|
121
|
+
'ANN401', # allow explicit "Any" typing, use with care
|
|
122
|
+
'PLR2004', # allow "magic numbers"
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
[tool.ruff.lint.flake8-type-checking]
|
|
126
|
+
runtime-evaluated-base-classes = [
|
|
127
|
+
"pydantic.BaseModel",
|
|
128
|
+
"intersect_sdk.IntersectBaseCapabilityImplementation",
|
|
129
|
+
]
|
|
130
|
+
runtime-evaluated-decorators = [
|
|
131
|
+
"pydantic.dataclasses.dataclass",
|
|
132
|
+
"pydantic.validate_call",
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
[tool.ruff.lint.extend-per-file-ignores]
|
|
136
|
+
'__init__.py' = [
|
|
137
|
+
'F401', # __init__.py commonly has unused imports
|
|
138
|
+
'TC004', # do lazy imports when importing from the base module
|
|
139
|
+
]
|
|
140
|
+
'docs/*' = [
|
|
141
|
+
'D', # the documentation folder does not need documentation
|
|
142
|
+
'INP001', # docs are not a namespace package
|
|
143
|
+
]
|
|
144
|
+
'examples/*' = [
|
|
145
|
+
'N999', # module names for examples are not standard
|
|
146
|
+
'T20', # allow print/pprint statements in examples
|
|
147
|
+
'S106', # don't care about credentials in examples
|
|
148
|
+
'D100', # documenting modules in examples is unhelpful
|
|
149
|
+
'D104', # documenting packages in examples is unhelpful
|
|
150
|
+
'TRY002', # examples can raise their own exception
|
|
151
|
+
]
|
|
152
|
+
'tests/*' = [
|
|
153
|
+
'S101', # allow assert statements in tests
|
|
154
|
+
'S106', # don't care about credentials in tests
|
|
155
|
+
'S311', # don't care about cryptographic security in tests
|
|
156
|
+
'SLF001', # allow private member access in tests
|
|
157
|
+
'ANN', # tests in general don't need types, unless they are runtime types.
|
|
158
|
+
'ARG', # allow unused parameters in tests
|
|
159
|
+
'D', # ignore documentation in tests
|
|
160
|
+
'RUF012', # permit "mutable" class attributes to not be annotated with typing.ClassVar (these shouldn't be mutated anyways...)
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
# see https://mypy.readthedocs.io/en/stable/config_file.html for a complete reference
|
|
164
|
+
[tool.mypy]
|
|
165
|
+
strict = true
|
|
166
|
+
ignore_missing_imports = true # don't require typing for library stubs if they don't exist
|
|
167
|
+
disallow_untyped_decorators = false # this is needed for library decorator compatibility, i.e. "retrying"
|
|
168
|
+
plugins = ["pydantic.mypy"]
|
|
169
|
+
|
|
170
|
+
[tool.pydantic-mypy]
|
|
171
|
+
init_forbid_extra = true
|
|
172
|
+
init_typed = true
|
|
173
|
+
warn_required_dynamic_aliases = true
|
|
174
|
+
warn_untyped_fields = true
|
|
175
|
+
|
|
176
|
+
[tool.pytest.ini_options]
|
|
177
|
+
log_cli = true
|
|
178
|
+
addopts = "-ra"
|
|
179
|
+
|
|
180
|
+
[tool.coverage.report]
|
|
181
|
+
omit = [
|
|
182
|
+
'*__init__*', # __init__ files should just re-export other classes and functions
|
|
183
|
+
'*/discovery_service.py', # currently unused
|
|
184
|
+
]
|
|
185
|
+
exclude_also = [
|
|
186
|
+
'pragma: no-cover', # standard
|
|
187
|
+
'if (typing\\.)?TYPE_CHECKING:', # type checking blocks are not executed in coverage, but we don't care
|
|
188
|
+
'@(abc\\.)?abstractmethod', # don't try to cover abstract methods
|
|
189
|
+
"class .*\\bProtocol\\):", # don't cover protocol classes (similar to abstract classes)
|
|
190
|
+
'raise NotImplementedError', # it's not implemented so shouldn't be covered
|
|
191
|
+
'except.* ImportError', # these are usually used to throw a "friendlier" error and are not really worth testing
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
[tool.codespell]
|
|
195
|
+
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
|
|
196
|
+
skip = '.git*,*.lock,.venv,.*cache/*,./docs/_build/*'
|
|
197
|
+
check-hidden = true
|
|
198
|
+
# ignore-regex = ''
|
|
199
|
+
# ignore-words-list = ''
|
|
@@ -12,6 +12,18 @@ from typing import TYPE_CHECKING
|
|
|
12
12
|
|
|
13
13
|
# import everything eagerly for IDEs/LSPs
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
|
+
from intersect_sdk_common import (
|
|
16
|
+
ControlPlaneConfig,
|
|
17
|
+
ControlProvider,
|
|
18
|
+
DataStoreConfig,
|
|
19
|
+
DataStoreConfigMap,
|
|
20
|
+
HierarchyConfig,
|
|
21
|
+
IntersectDataHandler,
|
|
22
|
+
IntersectMimeType,
|
|
23
|
+
intersect_sdk_version_info,
|
|
24
|
+
intersect_sdk_version_string,
|
|
25
|
+
)
|
|
26
|
+
|
|
15
27
|
from .app_lifecycle import default_intersect_lifecycle_loop
|
|
16
28
|
from .capability.base import IntersectBaseCapabilityImplementation
|
|
17
29
|
from .client import IntersectClient
|
|
@@ -22,14 +34,6 @@ if TYPE_CHECKING:
|
|
|
22
34
|
)
|
|
23
35
|
from .config.client import IntersectClientConfig
|
|
24
36
|
from .config.service import IntersectServiceConfig
|
|
25
|
-
from .config.shared import (
|
|
26
|
-
ControlPlaneConfig,
|
|
27
|
-
ControlProvider,
|
|
28
|
-
DataStoreConfig,
|
|
29
|
-
DataStoreConfigMap,
|
|
30
|
-
HierarchyConfig,
|
|
31
|
-
)
|
|
32
|
-
from .core_definitions import IntersectDataHandler, IntersectMimeType
|
|
33
37
|
from .exceptions import IntersectCapabilityError
|
|
34
38
|
from .schema import get_schema_from_capability_implementations
|
|
35
39
|
from .service import IntersectService
|
|
@@ -47,7 +51,7 @@ if TYPE_CHECKING:
|
|
|
47
51
|
IntersectDirectMessageParams,
|
|
48
52
|
IntersectEventMessageParams,
|
|
49
53
|
)
|
|
50
|
-
from .version import __version__
|
|
54
|
+
from .version import __version__
|
|
51
55
|
|
|
52
56
|
__all__ = (
|
|
53
57
|
'INTERSECT_CLIENT_EVENT_CALLBACK_TYPE',
|
|
@@ -76,50 +80,78 @@ __all__ = (
|
|
|
76
80
|
'default_intersect_lifecycle_loop',
|
|
77
81
|
'get_schema_from_capability_implementations',
|
|
78
82
|
'intersect_message',
|
|
83
|
+
'intersect_sdk_version_info',
|
|
84
|
+
'intersect_sdk_version_string',
|
|
79
85
|
'intersect_status',
|
|
80
|
-
'version_info',
|
|
81
|
-
'version_string',
|
|
82
86
|
)
|
|
83
87
|
|
|
84
88
|
# PEP 562 stuff: do lazy imports for people who just want to import from the top-level module
|
|
85
|
-
|
|
89
|
+
# [0] = package, [1] = path to module within package
|
|
86
90
|
__lazy_imports = {
|
|
87
|
-
|
|
88
|
-
'
|
|
89
|
-
'
|
|
90
|
-
|
|
91
|
-
'
|
|
92
|
-
'
|
|
93
|
-
'
|
|
94
|
-
'
|
|
95
|
-
'
|
|
96
|
-
|
|
97
|
-
'
|
|
98
|
-
'
|
|
99
|
-
|
|
100
|
-
'
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
'
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
'
|
|
109
|
-
'
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
'
|
|
114
|
-
|
|
115
|
-
|
|
91
|
+
# COMMON: core types
|
|
92
|
+
'IntersectDataHandler': ('intersect_sdk_common', '.'),
|
|
93
|
+
'IntersectMimeType': ('intersect_sdk_common', '.'),
|
|
94
|
+
# COMMON: config types
|
|
95
|
+
'ControlPlaneConfig': ('intersect_sdk_common', '.'),
|
|
96
|
+
'ControlProvider': ('intersect_sdk_common', '.'),
|
|
97
|
+
'DataStoreConfig': ('intersect_sdk_common', '.'),
|
|
98
|
+
'DataStoreConfigMap': ('intersect_sdk_common', '.'),
|
|
99
|
+
'HierarchyConfig': ('intersect_sdk_common', '.'),
|
|
100
|
+
# COMMON: version
|
|
101
|
+
'intersect_sdk_version_info': ('intersect_sdk_common', '.'),
|
|
102
|
+
'intersect_sdk_version_string': ('intersect_sdk_common', '.'),
|
|
103
|
+
# imports not in common
|
|
104
|
+
'INTERSECT_CLIENT_EVENT_CALLBACK_TYPE': (
|
|
105
|
+
__spec__.parent,
|
|
106
|
+
'.client_callback_definitions',
|
|
107
|
+
),
|
|
108
|
+
'INTERSECT_CLIENT_RESPONSE_CALLBACK_TYPE': (
|
|
109
|
+
__spec__.parent,
|
|
110
|
+
'.client_callback_definitions',
|
|
111
|
+
),
|
|
112
|
+
'INTERSECT_JSON_VALUE': (__spec__.parent, '.shared_callback_definitions'),
|
|
113
|
+
'INTERSECT_RESPONSE_VALUE': (
|
|
114
|
+
__spec__.parent,
|
|
115
|
+
'.shared_callback_definitions',
|
|
116
|
+
),
|
|
117
|
+
'INTERSECT_SERVICE_RESPONSE_CALLBACK_TYPE': (
|
|
118
|
+
__spec__.parent,
|
|
119
|
+
'.service_callback_definitions',
|
|
120
|
+
),
|
|
121
|
+
'IntersectBaseCapabilityImplementation': (
|
|
122
|
+
__spec__.parent,
|
|
123
|
+
'.capability.base',
|
|
124
|
+
),
|
|
125
|
+
'IntersectCapabilityError': (__spec__.parent, '.exceptions'),
|
|
126
|
+
'IntersectClient': (__spec__.parent, '.client'),
|
|
127
|
+
'IntersectClientCallback': (
|
|
128
|
+
__spec__.parent,
|
|
129
|
+
'.client_callback_definitions',
|
|
130
|
+
),
|
|
131
|
+
'IntersectClientConfig': (__spec__.parent, '.config.client'),
|
|
132
|
+
'IntersectDirectMessageParams': (
|
|
133
|
+
__spec__.parent,
|
|
134
|
+
'.shared_callback_definitions',
|
|
135
|
+
),
|
|
136
|
+
'IntersectEventDefinition': (__spec__.parent, '.service_definitions'),
|
|
137
|
+
'IntersectEventMessageParams': (
|
|
138
|
+
__spec__.parent,
|
|
139
|
+
'.shared_callback_definitions',
|
|
140
|
+
),
|
|
141
|
+
'IntersectService': (__spec__.parent, '.service'),
|
|
142
|
+
'IntersectServiceConfig': (__spec__.parent, '.config.service'),
|
|
143
|
+
'__version__': (__spec__.parent, '.version'),
|
|
144
|
+
'default_intersect_lifecycle_loop': (__spec__.parent, '.app_lifecycle'),
|
|
145
|
+
'get_schema_from_capability_implementations': (__spec__.parent, '.schema'),
|
|
146
|
+
'intersect_message': (__spec__.parent, '.service_definitions'),
|
|
147
|
+
'intersect_status': (__spec__.parent, '.service_definitions'),
|
|
116
148
|
}
|
|
117
149
|
|
|
118
150
|
|
|
119
151
|
def __getattr__(attr_name: str) -> object:
|
|
120
152
|
attr_module = __lazy_imports.get(attr_name)
|
|
121
153
|
if attr_module:
|
|
122
|
-
module = import_module(attr_module, package=
|
|
154
|
+
module = import_module(attr_module[1], package=attr_module[0])
|
|
123
155
|
return getattr(module, attr_name)
|
|
124
156
|
|
|
125
157
|
msg = f'module {__name__!r} has no attribute {attr_name!r}'
|
|
@@ -5,8 +5,9 @@ from typing import TYPE_CHECKING, Any, Protocol
|
|
|
5
5
|
if TYPE_CHECKING:
|
|
6
6
|
from uuid import UUID
|
|
7
7
|
|
|
8
|
+
from intersect_sdk_common import HierarchyConfig
|
|
9
|
+
|
|
8
10
|
from ..client_callback_definitions import INTERSECT_CLIENT_EVENT_CALLBACK_TYPE
|
|
9
|
-
from ..config.shared import HierarchyConfig
|
|
10
11
|
from ..service_callback_definitions import (
|
|
11
12
|
INTERSECT_SERVICE_RESPONSE_CALLBACK_TYPE,
|
|
12
13
|
)
|
{intersect_sdk-0.9.0 → intersect_sdk-0.9.2}/src/intersect_sdk/_internal/pydantic_schema_generator.py
RENAMED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
See: https://docs.pydantic.dev/latest/api/json_schema/#pydantic.json_schema.GenerateJsonSchema
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
import collections
|
|
6
7
|
from typing import (
|
|
7
8
|
Any,
|
|
8
9
|
)
|
|
@@ -10,14 +11,23 @@ from typing import (
|
|
|
10
11
|
from jsonschema import Draft202012Validator as SchemaValidator
|
|
11
12
|
from jsonschema import ValidationError as SchemaValidationError
|
|
12
13
|
from jsonschema.validators import validator_for
|
|
13
|
-
from pydantic import
|
|
14
|
+
from pydantic import (
|
|
15
|
+
PydanticInvalidForJsonSchema,
|
|
16
|
+
PydanticSchemaGenerationError,
|
|
17
|
+
TypeAdapter,
|
|
18
|
+
)
|
|
14
19
|
from pydantic.json_schema import (
|
|
15
20
|
GenerateJsonSchema,
|
|
16
21
|
JsonSchemaMode,
|
|
17
22
|
JsonSchemaValue,
|
|
18
23
|
)
|
|
19
24
|
from pydantic.type_adapter import _type_has_config
|
|
20
|
-
from pydantic_core import
|
|
25
|
+
from pydantic_core import (
|
|
26
|
+
CoreSchema,
|
|
27
|
+
PydanticSerializationError,
|
|
28
|
+
core_schema,
|
|
29
|
+
to_jsonable_python,
|
|
30
|
+
)
|
|
21
31
|
|
|
22
32
|
|
|
23
33
|
# build nested dictionary from list of keys. i.e. if keys = ['one', 'two', 'three']
|
|
@@ -73,7 +83,8 @@ def validate_schema(json_schema: Any) -> list[str]:
|
|
|
73
83
|
# custom impl. of check_schema() , gather all errors instead of throwing on first error
|
|
74
84
|
validator_cls = validator_for(SchemaValidator.META_SCHEMA, default=SchemaValidator)
|
|
75
85
|
metavalidator: SchemaValidator = validator_cls(
|
|
76
|
-
SchemaValidator.META_SCHEMA,
|
|
86
|
+
SchemaValidator.META_SCHEMA,
|
|
87
|
+
format_checker=SchemaValidator.FORMAT_CHECKER,
|
|
77
88
|
)
|
|
78
89
|
return [
|
|
79
90
|
f'{error.json_path} : {error.message}' for error in metavalidator.iter_errors(json_schema)
|
|
@@ -120,7 +131,10 @@ class GenerateTypedJsonSchema(GenerateJsonSchema):
|
|
|
120
131
|
ref_parts = self.ref_template.split('/')[1:-1]
|
|
121
132
|
defs_schema = build_nested_dict(ref_parts, defs)
|
|
122
133
|
|
|
123
|
-
for
|
|
134
|
+
for (
|
|
135
|
+
default,
|
|
136
|
+
inner_schema,
|
|
137
|
+
) in self.intersect_sdk_postgeneration_defaults:
|
|
124
138
|
final_schema = {**defs_schema, **inner_schema}
|
|
125
139
|
try:
|
|
126
140
|
validate_against_schema(final_schema, default)
|
|
@@ -146,7 +160,8 @@ class GenerateTypedJsonSchema(GenerateJsonSchema):
|
|
|
146
160
|
The generated JSON schema.
|
|
147
161
|
"""
|
|
148
162
|
return self.handle_invalid_for_json_schema(
|
|
149
|
-
schema,
|
|
163
|
+
schema,
|
|
164
|
+
'Any or object : dynamic typing is not allowed for INTERSECT schemas',
|
|
150
165
|
)
|
|
151
166
|
|
|
152
167
|
def is_subclass_schema(self, schema: core_schema.IsSubclassSchema) -> JsonSchemaValue:
|
|
@@ -249,12 +264,14 @@ class GenerateTypedJsonSchema(GenerateJsonSchema):
|
|
|
249
264
|
"""
|
|
250
265
|
if not schema.get('items_schema'):
|
|
251
266
|
return self.handle_invalid_for_json_schema(
|
|
252
|
-
schema,
|
|
267
|
+
schema,
|
|
268
|
+
'generator yield subtyping (first argument) may not be dynamic in INTERSECT',
|
|
253
269
|
)
|
|
254
270
|
json_schema = super().generator_schema(schema)
|
|
255
271
|
if not json_schema.get('items'):
|
|
256
272
|
return self.handle_invalid_for_json_schema(
|
|
257
|
-
schema,
|
|
273
|
+
schema,
|
|
274
|
+
'generator yield subtyping (first argument) may not be dynamic in INTERSECT',
|
|
258
275
|
)
|
|
259
276
|
return json_schema
|
|
260
277
|
|
|
@@ -281,7 +298,8 @@ class GenerateTypedJsonSchema(GenerateJsonSchema):
|
|
|
281
298
|
)
|
|
282
299
|
if 'values_schema' not in schema:
|
|
283
300
|
return self.handle_invalid_for_json_schema(
|
|
284
|
-
schema,
|
|
301
|
+
schema,
|
|
302
|
+
'dict or mapping: value type cannot be Any/object for INTERSECT',
|
|
285
303
|
)
|
|
286
304
|
keys_schema = self.generate_inner(schema['keys_schema']).copy()
|
|
287
305
|
values_schema = self.generate_inner(schema['values_schema']).copy()
|
|
@@ -343,6 +361,19 @@ class GenerateTypedJsonSchema(GenerateJsonSchema):
|
|
|
343
361
|
return json_schema
|
|
344
362
|
default = schema['default']
|
|
345
363
|
|
|
364
|
+
# Sort set/frozenset defaults to ensure deterministic JSON schema generation
|
|
365
|
+
# We only sort if len > 1 because sets of size 0 or 1 are already deterministic
|
|
366
|
+
if isinstance(default, collections.abc.Set) and len(default) > 1:
|
|
367
|
+
try:
|
|
368
|
+
default = sorted(default)
|
|
369
|
+
except TypeError:
|
|
370
|
+
# If items aren't comparable (e.g. mixed types), we can't sort them.
|
|
371
|
+
# Unlike Pydantic, we will actually raise an error here, as we want to force deterministic schema generation
|
|
372
|
+
err_msg = (
|
|
373
|
+
f'Do not use "{default}" as a default value: sets must contain the same types'
|
|
374
|
+
)
|
|
375
|
+
raise PydanticInvalidForJsonSchema(err_msg) # noqa: B904 (TypeError provides indirection)
|
|
376
|
+
|
|
346
377
|
try:
|
|
347
378
|
encoded_default = self.encode_default(default)
|
|
348
379
|
except PydanticSerializationError:
|
|
@@ -352,9 +383,9 @@ class GenerateTypedJsonSchema(GenerateJsonSchema):
|
|
|
352
383
|
f"Default value '{default}' is not JSON serializable; use pydantic.Field's 'default_factory' argument for this.",
|
|
353
384
|
)
|
|
354
385
|
|
|
355
|
-
if
|
|
356
|
-
|
|
357
|
-
|
|
386
|
+
# check if the schema has $ref in it directly, or if it has a boolean schema composition keyword
|
|
387
|
+
# if it does, we must validate this during $ref construction
|
|
388
|
+
if '$ref' in json_schema or 'oneOf' in json_schema or 'anyOf' in json_schema:
|
|
358
389
|
# IMPORTANT!!! You must send the "json_schema" object itself, it will be modified later internally by Pydantic
|
|
359
390
|
self.intersect_sdk_postgeneration_defaults.append((encoded_default, json_schema))
|
|
360
391
|
# Since reference schemas do not support child keys, we wrap the reference schema in a single-case allOf:
|
|
@@ -479,7 +510,9 @@ class GenerateTypedJsonSchema(GenerateJsonSchema):
|
|
|
479
510
|
return super().kw_arguments_schema(arguments, var_kwargs_schema)
|
|
480
511
|
|
|
481
512
|
def p_arguments_schema(
|
|
482
|
-
self,
|
|
513
|
+
self,
|
|
514
|
+
arguments: list[core_schema.ArgumentsParameter],
|
|
515
|
+
var_args_schema: CoreSchema | None,
|
|
483
516
|
) -> JsonSchemaValue:
|
|
484
517
|
"""Generates a JSON schema that matches a schema that defines a function's positional arguments.
|
|
485
518
|
|
|
@@ -14,12 +14,18 @@ from typing import (
|
|
|
14
14
|
get_origin,
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
+
from intersect_sdk_common import intersect_sdk_version_string
|
|
18
|
+
from intersect_sdk_common.constants import CAPABILITY_REGEX
|
|
19
|
+
from intersect_sdk_common.control_plane.messages.event import (
|
|
20
|
+
EventMessageHeaders,
|
|
21
|
+
)
|
|
22
|
+
from intersect_sdk_common.control_plane.messages.userspace import (
|
|
23
|
+
UserspaceMessageHeaders,
|
|
24
|
+
)
|
|
17
25
|
from pydantic import Field, PydanticUserError, TypeAdapter
|
|
18
26
|
from typing_extensions import TypeAliasType
|
|
19
27
|
|
|
20
|
-
from ..constants import CAPABILITY_REGEX
|
|
21
28
|
from ..service_definitions import IntersectEventDefinition
|
|
22
|
-
from ..version import version_string
|
|
23
29
|
from .constants import (
|
|
24
30
|
BASE_RESPONSE_ATTR,
|
|
25
31
|
BASE_STATUS_ATTR,
|
|
@@ -32,18 +38,15 @@ from .constants import (
|
|
|
32
38
|
from .event_metadata import EventMetadata, definition_metadata_differences
|
|
33
39
|
from .function_metadata import FunctionMetadata
|
|
34
40
|
from .logger import logger
|
|
35
|
-
from .messages.event import EventMessageHeaders
|
|
36
|
-
from .messages.userspace import UserspaceMessageHeaders
|
|
37
41
|
from .pydantic_schema_generator import GenerateTypedJsonSchema
|
|
38
42
|
from .status_metadata import StatusMetadata
|
|
39
43
|
from .utils import die
|
|
40
44
|
|
|
41
45
|
if TYPE_CHECKING:
|
|
46
|
+
from intersect_sdk_common import HierarchyConfig, IntersectDataHandler
|
|
42
47
|
from pydantic.json_schema import JsonSchemaMode
|
|
43
48
|
|
|
44
49
|
from ..capability.base import IntersectBaseCapabilityImplementation
|
|
45
|
-
from ..config.shared import HierarchyConfig
|
|
46
|
-
from ..core_definitions import IntersectDataHandler
|
|
47
50
|
|
|
48
51
|
ASYNCAPI_VERSION = '2.6.0'
|
|
49
52
|
|
|
@@ -619,7 +622,7 @@ def get_schema_and_functions_from_capability_implementations(
|
|
|
619
622
|
or not re.fullmatch(CAPABILITY_REGEX, cap_name)
|
|
620
623
|
):
|
|
621
624
|
die(
|
|
622
|
-
f'Invalid intersect_sdk_capability_name on capability {capability_type.__name__} - must be a non-empty string with only alphanumeric characters and
|
|
625
|
+
f'Invalid intersect_sdk_capability_name on capability {capability_type.__name__} - must be a non-empty string with only alphanumeric characters and underscores (you must explicitly set this, and do so on the class and not an instance).'
|
|
623
626
|
)
|
|
624
627
|
if cap_name in capability_schemas:
|
|
625
628
|
die(
|
|
@@ -659,7 +662,7 @@ def get_schema_and_functions_from_capability_implementations(
|
|
|
659
662
|
|
|
660
663
|
asyncapi_spec = {
|
|
661
664
|
'asyncapi': ASYNCAPI_VERSION,
|
|
662
|
-
'x-intersect-version':
|
|
665
|
+
'x-intersect-version': intersect_sdk_version_string,
|
|
663
666
|
'info': {
|
|
664
667
|
'title': service_name.hierarchy_string('.'),
|
|
665
668
|
'description': 'INTERSECT schema',
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from hashlib import sha384
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_service_queue_name(routing_key: str) -> str:
|
|
5
|
+
"""Generate a valid queue name from the routing key.
|
|
6
|
+
|
|
7
|
+
We want to always be able to generate the same queue name from the routing key every time,
|
|
8
|
+
so we don't use UUIDs or want the broker to generate a key name.
|
|
9
|
+
|
|
10
|
+
We must also keep the length under 128 characters.
|
|
11
|
+
|
|
12
|
+
See https://www.rabbitmq.com/docs/queues#names for a complete reference.
|
|
13
|
+
"""
|
|
14
|
+
return sha384(routing_key.encode()).hexdigest()
|