intersect-sdk-common 0.0.0a0__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.
Files changed (28) hide show
  1. intersect_sdk_common-0.0.0a0/PKG-INFO +52 -0
  2. intersect_sdk_common-0.0.0a0/README.md +32 -0
  3. intersect_sdk_common-0.0.0a0/pyproject.toml +183 -0
  4. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/__init__.py +72 -0
  5. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/config.py +168 -0
  6. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/constants.py +28 -0
  7. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/__init__.py +1 -0
  8. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/brokers/__init__.py +4 -0
  9. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/brokers/amqp_client.py +620 -0
  10. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/brokers/broker_client.py +81 -0
  11. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/brokers/mqtt_client.py +300 -0
  12. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/control_plane_manager.py +172 -0
  13. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/definitions.py +12 -0
  14. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/messages/__init__.py +6 -0
  15. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/messages/event.py +145 -0
  16. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/messages/lifecycle.py +112 -0
  17. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/messages/userspace.py +183 -0
  18. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/control_plane/topic_handler.py +31 -0
  19. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/core_definitions.py +47 -0
  20. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/data_plane/__init__.py +1 -0
  21. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/data_plane/data_plane_manager.py +109 -0
  22. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/data_plane/minio_utils.py +169 -0
  23. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/exceptions.py +19 -0
  24. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/logger.py +5 -0
  25. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/py.typed +0 -0
  26. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/utils/__init__.py +1 -0
  27. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/utils/multi_flag_thread_event.py +82 -0
  28. intersect_sdk_common-0.0.0a0/src/intersect_sdk_common/version.py +38 -0
@@ -0,0 +1,52 @@
1
+ Metadata-Version: 2.3
2
+ Name: intersect-sdk-common
3
+ Version: 0.0.0a0
4
+ Summary: Python SDK to interact with INTERSECT
5
+ Keywords: intersect
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>
8
+ License: BSD-3-Clause
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Requires-Dist: pydantic>=2.7.0
15
+ Requires-Dist: paho-mqtt>=2.1.0,<3.0.0
16
+ Requires-Dist: pika>=1.3.2,<2.0.0
17
+ Requires-Dist: minio>=7.2.3
18
+ Requires-Python: >=3.10, <4.0
19
+ Description-Content-Type: text/markdown
20
+
21
+ # INTERSECT common libraries
22
+
23
+ This library is meant to provide common definitions across all INTERSECT services, both domain science microservices and INTERSECT core services.
24
+
25
+ ## IMPORTANT - READ THIS SECTION
26
+
27
+ If you are developing a domain science application, do NOT import directly from this package. Use the [intersect-sdk](https://github.com/INTERSECT-SDK/python-sdk) package instead. You also don't need to import this package directly, the `intersect-sdk` package will automatically manage this version for you.
28
+
29
+ ## Version release policy
30
+
31
+ Note that this package does _not_ follow semantic versioning for everything, as this is meant to be an internal package used by both the INTERSECT SDK and INTERSECT core services; it ONLY follows semantic versioning for the internal message structure.
32
+
33
+ Prior to release 1.0.0, the policy is:
34
+
35
+ - MINOR VERSION CHANGE - if the message structure changes (relevant to end users and the ecosystem)
36
+ - PATCH VERSION CHANGE - any release, which may or may not be breaking (only relevant to the INTERSECT-SDK and INTERSECT core services)
37
+
38
+ After release 1.0.0, the policy is expected to be:
39
+
40
+ - MAJOR VERSION CHANGE - if the message structure changes (relevant to end users and the ecosystem)
41
+ - MINOR VERSION CHANGE - breaking API changes (this is only relevant to the INTERSECT-SDK and INTERSECT core services)
42
+ - PATCH VERSION CHANGE - backwards compatible changes
43
+
44
+ The INTERSECT-SDK MUST follow semantic versioning, and MUST update its semantic version if this package's semantic version is updated.
45
+
46
+ ## Developing
47
+
48
+ ```bash
49
+ uv venv .venv
50
+ source .venv/bin/activate
51
+ uv sync --locked --all-extras --all-groups
52
+ ```
@@ -0,0 +1,32 @@
1
+ # INTERSECT common libraries
2
+
3
+ This library is meant to provide common definitions across all INTERSECT services, both domain science microservices and INTERSECT core services.
4
+
5
+ ## IMPORTANT - READ THIS SECTION
6
+
7
+ If you are developing a domain science application, do NOT import directly from this package. Use the [intersect-sdk](https://github.com/INTERSECT-SDK/python-sdk) package instead. You also don't need to import this package directly, the `intersect-sdk` package will automatically manage this version for you.
8
+
9
+ ## Version release policy
10
+
11
+ Note that this package does _not_ follow semantic versioning for everything, as this is meant to be an internal package used by both the INTERSECT SDK and INTERSECT core services; it ONLY follows semantic versioning for the internal message structure.
12
+
13
+ Prior to release 1.0.0, the policy is:
14
+
15
+ - MINOR VERSION CHANGE - if the message structure changes (relevant to end users and the ecosystem)
16
+ - PATCH VERSION CHANGE - any release, which may or may not be breaking (only relevant to the INTERSECT-SDK and INTERSECT core services)
17
+
18
+ After release 1.0.0, the policy is expected to be:
19
+
20
+ - MAJOR VERSION CHANGE - if the message structure changes (relevant to end users and the ecosystem)
21
+ - MINOR VERSION CHANGE - breaking API changes (this is only relevant to the INTERSECT-SDK and INTERSECT core services)
22
+ - PATCH VERSION CHANGE - backwards compatible changes
23
+
24
+ The INTERSECT-SDK MUST follow semantic versioning, and MUST update its semantic version if this package's semantic version is updated.
25
+
26
+ ## Developing
27
+
28
+ ```bash
29
+ uv venv .venv
30
+ source .venv/bin/activate
31
+ uv sync --locked --all-extras --all-groups
32
+ ```
@@ -0,0 +1,183 @@
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.0.0alpha.0"
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
+ lint = [
38
+ "pre-commit>=3.3.1",
39
+ "ruff==0.12.7",
40
+ "mypy>=1.10.0",
41
+ "codespell>=2.3.0",
42
+ ]
43
+ test = ["pytest>=7.3.2", "pytest-cov>=4.1.0", "httpretty>=1.1.4"]
44
+
45
+ [build-system]
46
+ requires = ["uv_build>=0.10.2,<0.11.0"]
47
+ build-backend = "uv_build"
48
+
49
+ [tool.ruff]
50
+ line-length = 100
51
+ format = { quote-style = 'single' }
52
+
53
+ [tool.ruff.lint]
54
+ isort = { known-first-party = ['src'] }
55
+ pydocstyle = { convention = 'google' }
56
+ flake8-quotes = { inline-quotes = 'single', multiline-quotes = 'double' }
57
+ mccabe = { max-complexity = 20 }
58
+ pylint = { max-args = 10, max-branches = 20, max-returns = 15, max-statements = 75 }
59
+ # pyflakes and the relevant pycodestyle rules are already configured
60
+ extend-select = [
61
+ 'C90', # mccabe complexity
62
+ 'I', # isort
63
+ 'N', # pep8-naming
64
+ 'D', # pydocstyle
65
+ 'UP', # pyupgrade
66
+ 'YTT', # flake8-2020
67
+ 'ANN', # flake8-annotations
68
+ 'ASYNC', # flake8-async
69
+ 'S', # flake8-bandit
70
+ 'BLE', # flake8-blind-except
71
+ 'B', # flake8-bugbear
72
+ 'A', # flake8-builtins
73
+ 'COM', # flake8-commas
74
+ 'C4', # flake8-comprehensions
75
+ 'DTZ', # flake8-datetimez
76
+ 'T10', # flake8-debugger
77
+ 'EM', # flake8-error-message
78
+ 'FA', # flake8-future-annotations
79
+ 'ISC', # flake8-implicit-string-concat
80
+ 'ICN', # flake8-import-conventions
81
+ 'G', # flake8-logging-format
82
+ 'INP', # flake8-no-pep420
83
+ 'PIE', # flake8-PIE
84
+ 'T20', # flake8-T20
85
+ 'PYI', # flake8-pyi
86
+ 'PT', # flake8-pytest-style
87
+ 'Q', # flake8-quotes
88
+ 'RSE', # flake8-raise
89
+ 'RET', # flake8-return
90
+ 'SLF', # flake8-self
91
+ 'SLOT', # flake8-slots
92
+ 'SIM', # flake8-simplify
93
+ 'TC', # flake8-type-checking
94
+ 'ARG', # flake8-unused-arguments
95
+ 'PTH', # flake8-use-pathlib
96
+ 'PGH', # pygrep-hooks
97
+ 'PL', # pylint
98
+ 'TRY', # tryceratops
99
+ 'FLY', # flynt
100
+ 'RUF', # RUFF additional rules
101
+ 'INT', # flake8-gettext
102
+ ]
103
+ # 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.
104
+ ignore = [
105
+ 'COM812', # formatter, handled by Ruff format
106
+ 'ISC001', # formatter, handled by Ruff format
107
+ 'SIM105', # "with contextlib.suppress():" is slower than try-except-pass
108
+ 'ANN401', # allow explicit "Any" typing, use with care
109
+ 'PLR2004', # allow "magic numbers"
110
+ ]
111
+
112
+ [tool.ruff.lint.flake8-type-checking]
113
+ runtime-evaluated-base-classes = ["pydantic.BaseModel"]
114
+ runtime-evaluated-decorators = ["pydantic.dataclasses.dataclass","pydantic.validate_call"]
115
+
116
+ [tool.ruff.lint.extend-per-file-ignores]
117
+ '__init__.py' = [
118
+ 'F401', # __init__.py commonly has unused imports
119
+ 'TC004', # do lazy imports when importing from the base module
120
+ ]
121
+ 'docs/*' = [
122
+ 'D', # the documentation folder does not need documentation
123
+ 'INP001', # docs are not a namespace package
124
+ ]
125
+ 'tests/*' = [
126
+ 'S101', # allow assert statements in tests
127
+ 'S106', # don't care about credentials in tests
128
+ 'S311', # don't care about cryptographic security in tests
129
+ 'SLF001', # allow private member access in tests
130
+ 'ANN', # tests in general don't need types, unless they are runtime types.
131
+ 'ARG', # allow unused parameters in tests
132
+ 'D', # ignore documentation in tests
133
+ 'RUF012', # permit "mutable" class attributes to not be annotated with typing.ClassVar (these shouldn't be mutated anyways...)
134
+ ]
135
+
136
+ # see https://mypy.readthedocs.io/en/stable/config_file.html for a complete reference
137
+ [tool.mypy]
138
+ strict = true
139
+ ignore_missing_imports = true # don't require typing for library stubs if they don't exist
140
+ disallow_untyped_decorators = false # this is needed for library decorator compatibility, i.e. "retrying"
141
+ plugins = ["pydantic.mypy"]
142
+
143
+ [tool.pydantic-mypy]
144
+ init_forbid_extra = true
145
+ init_typed = true
146
+ warn_required_dynamic_aliases = true
147
+ warn_untyped_fields = true
148
+
149
+ [tool.pytest.ini_options]
150
+ log_cli = true
151
+ addopts = "-ra"
152
+
153
+ [tool.coverage.report]
154
+ omit = [
155
+ '*__init__*', # __init__ files should just re-export other classes and functions
156
+ ]
157
+ exclude_also = [
158
+ 'pragma: no-cover', # standard
159
+ 'if (typing\\.)?TYPE_CHECKING:', # type checking blocks are not executed in coverage, but we don't care
160
+ '@(abc\\.)?abstractmethod', # don't try to cover abstract methods
161
+ "class .*\\bProtocol\\):", # don't cover protocol classes (similar to abstract classes)
162
+ 'raise NotImplementedError', # it's not implemented so shouldn't be covered
163
+ 'except.* ImportError', # these are usually used to throw a "friendlier" error and are not really worth testing
164
+ ]
165
+
166
+
167
+ #[project.scripts]
168
+ #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"
169
+ #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"
170
+ #test-unit = "pytest tests/unit --cov=src/intersect_sdk_common/"
171
+ #test-e2e = "pytest tests/e2e --cov=src/intersect_sdk_common/"
172
+ #lint-docs = "sphinx-build -W --keep-going docs docs/_build"
173
+ #lint-format = "ruff format"
174
+ #lint-ruff = "ruff check --fix"
175
+ #lint-mypy = "mypy src/intersect_sdk_common/"
176
+ #lint-spelling = "codespell -w docs examples src tests *.md -S docs/_build"
177
+
178
+ [tool.codespell]
179
+ # Ref: https://github.com/codespell-project/codespell#using-a-config-file
180
+ skip = '.git*,*.lock,.venv,.*cache/*,./docs/_build/*'
181
+ check-hidden = true
182
+ # ignore-regex = ''
183
+ # ignore-words-list = ''
@@ -0,0 +1,72 @@
1
+ """Common definitions shared across ALL INTERSECT services, be they domain science microservices or INTERSECT core services.
2
+
3
+ You can use the base package as the public API, no need to import from submodules.
4
+
5
+ IMPORTANT: If you are building a scientific microservice, do NOT import from this package. Instead, import from intersect-sdk, which is the public-facing library intended for you. Relevant definitions from this package will be re-exported there.
6
+ """
7
+
8
+ from importlib import import_module
9
+ from typing import TYPE_CHECKING
10
+
11
+ # import everything eagerly for IDEs/LSPs
12
+ if TYPE_CHECKING:
13
+ from .config import (
14
+ ControlPlaneConfig,
15
+ ControlProvider,
16
+ DataStoreConfig,
17
+ DataStoreConfigMap,
18
+ HierarchyConfig,
19
+ )
20
+ from .control_plane.control_plane_manager import ControlPlaneManager
21
+ from .control_plane.definitions import MessageCallback
22
+ from .core_definitions import IntersectDataHandler, IntersectMimeType
23
+ from .data_plane.data_plane_manager import DataPlaneManager
24
+ from .version import __version__, intersect_sdk_version_info, intersect_sdk_version_string
25
+
26
+ __all__ = (
27
+ 'ControlPlaneConfig',
28
+ 'ControlPlaneManager',
29
+ 'ControlProvider',
30
+ 'DataPlaneManager',
31
+ 'DataStoreConfig',
32
+ 'DataStoreConfigMap',
33
+ 'HierarchyConfig',
34
+ 'IntersectDataHandler',
35
+ 'IntersectMimeType',
36
+ 'MessageCallback',
37
+ '__version__',
38
+ 'intersect_sdk_version_info',
39
+ 'intersect_sdk_version_string',
40
+ )
41
+
42
+ # PEP 562 stuff: do lazy imports for people who just want to import from the top-level module
43
+
44
+ __lazy_imports = {
45
+ 'ControlPlaneConfig': '.config',
46
+ 'ControlProvider': '.config',
47
+ 'DataStoreConfig': '.config',
48
+ 'DataStoreConfigMap': '.config',
49
+ 'HierarchyConfig': '.config',
50
+ 'ControlPlaneManager': '.control_plane.control_plane_manager',
51
+ 'MessageCallback': '.control_plane.definitions',
52
+ 'IntersectDataHandler': '.core_definitions',
53
+ 'IntersectMimeType': '.core_definitions',
54
+ 'DataPlaneManager': '.data_plane.data_plane_manager',
55
+ '__version__': '.version',
56
+ 'intersect_sdk_version_info': '.version',
57
+ 'intersect_sdk_version_string': '.version',
58
+ }
59
+
60
+
61
+ def __getattr__(attr_name: str) -> object:
62
+ attr_module = __lazy_imports.get(attr_name)
63
+ if attr_module:
64
+ module = import_module(attr_module, package=__spec__.parent)
65
+ return getattr(module, attr_name)
66
+
67
+ msg = f'module {__name__!r} has no attribute {attr_name!r}'
68
+ raise AttributeError(msg)
69
+
70
+
71
+ def __dir__() -> list[str]:
72
+ return list(__all__)
@@ -0,0 +1,168 @@
1
+ """Configuration types shared across both Clients and Services."""
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import Annotated, Literal
5
+
6
+ from pydantic import BaseModel, ConfigDict, Field, PositiveInt
7
+
8
+ from .core_definitions import IntersectDataHandler
9
+
10
+ HIERARCHY_REGEX = r'^[a-z]((?!--)[a-z0-9-]){2,62}$'
11
+ """
12
+ The hierarchy regex needs to be fairly restricted due to the number of different
13
+ systems we want to be compatible with. The rules:
14
+
15
+ - Only allow unreserved characters (alphanumeric and .-~_): https://datatracker.ietf.org/doc/html/rfc3986#section-2.3
16
+ - Require lowercase letters to avoid incompatibilities with case-insensitive systems.
17
+ - MinIO has been found to forbid _ and ~ characters
18
+ - MinIO requires an alphanumeric character at the start of the string
19
+ - No adjacent non-alphanumeric characters allowed
20
+ - Range should be from 3-63 characters
21
+
22
+ The following commit tracks several issues with MINIO: https://code.ornl.gov/intersect/additive-manufacturing/ros-intersect-adapter/-/commit/fa71b791be0ccf1a5884910b5be3b5239cf9896f
23
+ """
24
+
25
+ ControlProvider = Literal['mqtt5.0', 'amqp0.9.1']
26
+ """The type of broker we connect to."""
27
+
28
+
29
+ class HierarchyConfig(BaseModel):
30
+ """Configuration for registering this service in a system-of-system architecture."""
31
+
32
+ service: Annotated[str, Field(pattern=HIERARCHY_REGEX)]
33
+ """
34
+ The name of this application - should be unique within an INTERSECT system
35
+ """
36
+
37
+ subsystem: str | None = Field(default=None, pattern=HIERARCHY_REGEX)
38
+ """
39
+ An associated subsystem / service-grouping of the system (should be unique within an INTERSECT system)
40
+ """
41
+
42
+ system: Annotated[str, Field(pattern=HIERARCHY_REGEX)]
43
+ """
44
+ Name of the "system", could also be thought of as a "device" (should be unique within a facility)
45
+ """
46
+
47
+ facility: Annotated[str, Field(pattern=HIERARCHY_REGEX)]
48
+ """
49
+ Name of the facility (an ORNL institutional designation, i.e. 'neutrons') (NOT abbreviated, should be unique within an organization)
50
+ """
51
+
52
+ organization: Annotated[str, Field(pattern=HIERARCHY_REGEX)]
53
+ """
54
+ Name of the organization (i.e. 'ornl') (NOT abbreviated) (should be unique in an INTERSECT cluster)
55
+ """
56
+
57
+ def hierarchy_string(self, join_str: str = '') -> str:
58
+ """Get the full hierarchy string. This is mostly used internally, but if you're developing a client, it could potentially be helpful.
59
+
60
+ Params
61
+ join_str: String used to separate different hierarchy parts in the full string (default: empty string).
62
+
63
+ Returns:
64
+ Single string, which will contain all system-of-system parts. For optional parts not configured (i.e. - no subsystem), they will be represented by a "-" character.
65
+ """
66
+ if not self.subsystem:
67
+ return join_str.join([self.organization, self.facility, self.system, '-', self.service])
68
+ return join_str.join(
69
+ [
70
+ self.organization,
71
+ self.facility,
72
+ self.system,
73
+ self.subsystem,
74
+ self.service,
75
+ ]
76
+ )
77
+
78
+ # we need to use the Python regex engine instead of the Rust regex engine here, because Rust's does not support lookaheads
79
+ model_config = ConfigDict(regex_engine='python-re')
80
+
81
+
82
+ @dataclass
83
+ class ControlPlaneConfig:
84
+ """Configuration for interacting with a broker."""
85
+
86
+ protocol: ControlProvider
87
+ """
88
+ The protocol of the broker you'd like to use (i.e. AMQP, MQTT...)
89
+ """
90
+ # TODO - support more protocols and protocol versions as needed - see https://www.asyncapi.com/docs/reference/specification/v2.6.0#serverObject
91
+
92
+ username: Annotated[str, Field(min_length=1)]
93
+ """
94
+ Username credentials for broker connection.
95
+ """
96
+
97
+ password: Annotated[str, Field(min_length=1)]
98
+ """
99
+ Password credentials for broker connection.
100
+ """
101
+
102
+ host: Annotated[str, Field(min_length=1)] = '127.0.0.1'
103
+ """
104
+ Broker hostname (default: 127.0.0.1)
105
+ """
106
+
107
+ port: PositiveInt | None = None
108
+ """
109
+ Broker port. List of common ports:
110
+
111
+ - 1883 (MQTT)
112
+ - 4222 (NATS default port)
113
+ - 5222 (XMPP)
114
+ - 5223 (XMPP over TLS)
115
+ - 5671 (AMQP over TLS)
116
+ - 5672 (AMQP)
117
+ - 7400 (DDS Discovery)
118
+ - 7401 (DDS User traffic)
119
+ - 8883 (MQTT over TLS)
120
+ - 61613 (RabbitMQ STOMP - WARNING: ephemeral port)
121
+
122
+ NOTE: INTERSECT currently only supports AMQP and MQTT.
123
+ """
124
+
125
+
126
+ @dataclass
127
+ class DataStoreConfig:
128
+ """Configuration for interacting with a data store."""
129
+
130
+ username: Annotated[str, Field(min_length=1)]
131
+ """
132
+ Username credentials for data store connection.
133
+ """
134
+
135
+ password: Annotated[str, Field(min_length=1)]
136
+ """
137
+ Password credentials for data store connection.
138
+ """
139
+
140
+ host: Annotated[str, Field(min_length=1)] = '127.0.0.1'
141
+ """
142
+ Data store hostname (default: 127.0.0.1)
143
+ """
144
+
145
+ port: PositiveInt | None = None
146
+ """
147
+ Data store port
148
+ """
149
+
150
+
151
+ @dataclass
152
+ class DataStoreConfigMap:
153
+ """Configurations for any data stores the application should talk to."""
154
+
155
+ minio: list[DataStoreConfig] = field(default_factory=list)
156
+ """
157
+ minio configurations
158
+ """
159
+
160
+ def get_missing_data_store_types(self) -> set[IntersectDataHandler]:
161
+ """Return a set of IntersectDataHandlers which will not be permitted, due to a configuration type missing.
162
+
163
+ If all data configurations exist, returns an empty set
164
+ """
165
+ missing = set()
166
+ if not self.minio:
167
+ missing.add(IntersectDataHandler.MINIO)
168
+ return missing
@@ -0,0 +1,28 @@
1
+ """These are miscellaneous constants used in INTERSECT which SDK users may obtain value from knowing about."""
2
+
3
+ SYSTEM_OF_SYSTEM_REGEX = r'^[a-z0-9][-a-z0-9.]*[-a-z0-9]$'
4
+ """
5
+ This is the regex used as a representation of a source/destination.
6
+ This is only needed externally if you are building a client, services can ignore this.
7
+
8
+ NOTE: for future compatibility reasons, we are NOT specifying the number of "parts" (separated by a '.') in this regex. All that matters is that you don't start or end with a period, or start with a hyphen.
9
+ """
10
+
11
+ # see the internal schema file for full validation details
12
+ CAPABILITY_REGEX = r'^[a-zA-Z0-9]\w*$'
13
+ """
14
+ This is the regex used for representing capabilities and event keys. Capabilities should start with an alphanumeric character, and not be longer than 255 characters.
15
+
16
+ This regex applies to namespacing local to a Service, so does not have to be unique across the ecosystem.
17
+ """
18
+
19
+ MIME_TYPE_REGEX = r'\w+/[-+.\w]+'
20
+ """
21
+ Regex used for validating Content Types.
22
+
23
+ References can be found at:
24
+
25
+ - https://www.iana.org/assignments/media-types/media-types.xhtml
26
+
27
+ - https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
28
+ """
@@ -0,0 +1 @@
1
+ """Logic associated with the control plane."""
@@ -0,0 +1,4 @@
1
+ """Common logic for interacting with brokers on the protocol level.
2
+
3
+ These classes should be kept internal to the common library.
4
+ """