intersect-sdk-common 0.9.4__tar.gz → 0.9.6__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_common-0.9.4 → intersect_sdk_common-0.9.6}/PKG-INFO +1 -1
- intersect_sdk_common-0.9.6/pyproject.toml +188 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/__init__.py +13 -2
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/control_plane_manager.py +12 -3
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/topic_handler.py +7 -3
- intersect_sdk_common-0.9.6/src/intersect_sdk_common/utils/version_resolver.py +70 -0
- intersect_sdk_common-0.9.4/pyproject.toml +0 -185
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/README.md +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/config.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/constants.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/__init__.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/brokers/__init__.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/brokers/amqp_client.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/brokers/broker_client.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/brokers/mqtt_client.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/custom_binary_protocol.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/definitions.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/messages/__init__.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/messages/event.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/messages/lifecycle.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/control_plane/messages/userspace.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/core_definitions.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/data_plane/__init__.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/data_plane/data_plane_manager.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/data_plane/minio_utils.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/exceptions.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/logger.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/py.typed +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/utils/__init__.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/utils/multi_flag_thread_event.py +0 -0
- {intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: intersect-sdk-common
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.6
|
|
4
4
|
Summary: Python SDK to interact with INTERSECT
|
|
5
5
|
Keywords: intersect
|
|
6
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
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "intersect-sdk-common"
|
|
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
|
+
readme = "README.md"
|
|
18
|
+
license = { text = "BSD-3-Clause" }
|
|
19
|
+
requires-python = ">=3.10,<4.0"
|
|
20
|
+
keywords = ["intersect"]
|
|
21
|
+
version = "0.9.6"
|
|
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
|
+
"paho-mqtt>=2.1.0,<3.0.0",
|
|
32
|
+
"pika>=1.3.2,<2.0.0",
|
|
33
|
+
"minio>=7.2.3",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[dependency-groups]
|
|
37
|
+
dev = [
|
|
38
|
+
"pre-commit>=3.3.1",
|
|
39
|
+
"ruff==0.12.7",
|
|
40
|
+
"mypy>=1.10.0",
|
|
41
|
+
"codespell>=2.3.0",
|
|
42
|
+
"pytest>=7.3.2",
|
|
43
|
+
"pytest-cov>=4.1.0",
|
|
44
|
+
"httpretty>=1.1.4",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[build-system]
|
|
48
|
+
requires = ["uv_build>=0.10.2,<0.11.0"]
|
|
49
|
+
build-backend = "uv_build"
|
|
50
|
+
|
|
51
|
+
[tool.ruff]
|
|
52
|
+
line-length = 100
|
|
53
|
+
format = { quote-style = 'single' }
|
|
54
|
+
|
|
55
|
+
[tool.ruff.lint]
|
|
56
|
+
isort = { known-first-party = ['src'] }
|
|
57
|
+
pydocstyle = { convention = 'google' }
|
|
58
|
+
flake8-quotes = { inline-quotes = 'single', multiline-quotes = 'double' }
|
|
59
|
+
mccabe = { max-complexity = 20 }
|
|
60
|
+
pylint = { max-args = 10, max-branches = 20, max-returns = 15, max-statements = 75 }
|
|
61
|
+
# pyflakes and the relevant pycodestyle rules are already configured
|
|
62
|
+
extend-select = [
|
|
63
|
+
'C90', # mccabe complexity
|
|
64
|
+
'I', # isort
|
|
65
|
+
'N', # pep8-naming
|
|
66
|
+
'D', # pydocstyle
|
|
67
|
+
'UP', # pyupgrade
|
|
68
|
+
'YTT', # flake8-2020
|
|
69
|
+
'ANN', # flake8-annotations
|
|
70
|
+
'ASYNC', # flake8-async
|
|
71
|
+
'S', # flake8-bandit
|
|
72
|
+
'BLE', # flake8-blind-except
|
|
73
|
+
'B', # flake8-bugbear
|
|
74
|
+
'A', # flake8-builtins
|
|
75
|
+
'COM', # flake8-commas
|
|
76
|
+
'C4', # flake8-comprehensions
|
|
77
|
+
'DTZ', # flake8-datetimez
|
|
78
|
+
'T10', # flake8-debugger
|
|
79
|
+
'EM', # flake8-error-message
|
|
80
|
+
'FA', # flake8-future-annotations
|
|
81
|
+
'ISC', # flake8-implicit-string-concat
|
|
82
|
+
'ICN', # flake8-import-conventions
|
|
83
|
+
'G', # flake8-logging-format
|
|
84
|
+
'INP', # flake8-no-pep420
|
|
85
|
+
'PIE', # flake8-PIE
|
|
86
|
+
'T20', # flake8-T20
|
|
87
|
+
'PYI', # flake8-pyi
|
|
88
|
+
'PT', # flake8-pytest-style
|
|
89
|
+
'Q', # flake8-quotes
|
|
90
|
+
'RSE', # flake8-raise
|
|
91
|
+
'RET', # flake8-return
|
|
92
|
+
'SLF', # flake8-self
|
|
93
|
+
'SLOT', # flake8-slots
|
|
94
|
+
'SIM', # flake8-simplify
|
|
95
|
+
'TC', # flake8-type-checking
|
|
96
|
+
'ARG', # flake8-unused-arguments
|
|
97
|
+
'PTH', # flake8-use-pathlib
|
|
98
|
+
'PGH', # pygrep-hooks
|
|
99
|
+
'PL', # pylint
|
|
100
|
+
'TRY', # tryceratops
|
|
101
|
+
'FLY', # flynt
|
|
102
|
+
'RUF', # RUFF additional rules
|
|
103
|
+
'INT', # flake8-gettext
|
|
104
|
+
]
|
|
105
|
+
# 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.
|
|
106
|
+
ignore = [
|
|
107
|
+
'COM812', # formatter, handled by Ruff format
|
|
108
|
+
'ISC001', # formatter, handled by Ruff format
|
|
109
|
+
'SIM105', # "with contextlib.suppress():" is slower than try-except-pass
|
|
110
|
+
'ANN401', # allow explicit "Any" typing, use with care
|
|
111
|
+
'PLR2004', # allow "magic numbers"
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
[tool.ruff.lint.flake8-type-checking]
|
|
115
|
+
runtime-evaluated-base-classes = ["pydantic.BaseModel"]
|
|
116
|
+
runtime-evaluated-decorators = [
|
|
117
|
+
"pydantic.dataclasses.dataclass",
|
|
118
|
+
"pydantic.validate_call",
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
[tool.ruff.lint.extend-per-file-ignores]
|
|
122
|
+
'__init__.py' = [
|
|
123
|
+
'F401', # __init__.py commonly has unused imports
|
|
124
|
+
'TC004', # do lazy imports when importing from the base module
|
|
125
|
+
]
|
|
126
|
+
'docs/*' = [
|
|
127
|
+
'D', # the documentation folder does not need documentation
|
|
128
|
+
'INP001', # docs are not a namespace package
|
|
129
|
+
]
|
|
130
|
+
'tests/*' = [
|
|
131
|
+
'S101', # allow assert statements in tests
|
|
132
|
+
'S106', # don't care about credentials in tests
|
|
133
|
+
'S311', # don't care about cryptographic security in tests
|
|
134
|
+
'SLF001', # allow private member access in tests
|
|
135
|
+
'ANN', # tests in general don't need types, unless they are runtime types.
|
|
136
|
+
'ARG', # allow unused parameters in tests
|
|
137
|
+
'D', # ignore documentation in tests
|
|
138
|
+
'RUF012', # permit "mutable" class attributes to not be annotated with typing.ClassVar (these shouldn't be mutated anyways...)
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
# see https://mypy.readthedocs.io/en/stable/config_file.html for a complete reference
|
|
142
|
+
[tool.mypy]
|
|
143
|
+
strict = true
|
|
144
|
+
ignore_missing_imports = true # don't require typing for library stubs if they don't exist
|
|
145
|
+
disallow_untyped_decorators = false # this is needed for library decorator compatibility, i.e. "retrying"
|
|
146
|
+
plugins = ["pydantic.mypy"]
|
|
147
|
+
|
|
148
|
+
[tool.pydantic-mypy]
|
|
149
|
+
init_forbid_extra = true
|
|
150
|
+
init_typed = true
|
|
151
|
+
warn_required_dynamic_aliases = true
|
|
152
|
+
warn_untyped_fields = true
|
|
153
|
+
|
|
154
|
+
[tool.pytest.ini_options]
|
|
155
|
+
log_cli = true
|
|
156
|
+
addopts = "-ra"
|
|
157
|
+
|
|
158
|
+
[tool.coverage.report]
|
|
159
|
+
omit = [
|
|
160
|
+
'*__init__*', # __init__ files should just re-export other classes and functions
|
|
161
|
+
]
|
|
162
|
+
exclude_also = [
|
|
163
|
+
'pragma: no-cover', # standard
|
|
164
|
+
'if (typing\\.)?TYPE_CHECKING:', # type checking blocks are not executed in coverage, but we don't care
|
|
165
|
+
'@(abc\\.)?abstractmethod', # don't try to cover abstract methods
|
|
166
|
+
"class .*\\bProtocol\\):", # don't cover protocol classes (similar to abstract classes)
|
|
167
|
+
'raise NotImplementedError', # it's not implemented so shouldn't be covered
|
|
168
|
+
'except.* ImportError', # these are usually used to throw a "friendlier" error and are not really worth testing
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
#[project.scripts]
|
|
173
|
+
#test-all = "pytest tests/ --cov=src/intersect_sdk_common/ --cov-fail-under=80 --cov-report=html:reports/htmlcov/ --cov-report=xml:reports/coverage_report.xml --junitxml=reports/junit.xml"
|
|
174
|
+
#test-all-debug = "pytest tests/ --cov=src/intersect_sdk_common/ --cov-fail-under=80 --cov-report=html:reports/htmlcov/ --cov-report=xml:reports/coverage_report.xml --junitxml=reports/junit.xml -s"
|
|
175
|
+
#test-unit = "pytest tests/unit --cov=src/intersect_sdk_common/"
|
|
176
|
+
#test-e2e = "pytest tests/e2e --cov=src/intersect_sdk_common/"
|
|
177
|
+
#lint-docs = "sphinx-build -W --keep-going docs docs/_build"
|
|
178
|
+
#lint-format = "ruff format"
|
|
179
|
+
#lint-ruff = "ruff check --fix"
|
|
180
|
+
#lint-mypy = "mypy src/intersect_sdk_common/"
|
|
181
|
+
#lint-spelling = "codespell -w docs examples src tests *.md -S docs/_build"
|
|
182
|
+
|
|
183
|
+
[tool.codespell]
|
|
184
|
+
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
|
|
185
|
+
skip = '.git*,*.lock,.venv,.*cache/*,./docs/_build/*'
|
|
186
|
+
check-hidden = true
|
|
187
|
+
# ignore-regex = ''
|
|
188
|
+
# ignore-words-list = ''
|
{intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/__init__.py
RENAMED
|
@@ -21,8 +21,17 @@ if TYPE_CHECKING:
|
|
|
21
21
|
from .control_plane.definitions import MessageCallback
|
|
22
22
|
from .core_definitions import IntersectDataHandler, IntersectMimeType
|
|
23
23
|
from .data_plane.data_plane_manager import DataPlaneManager
|
|
24
|
-
from .exceptions import
|
|
25
|
-
|
|
24
|
+
from .exceptions import (
|
|
25
|
+
IntersectApplicationError,
|
|
26
|
+
IntersectError,
|
|
27
|
+
IntersectSetupError,
|
|
28
|
+
)
|
|
29
|
+
from .utils.version_resolver import resolve_user_version
|
|
30
|
+
from .version import (
|
|
31
|
+
__version__,
|
|
32
|
+
intersect_sdk_version_info,
|
|
33
|
+
intersect_sdk_version_string,
|
|
34
|
+
)
|
|
26
35
|
|
|
27
36
|
__all__ = (
|
|
28
37
|
'ControlPlaneConfig',
|
|
@@ -41,6 +50,7 @@ __all__ = (
|
|
|
41
50
|
'__version__',
|
|
42
51
|
'intersect_sdk_version_info',
|
|
43
52
|
'intersect_sdk_version_string',
|
|
53
|
+
'resolve_user_version',
|
|
44
54
|
)
|
|
45
55
|
|
|
46
56
|
# PEP 562 stuff: do lazy imports for people who just want to import from the top-level module
|
|
@@ -62,6 +72,7 @@ __lazy_imports = {
|
|
|
62
72
|
'__version__': '.version',
|
|
63
73
|
'intersect_sdk_version_info': '.version',
|
|
64
74
|
'intersect_sdk_version_string': '.version',
|
|
75
|
+
'resolve_user_version': '.utils.version_resolver',
|
|
65
76
|
}
|
|
66
77
|
|
|
67
78
|
|
|
@@ -10,14 +10,17 @@ from .brokers.broker_client import BrokerClient
|
|
|
10
10
|
from .definitions import MessageCallback
|
|
11
11
|
from .topic_handler import TopicHandler
|
|
12
12
|
|
|
13
|
-
_CHANNEL_REGEX = re.compile(r'^[a-zA-Z0-
|
|
13
|
+
_CHANNEL_REGEX = re.compile(r'^[a-zA-Z0-9_*/-]+[a-zA-Z0-9_*#/-]$')
|
|
14
14
|
"""Allow for these patterns:
|
|
15
15
|
|
|
16
16
|
- alphanumeric characters
|
|
17
17
|
- hyphens
|
|
18
|
+
- underscores
|
|
18
19
|
- `/` (topic separator; note that this is '.' on the broker)
|
|
19
20
|
- `*` (wildcard for exactly one word)
|
|
20
21
|
- `#` (wildcard for any number of words, but can ONLY appear at the end of the topic string, see section 4.7.1.2 at https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718107)
|
|
22
|
+
|
|
23
|
+
This should be permissive relative to other patterns. You must cover system/service/hierarchy regexes, capability regexes, and event name regexes.
|
|
21
24
|
"""
|
|
22
25
|
|
|
23
26
|
|
|
@@ -75,7 +78,11 @@ class ControlPlaneManager:
|
|
|
75
78
|
self._wildcards: dict[str, TopicHandler] = {}
|
|
76
79
|
|
|
77
80
|
def add_subscription_channel(
|
|
78
|
-
self,
|
|
81
|
+
self,
|
|
82
|
+
channel: str,
|
|
83
|
+
callbacks: set[MessageCallback],
|
|
84
|
+
persist: bool,
|
|
85
|
+
queue_name: str,
|
|
79
86
|
) -> None:
|
|
80
87
|
"""Start listening for messages on a channel on all configured brokers.
|
|
81
88
|
|
|
@@ -167,7 +174,9 @@ class ControlPlaneManager:
|
|
|
167
174
|
return wildcard, topic_handler
|
|
168
175
|
return None
|
|
169
176
|
|
|
170
|
-
def get_all_subscription_channels(
|
|
177
|
+
def get_all_subscription_channels(
|
|
178
|
+
self,
|
|
179
|
+
) -> itertools.chain[tuple[str, TopicHandler]]:
|
|
171
180
|
"""Get all subscription channels, including wildcard channels.
|
|
172
181
|
|
|
173
182
|
This function is safe to call from the broker clients, as it does not mutate state.
|
|
@@ -23,7 +23,10 @@ class TopicHandler:
|
|
|
23
23
|
"""If this is a wildcard topic, the regex pattern to match incoming topics against (if no wildcards, this will be None)."""
|
|
24
24
|
|
|
25
25
|
def __init__(
|
|
26
|
-
self,
|
|
26
|
+
self,
|
|
27
|
+
topic_persist: bool,
|
|
28
|
+
queue_name: str,
|
|
29
|
+
regex_pattern: str | None = None,
|
|
27
30
|
) -> None:
|
|
28
31
|
"""Initialize a TopicHandler instance.
|
|
29
32
|
|
|
@@ -37,14 +40,15 @@ class TopicHandler:
|
|
|
37
40
|
self.queue_name = queue_name
|
|
38
41
|
|
|
39
42
|
if regex_pattern:
|
|
43
|
+
# the generated regex must be permissive and allow any non-special characters _CHANNEL_REGEX (ControlPlaneManager) allows
|
|
40
44
|
regex_builder = ['^']
|
|
41
45
|
for char in regex_pattern:
|
|
42
46
|
if char == '*':
|
|
43
47
|
# match a single word (do not include the separator)
|
|
44
|
-
regex_builder.append('[a-zA-Z0-
|
|
48
|
+
regex_builder.append('[a-zA-Z0-9_-]+')
|
|
45
49
|
elif char == '#':
|
|
46
50
|
# match any sequence of 0 or more words (make sure to allow for the separator)
|
|
47
|
-
regex_builder.append('[a-zA-Z0-9
|
|
51
|
+
regex_builder.append('[a-zA-Z0-9/_-]*')
|
|
48
52
|
elif char == '/':
|
|
49
53
|
# in-memory topics use '/' as the separator, it is the protocol handler's responsibility to convert topics to use '/' as the separator
|
|
50
54
|
regex_builder.append('/')
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Handles version resolution via semantic versioning logic."""
|
|
2
|
+
|
|
3
|
+
from .. import (
|
|
4
|
+
IntersectDataHandler,
|
|
5
|
+
intersect_sdk_version_info,
|
|
6
|
+
intersect_sdk_version_string,
|
|
7
|
+
)
|
|
8
|
+
from ..logger import logger
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _resolve_user_version(
|
|
12
|
+
their_version: str,
|
|
13
|
+
their_source: str,
|
|
14
|
+
their_data_handler: IntersectDataHandler,
|
|
15
|
+
our_version: str,
|
|
16
|
+
our_version_info: tuple[int, int, int],
|
|
17
|
+
) -> bool:
|
|
18
|
+
"""Function which handles version resolution information.
|
|
19
|
+
|
|
20
|
+
Separated into private function for testing purposes
|
|
21
|
+
"""
|
|
22
|
+
their_version_info = [int(x) for x in their_version.split('.')]
|
|
23
|
+
|
|
24
|
+
# logging rules: log "error" if it's definitely our fault, "warning" if it _might_ be our fault
|
|
25
|
+
if len(their_version_info) < 3:
|
|
26
|
+
logger.warning(f'Invalid version {their_version} received')
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
if their_version_info[0] != our_version_info[0]:
|
|
30
|
+
logger.warning(
|
|
31
|
+
f'Problem with source {their_source}: Major version incompatibility between our SDK version {our_version} and their SDK version {their_version}'
|
|
32
|
+
)
|
|
33
|
+
return False
|
|
34
|
+
if our_version_info[0] == 0 and our_version_info[1] != their_version_info[1]:
|
|
35
|
+
logger.warning(
|
|
36
|
+
f'Problem with source {their_source}: Pre-release minor version incompatibility between our SDK version {our_version} and their SDK version {their_version}'
|
|
37
|
+
)
|
|
38
|
+
return False
|
|
39
|
+
if their_data_handler.value not in [e.value for e in IntersectDataHandler]:
|
|
40
|
+
logger.error(
|
|
41
|
+
f'Problem with source {their_source}: This adapter cannot handle data handler with code "{their_data_handler}", please upgrade to the latest intersect-sdk version.'
|
|
42
|
+
)
|
|
43
|
+
return False
|
|
44
|
+
# NOTE: consider implementing a content-type check here as well
|
|
45
|
+
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def resolve_user_version(
|
|
50
|
+
their_version: str,
|
|
51
|
+
their_source: str,
|
|
52
|
+
their_data_handler: IntersectDataHandler,
|
|
53
|
+
) -> bool:
|
|
54
|
+
"""This function handles all version compatibilities between our SDK version and an incoming message's SDK version.
|
|
55
|
+
|
|
56
|
+
Params
|
|
57
|
+
their_version - version information from headers
|
|
58
|
+
their_source - source information from headers
|
|
59
|
+
their_data_handler - data handler information from headers
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
True if version resolution successful, false otherwise
|
|
63
|
+
"""
|
|
64
|
+
return _resolve_user_version(
|
|
65
|
+
their_version,
|
|
66
|
+
their_source,
|
|
67
|
+
their_data_handler,
|
|
68
|
+
our_version=intersect_sdk_version_string,
|
|
69
|
+
our_version_info=intersect_sdk_version_info,
|
|
70
|
+
)
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
[project]
|
|
2
|
-
name = "intersect-sdk-common"
|
|
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
|
-
readme = "README.md"
|
|
18
|
-
license = { text = "BSD-3-Clause" }
|
|
19
|
-
requires-python = ">=3.10,<4.0"
|
|
20
|
-
keywords = ["intersect"]
|
|
21
|
-
version = "0.9.4"
|
|
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
|
-
"paho-mqtt>=2.1.0,<3.0.0",
|
|
32
|
-
"pika>=1.3.2,<2.0.0",
|
|
33
|
-
"minio>=7.2.3",
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
[dependency-groups]
|
|
37
|
-
dev = [
|
|
38
|
-
"pre-commit>=3.3.1",
|
|
39
|
-
"ruff==0.12.7",
|
|
40
|
-
"mypy>=1.10.0",
|
|
41
|
-
"codespell>=2.3.0",
|
|
42
|
-
"pytest>=7.3.2",
|
|
43
|
-
"pytest-cov>=4.1.0",
|
|
44
|
-
"httpretty>=1.1.4",
|
|
45
|
-
]
|
|
46
|
-
|
|
47
|
-
[build-system]
|
|
48
|
-
requires = ["uv_build>=0.10.2,<0.11.0"]
|
|
49
|
-
build-backend = "uv_build"
|
|
50
|
-
|
|
51
|
-
[tool.ruff]
|
|
52
|
-
line-length = 100
|
|
53
|
-
format = { quote-style = 'single' }
|
|
54
|
-
|
|
55
|
-
[tool.ruff.lint]
|
|
56
|
-
isort = { known-first-party = ['src'] }
|
|
57
|
-
pydocstyle = { convention = 'google' }
|
|
58
|
-
flake8-quotes = { inline-quotes = 'single', multiline-quotes = 'double' }
|
|
59
|
-
mccabe = { max-complexity = 20 }
|
|
60
|
-
pylint = { max-args = 10, max-branches = 20, max-returns = 15, max-statements = 75 }
|
|
61
|
-
# pyflakes and the relevant pycodestyle rules are already configured
|
|
62
|
-
extend-select = [
|
|
63
|
-
'C90', # mccabe complexity
|
|
64
|
-
'I', # isort
|
|
65
|
-
'N', # pep8-naming
|
|
66
|
-
'D', # pydocstyle
|
|
67
|
-
'UP', # pyupgrade
|
|
68
|
-
'YTT', # flake8-2020
|
|
69
|
-
'ANN', # flake8-annotations
|
|
70
|
-
'ASYNC', # flake8-async
|
|
71
|
-
'S', # flake8-bandit
|
|
72
|
-
'BLE', # flake8-blind-except
|
|
73
|
-
'B', # flake8-bugbear
|
|
74
|
-
'A', # flake8-builtins
|
|
75
|
-
'COM', # flake8-commas
|
|
76
|
-
'C4', # flake8-comprehensions
|
|
77
|
-
'DTZ', # flake8-datetimez
|
|
78
|
-
'T10', # flake8-debugger
|
|
79
|
-
'EM', # flake8-error-message
|
|
80
|
-
'FA', # flake8-future-annotations
|
|
81
|
-
'ISC', # flake8-implicit-string-concat
|
|
82
|
-
'ICN', # flake8-import-conventions
|
|
83
|
-
'G', # flake8-logging-format
|
|
84
|
-
'INP', # flake8-no-pep420
|
|
85
|
-
'PIE', # flake8-PIE
|
|
86
|
-
'T20', # flake8-T20
|
|
87
|
-
'PYI', # flake8-pyi
|
|
88
|
-
'PT', # flake8-pytest-style
|
|
89
|
-
'Q', # flake8-quotes
|
|
90
|
-
'RSE', # flake8-raise
|
|
91
|
-
'RET', # flake8-return
|
|
92
|
-
'SLF', # flake8-self
|
|
93
|
-
'SLOT', # flake8-slots
|
|
94
|
-
'SIM', # flake8-simplify
|
|
95
|
-
'TC', # flake8-type-checking
|
|
96
|
-
'ARG', # flake8-unused-arguments
|
|
97
|
-
'PTH', # flake8-use-pathlib
|
|
98
|
-
'PGH', # pygrep-hooks
|
|
99
|
-
'PL', # pylint
|
|
100
|
-
'TRY', # tryceratops
|
|
101
|
-
'FLY', # flynt
|
|
102
|
-
'RUF', # RUFF additional rules
|
|
103
|
-
'INT', # flake8-gettext
|
|
104
|
-
]
|
|
105
|
-
# 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.
|
|
106
|
-
ignore = [
|
|
107
|
-
'COM812', # formatter, handled by Ruff format
|
|
108
|
-
'ISC001', # formatter, handled by Ruff format
|
|
109
|
-
'SIM105', # "with contextlib.suppress():" is slower than try-except-pass
|
|
110
|
-
'ANN401', # allow explicit "Any" typing, use with care
|
|
111
|
-
'PLR2004', # allow "magic numbers"
|
|
112
|
-
]
|
|
113
|
-
|
|
114
|
-
[tool.ruff.lint.flake8-type-checking]
|
|
115
|
-
runtime-evaluated-base-classes = ["pydantic.BaseModel"]
|
|
116
|
-
runtime-evaluated-decorators = ["pydantic.dataclasses.dataclass","pydantic.validate_call"]
|
|
117
|
-
|
|
118
|
-
[tool.ruff.lint.extend-per-file-ignores]
|
|
119
|
-
'__init__.py' = [
|
|
120
|
-
'F401', # __init__.py commonly has unused imports
|
|
121
|
-
'TC004', # do lazy imports when importing from the base module
|
|
122
|
-
]
|
|
123
|
-
'docs/*' = [
|
|
124
|
-
'D', # the documentation folder does not need documentation
|
|
125
|
-
'INP001', # docs are not a namespace package
|
|
126
|
-
]
|
|
127
|
-
'tests/*' = [
|
|
128
|
-
'S101', # allow assert statements in tests
|
|
129
|
-
'S106', # don't care about credentials in tests
|
|
130
|
-
'S311', # don't care about cryptographic security in tests
|
|
131
|
-
'SLF001', # allow private member access in tests
|
|
132
|
-
'ANN', # tests in general don't need types, unless they are runtime types.
|
|
133
|
-
'ARG', # allow unused parameters in tests
|
|
134
|
-
'D', # ignore documentation in tests
|
|
135
|
-
'RUF012', # permit "mutable" class attributes to not be annotated with typing.ClassVar (these shouldn't be mutated anyways...)
|
|
136
|
-
]
|
|
137
|
-
|
|
138
|
-
# see https://mypy.readthedocs.io/en/stable/config_file.html for a complete reference
|
|
139
|
-
[tool.mypy]
|
|
140
|
-
strict = true
|
|
141
|
-
ignore_missing_imports = true # don't require typing for library stubs if they don't exist
|
|
142
|
-
disallow_untyped_decorators = false # this is needed for library decorator compatibility, i.e. "retrying"
|
|
143
|
-
plugins = ["pydantic.mypy"]
|
|
144
|
-
|
|
145
|
-
[tool.pydantic-mypy]
|
|
146
|
-
init_forbid_extra = true
|
|
147
|
-
init_typed = true
|
|
148
|
-
warn_required_dynamic_aliases = true
|
|
149
|
-
warn_untyped_fields = true
|
|
150
|
-
|
|
151
|
-
[tool.pytest.ini_options]
|
|
152
|
-
log_cli = true
|
|
153
|
-
addopts = "-ra"
|
|
154
|
-
|
|
155
|
-
[tool.coverage.report]
|
|
156
|
-
omit = [
|
|
157
|
-
'*__init__*', # __init__ files should just re-export other classes and functions
|
|
158
|
-
]
|
|
159
|
-
exclude_also = [
|
|
160
|
-
'pragma: no-cover', # standard
|
|
161
|
-
'if (typing\\.)?TYPE_CHECKING:', # type checking blocks are not executed in coverage, but we don't care
|
|
162
|
-
'@(abc\\.)?abstractmethod', # don't try to cover abstract methods
|
|
163
|
-
"class .*\\bProtocol\\):", # don't cover protocol classes (similar to abstract classes)
|
|
164
|
-
'raise NotImplementedError', # it's not implemented so shouldn't be covered
|
|
165
|
-
'except.* ImportError', # these are usually used to throw a "friendlier" error and are not really worth testing
|
|
166
|
-
]
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
#[project.scripts]
|
|
170
|
-
#test-all = "pytest tests/ --cov=src/intersect_sdk_common/ --cov-fail-under=80 --cov-report=html:reports/htmlcov/ --cov-report=xml:reports/coverage_report.xml --junitxml=reports/junit.xml"
|
|
171
|
-
#test-all-debug = "pytest tests/ --cov=src/intersect_sdk_common/ --cov-fail-under=80 --cov-report=html:reports/htmlcov/ --cov-report=xml:reports/coverage_report.xml --junitxml=reports/junit.xml -s"
|
|
172
|
-
#test-unit = "pytest tests/unit --cov=src/intersect_sdk_common/"
|
|
173
|
-
#test-e2e = "pytest tests/e2e --cov=src/intersect_sdk_common/"
|
|
174
|
-
#lint-docs = "sphinx-build -W --keep-going docs docs/_build"
|
|
175
|
-
#lint-format = "ruff format"
|
|
176
|
-
#lint-ruff = "ruff check --fix"
|
|
177
|
-
#lint-mypy = "mypy src/intersect_sdk_common/"
|
|
178
|
-
#lint-spelling = "codespell -w docs examples src tests *.md -S docs/_build"
|
|
179
|
-
|
|
180
|
-
[tool.codespell]
|
|
181
|
-
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
|
|
182
|
-
skip = '.git*,*.lock,.venv,.*cache/*,./docs/_build/*'
|
|
183
|
-
check-hidden = true
|
|
184
|
-
# ignore-regex = ''
|
|
185
|
-
# ignore-words-list = ''
|
|
File without changes
|
{intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/config.py
RENAMED
|
File without changes
|
{intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/exceptions.py
RENAMED
|
File without changes
|
{intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/logger.py
RENAMED
|
File without changes
|
|
File without changes
|
{intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{intersect_sdk_common-0.9.4 → intersect_sdk_common-0.9.6}/src/intersect_sdk_common/version.py
RENAMED
|
File without changes
|