OpenSMI-Core 0.1__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 (42) hide show
  1. opensmi_core-0.1/.github/workflows/python-publish.yml +70 -0
  2. opensmi_core-0.1/.gitignore +18 -0
  3. opensmi_core-0.1/.gitlab-ci.yml +49 -0
  4. opensmi_core-0.1/LICENSE +18 -0
  5. opensmi_core-0.1/LICENSES/MIT.txt +18 -0
  6. opensmi_core-0.1/PKG-INFO +32 -0
  7. opensmi_core-0.1/README.md +2 -0
  8. opensmi_core-0.1/pyproject.toml +180 -0
  9. opensmi_core-0.1/setup.cfg +4 -0
  10. opensmi_core-0.1/src/OpenSMI_Core.egg-info/PKG-INFO +32 -0
  11. opensmi_core-0.1/src/OpenSMI_Core.egg-info/SOURCES.txt +40 -0
  12. opensmi_core-0.1/src/OpenSMI_Core.egg-info/dependency_links.txt +1 -0
  13. opensmi_core-0.1/src/OpenSMI_Core.egg-info/requires.txt +12 -0
  14. opensmi_core-0.1/src/OpenSMI_Core.egg-info/scm_file_list.json +37 -0
  15. opensmi_core-0.1/src/OpenSMI_Core.egg-info/scm_version.json +8 -0
  16. opensmi_core-0.1/src/OpenSMI_Core.egg-info/top_level.txt +1 -0
  17. opensmi_core-0.1/src/opensmi/core/__init__.py +21 -0
  18. opensmi_core-0.1/src/opensmi/core/async_task_mixin.py +55 -0
  19. opensmi_core-0.1/src/opensmi/core/base_server.py +75 -0
  20. opensmi_core-0.1/src/opensmi/core/base_ua_object.py +120 -0
  21. opensmi_core-0.1/src/opensmi/core/config.py +92 -0
  22. opensmi_core-0.1/src/opensmi/core/enums.py +24 -0
  23. opensmi_core-0.1/src/opensmi/core/errors.py +67 -0
  24. opensmi_core-0.1/src/opensmi/core/frozen.py +26 -0
  25. opensmi_core-0.1/src/opensmi/core/hook.py +22 -0
  26. opensmi_core-0.1/src/opensmi/core/lifecycle_mixin.py +275 -0
  27. opensmi_core-0.1/src/opensmi/core/logging.py +161 -0
  28. opensmi_core-0.1/src/opensmi/core/meta.py +51 -0
  29. opensmi_core-0.1/src/opensmi/core/mixin_helpers.py +19 -0
  30. opensmi_core-0.1/src/opensmi/core/protocols.py +32 -0
  31. opensmi_core-0.1/src/opensmi/core/repr_mixin.py +33 -0
  32. opensmi_core-0.1/src/opensmi/core/signal.py +36 -0
  33. opensmi_core-0.1/src/opensmi/core/subscription_manager.py +190 -0
  34. opensmi_core-0.1/src/opensmi/core/ua.py +17 -0
  35. opensmi_core-0.1/src/opensmi/core/ua_enums.py +93 -0
  36. opensmi_core-0.1/src/opensmi/core/ua_node_util.py +239 -0
  37. opensmi_core-0.1/src/opensmi/core/unit_all.py +2187 -0
  38. opensmi_core-0.1/src/opensmi/core/unit_base.py +71 -0
  39. opensmi_core-0.1/src/opensmi/core/unset.py +22 -0
  40. opensmi_core-0.1/tests/test_signal.py +144 -0
  41. opensmi_core-0.1/tests/test_unit.py +62 -0
  42. opensmi_core-0.1/tools/auto_generate_units.py +170 -0
@@ -0,0 +1,70 @@
1
+ # This workflow will upload a Python Package to PyPI when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3
+
4
+ # This workflow uses actions that are not certified by GitHub.
5
+ # They are provided by a third-party and are governed by
6
+ # separate terms of service, privacy policy, and support
7
+ # documentation.
8
+
9
+ name: Upload Python Package
10
+
11
+ on:
12
+ release:
13
+ types: [published]
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ release-build:
20
+ runs-on: ubuntu-latest
21
+
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+
25
+ - uses: actions/setup-python@v5
26
+ with:
27
+ python-version: "3.11"
28
+
29
+ - name: Build release distributions
30
+ run: |
31
+ # NOTE: put your own distribution build steps here.
32
+ python -m pip install build
33
+ python -m build
34
+
35
+ - name: Upload distributions
36
+ uses: actions/upload-artifact@v4
37
+ with:
38
+ name: release-dists
39
+ path: dist/
40
+
41
+ pypi-publish:
42
+ runs-on: ubuntu-latest
43
+ needs:
44
+ - release-build
45
+ permissions:
46
+ # IMPORTANT: this permission is mandatory for trusted publishing
47
+ id-token: write
48
+
49
+ # Dedicated environments with protections for publishing are strongly recommended.
50
+ # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
51
+ environment:
52
+ name: pypi
53
+ # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
54
+ # url: https://pypi.org/p/YOURPROJECT
55
+ #
56
+ # ALTERNATIVE: if your GitHub Release name is the PyPI project version string
57
+ # ALTERNATIVE: exactly, uncomment the following line instead:
58
+ # url: https://pypi.org/project/YOURPROJECT/${{ github.event.release.name }}
59
+
60
+ steps:
61
+ - name: Retrieve release distributions
62
+ uses: actions/download-artifact@v4
63
+ with:
64
+ name: release-dists
65
+ path: dist/
66
+
67
+ - name: Publish release distributions to PyPI
68
+ uses: pypa/gh-action-pypi-publish@release/v1
69
+ with:
70
+ packages-dir: dist/
@@ -0,0 +1,18 @@
1
+ *.pyc
2
+ /.idea
3
+ /.vs
4
+ /.vscode
5
+ *.egg-info
6
+ /dist
7
+ *.log
8
+ /build
9
+ /tools/UNECE_to_OPCUA.csv
10
+ /.venv/
11
+ /uv.lock
12
+ /*.xml
13
+ /*.html
14
+ *.coverage
15
+ /apidocs
16
+ *.der
17
+ *.pem
18
+ *.sql
@@ -0,0 +1,49 @@
1
+ default:
2
+ image: python:3.14-alpine
3
+ cache:
4
+ key: "$CI_COMMIT_REF_SLUG"
5
+ paths:
6
+ - .cache/pip
7
+ tags:
8
+ - k8s
9
+
10
+ test:
11
+ stage: test
12
+ parallel:
13
+ matrix:
14
+ - PYTHON_VERSION: [ "3.11", "3.14" ]
15
+ image: python:${PYTHON_VERSION}-alpine
16
+ before_script:
17
+ - apk add --no-cache git
18
+ - python --version
19
+ - python -m pip install --cache-dir .cache/pip --upgrade pip setuptools wheel
20
+ - python -m pip install --cache-dir .cache/pip . --group dev
21
+ script:
22
+ - python -m pytest --timeout=120 --html=report.html --self-contained-html --junitxml=result.xml --cov=open_smi --cov-report term --cov-report xml:coverage.xml -v -n 8
23
+ coverage: '/TOTAL.+ ([0-9]{1,3}%)/'
24
+ artifacts:
25
+ when: always
26
+ paths:
27
+ - report.html
28
+ - result.xml
29
+ - coverage.xml
30
+ - .coverage
31
+ reports:
32
+ junit: result.xml
33
+ coverage_report:
34
+ coverage_format: cobertura
35
+ path: coverage.xml
36
+
37
+ package:
38
+ stage: deploy
39
+ variables:
40
+ TWINE_USERNAME: __token__
41
+ TWINE_PASSWORD: ${TEST_PYPI_PASSWORD}
42
+ TWINE_REPOSITORY_URL: https://test.pypi.org/legacy/
43
+ script:
44
+ - apk add --no-cache git
45
+ - pip install build twine
46
+ - python -m build
47
+ - python -m twine upload dist/* --verbose
48
+ rules:
49
+ - if: $CI_COMMIT_TAG
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OpenSMI Contributors.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
16
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OpenSMI Contributors.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
16
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,32 @@
1
+ Metadata-Version: 2.4
2
+ Name: OpenSMI-Core
3
+ Version: 0.1
4
+ Summary: Smart Machine Interface core functionality for server and client applications.
5
+ Author-email: Carsten Harms <Carsten.Harms@dfki.de>, Simon Jungbluth <Simon.Jungbluth@smartfactory.de>
6
+ Classifier: Development Status :: 4 - Beta
7
+ Classifier: Intended Audience :: Developers
8
+ Classifier: Intended Audience :: Information Technology
9
+ Classifier: Intended Audience :: Manufacturing
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Topic :: Communications
17
+ Classifier: Topic :: Scientific/Engineering
18
+ Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
19
+ Classifier: Topic :: Software Development :: Embedded Systems
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.11
23
+ License-File: LICENSE
24
+ Requires-Dist: asyncua<3,>=2.0.1
25
+ Requires-Dist: structlog>=26
26
+ Requires-Dist: typing-extensions>=4.16.0
27
+ Provides-Extra: rich
28
+ Requires-Dist: rich>=15.0.0; extra == "rich"
29
+ Requires-Dist: colorama>=0.4; sys_platform == "win32" and extra == "rich"
30
+ Provides-Extra: json
31
+ Requires-Dist: orjson<4,>=3; extra == "json"
32
+ Dynamic: license-file
@@ -0,0 +1,2 @@
1
+ # OpenSMI Common
2
+
@@ -0,0 +1,180 @@
1
+ [build-system]
2
+ requires = ["setuptools>=80", "setuptools-scm[simple]>=9.2"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "OpenSMI-Core"
7
+ dynamic = ["version"]
8
+
9
+ description = "Smart Machine Interface core functionality for server and client applications."
10
+ authors = [
11
+ { name = "Carsten Harms", email = "Carsten.Harms@dfki.de" },
12
+ { name = "Simon Jungbluth", email = "Simon.Jungbluth@smartfactory.de" },
13
+ ]
14
+
15
+ # see https://pypi.org/classifiers/
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "Intended Audience :: Information Technology",
20
+ "Intended Audience :: Manufacturing",
21
+ "Intended Audience :: Science/Research",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Programming Language :: Python :: 3.14",
27
+ "Topic :: Communications",
28
+ "Topic :: Scientific/Engineering",
29
+ "Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator",
30
+ "Topic :: Software Development :: Embedded Systems",
31
+ "Topic :: Software Development :: Libraries",
32
+ "Typing :: Typed"
33
+ ]
34
+
35
+ requires-python = ">=3.11"
36
+
37
+ dependencies = [
38
+ "asyncua>=2.0.1,<3", # OPC UA, main dep; has quite a few deps
39
+ "structlog>=26", # structured logging; has no deps
40
+ "typing-extensions>=4.16.0", # backported type hints; already a dep of asyncua
41
+ ]
42
+
43
+ [project.optional-dependencies]
44
+ rich = [
45
+ "rich>=15.0.0", # colorful logging; transitive deps: markdown-it-py, mdurl & pygments
46
+ "colorama>=0.4; sys_platform == 'win32'", # colors in terminal on Windows; has no deps
47
+ ]
48
+ json = [
49
+ "orjson>=3, <4", # faster JSON logging; has no deps
50
+ ]
51
+
52
+ [dependency-groups]
53
+ dev = [
54
+ "basedpyright>=1.39.9",
55
+ "ruff>=0.15",
56
+ "pytest>=9",
57
+ "pytest-asyncio>=1",
58
+ "pytest-cov>=7",
59
+ "pytest-xdist>=3",
60
+ "pytest-html>=4",
61
+ "pytest-timeout>=2",
62
+ "openpyxl" # to load UNECE Excel to autogenerate units
63
+ ]
64
+
65
+ [tool.setuptools]
66
+ include-package-data = true
67
+
68
+ [tool.setuptools.packages.find]
69
+ where = ["src"]
70
+ namespaces = true
71
+ # exclude = ["tests", "doc*", "examples"]
72
+
73
+ [tool.ruff]
74
+ # Exclude a variety of commonly ignored directories.
75
+ exclude = [
76
+ ".bzr",
77
+ ".direnv",
78
+ ".eggs",
79
+ ".git",
80
+ ".git-rewrite",
81
+ ".hg",
82
+ ".ipynb_checkpoints",
83
+ ".mypy_cache",
84
+ ".nox",
85
+ ".pants.d",
86
+ ".pyenv",
87
+ ".pytest_cache",
88
+ ".pytype",
89
+ ".ruff_cache",
90
+ ".svn",
91
+ ".tox",
92
+ ".venv",
93
+ ".vscode",
94
+ "__pypackages__",
95
+ "_build",
96
+ "buck-out",
97
+ "build",
98
+ "dist",
99
+ "node_modules",
100
+ "site-packages",
101
+ "venv",
102
+ ]
103
+
104
+ line-length = 120
105
+ indent-width = 4
106
+ fix = true
107
+
108
+
109
+ [tool.ruff.lint]
110
+ select = ["A", "ANN001", "ANN201", "ANN205", "ANN206",
111
+ "ASYNC", "B", "C4", "CPY", "D", "DTZ", "E", "EM",
112
+ "EXE", "F", "FA", "ICN", "I", "LOG", "T20", "PT",
113
+ "SLF", "SIM", "C901", "N", "PIE", "PLE", "PYI", "PT",
114
+ "Q", "RSE", "RET", "TD", "PERF", "UP", "FURB", "RUF",
115
+ "TRY"]
116
+ ignore = ["D203", "D213"]
117
+
118
+ # Allow fix for all enabled rules (when `--fix`) is provided.
119
+ fixable = ["ALL"]
120
+ unfixable = []
121
+
122
+ # Allow unused variables when underscore-prefixed.
123
+ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
124
+
125
+ [tool.ruff.lint.flake8-annotations]
126
+ allow-star-arg-any = true
127
+
128
+ [tool.ruff.lint.flake8-copyright]
129
+ notice-rgx = "SPDX-FileCopyrightText: \\d{4}"
130
+ author = "OpenSMI Contributors"
131
+
132
+ [tool.ruff.lint.per-file-ignores]
133
+ "tests/**" = ["ANN", "D", "T", "SLF001"]
134
+ "src/opensmi/core/unit_all.py" = [ # auto-generated
135
+ "E501", # line too long
136
+ "RUF001", # String contains ambiguous ~
137
+ "CPY", # copyright
138
+ ]
139
+
140
+ [tool.ruff.format]
141
+ quote-style = "double"
142
+ indent-style = "space"
143
+ skip-magic-trailing-comma = false
144
+ line-ending = "auto"
145
+
146
+ # Enable auto-formatting of code examples in docstrings. Markdown,
147
+ # reStructuredText code/literal blocks and doctests are all supported.
148
+ #
149
+ # This is currently disabled by default, but it is planned for this
150
+ # to be opt-out in the future.
151
+ docstring-code-format = true
152
+
153
+ # Set the line length limit used when formatting code snippets in
154
+ # docstrings.
155
+ #
156
+ # This only has an effect when the `docstring-code-format` setting is
157
+ # enabled.
158
+ docstring-code-line-length = "dynamic"
159
+
160
+ [tool.mypy]
161
+ packages = "src/opensmi/core"
162
+
163
+ warn_unused_configs = true
164
+ pretty = true
165
+
166
+ strict = true
167
+
168
+ [tool.basedpyright]
169
+ include = ["src"]
170
+ typeCheckingMode = "standard"
171
+ executionEnvironments = [{ root = "src" }]
172
+
173
+ [tool.pydoctor]
174
+ project-name = "OpenSMI-Core"
175
+ add-package = ["src/opensmi/core"]
176
+ docformat = "restructuredtext"
177
+ theme = "readthedocs"
178
+ # verbose = 1
179
+ warnings-as-errors = true
180
+ intersphinx = ["https://opcua-asyncio.readthedocs.io/en/latest/objects.inv"] # TODO(CaHa): does not work
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,32 @@
1
+ Metadata-Version: 2.4
2
+ Name: OpenSMI-Core
3
+ Version: 0.1
4
+ Summary: Smart Machine Interface core functionality for server and client applications.
5
+ Author-email: Carsten Harms <Carsten.Harms@dfki.de>, Simon Jungbluth <Simon.Jungbluth@smartfactory.de>
6
+ Classifier: Development Status :: 4 - Beta
7
+ Classifier: Intended Audience :: Developers
8
+ Classifier: Intended Audience :: Information Technology
9
+ Classifier: Intended Audience :: Manufacturing
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Topic :: Communications
17
+ Classifier: Topic :: Scientific/Engineering
18
+ Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol Translator
19
+ Classifier: Topic :: Software Development :: Embedded Systems
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.11
23
+ License-File: LICENSE
24
+ Requires-Dist: asyncua<3,>=2.0.1
25
+ Requires-Dist: structlog>=26
26
+ Requires-Dist: typing-extensions>=4.16.0
27
+ Provides-Extra: rich
28
+ Requires-Dist: rich>=15.0.0; extra == "rich"
29
+ Requires-Dist: colorama>=0.4; sys_platform == "win32" and extra == "rich"
30
+ Provides-Extra: json
31
+ Requires-Dist: orjson<4,>=3; extra == "json"
32
+ Dynamic: license-file
@@ -0,0 +1,40 @@
1
+ .gitignore
2
+ .gitlab-ci.yml
3
+ LICENSE
4
+ README.md
5
+ pyproject.toml
6
+ .github/workflows/python-publish.yml
7
+ LICENSES/MIT.txt
8
+ src/OpenSMI_Core.egg-info/PKG-INFO
9
+ src/OpenSMI_Core.egg-info/SOURCES.txt
10
+ src/OpenSMI_Core.egg-info/dependency_links.txt
11
+ src/OpenSMI_Core.egg-info/requires.txt
12
+ src/OpenSMI_Core.egg-info/scm_file_list.json
13
+ src/OpenSMI_Core.egg-info/scm_version.json
14
+ src/OpenSMI_Core.egg-info/top_level.txt
15
+ src/opensmi/core/__init__.py
16
+ src/opensmi/core/async_task_mixin.py
17
+ src/opensmi/core/base_server.py
18
+ src/opensmi/core/base_ua_object.py
19
+ src/opensmi/core/config.py
20
+ src/opensmi/core/enums.py
21
+ src/opensmi/core/errors.py
22
+ src/opensmi/core/frozen.py
23
+ src/opensmi/core/hook.py
24
+ src/opensmi/core/lifecycle_mixin.py
25
+ src/opensmi/core/logging.py
26
+ src/opensmi/core/meta.py
27
+ src/opensmi/core/mixin_helpers.py
28
+ src/opensmi/core/protocols.py
29
+ src/opensmi/core/repr_mixin.py
30
+ src/opensmi/core/signal.py
31
+ src/opensmi/core/subscription_manager.py
32
+ src/opensmi/core/ua.py
33
+ src/opensmi/core/ua_enums.py
34
+ src/opensmi/core/ua_node_util.py
35
+ src/opensmi/core/unit_all.py
36
+ src/opensmi/core/unit_base.py
37
+ src/opensmi/core/unset.py
38
+ tests/test_signal.py
39
+ tests/test_unit.py
40
+ tools/auto_generate_units.py
@@ -0,0 +1,12 @@
1
+ asyncua<3,>=2.0.1
2
+ structlog>=26
3
+ typing-extensions>=4.16.0
4
+
5
+ [json]
6
+ orjson<4,>=3
7
+
8
+ [rich]
9
+ rich>=15.0.0
10
+
11
+ [rich:sys_platform == "win32"]
12
+ colorama>=0.4
@@ -0,0 +1,37 @@
1
+ {
2
+ "files": [
3
+ ".github/workflows/python-publish.yml",
4
+ ".gitignore",
5
+ ".gitlab-ci.yml",
6
+ "LICENSE",
7
+ "LICENSES/MIT.txt",
8
+ "README.md",
9
+ "pyproject.toml",
10
+ "src/opensmi/core/__init__.py",
11
+ "src/opensmi/core/async_task_mixin.py",
12
+ "src/opensmi/core/base_server.py",
13
+ "src/opensmi/core/base_ua_object.py",
14
+ "src/opensmi/core/config.py",
15
+ "src/opensmi/core/enums.py",
16
+ "src/opensmi/core/errors.py",
17
+ "src/opensmi/core/frozen.py",
18
+ "src/opensmi/core/hook.py",
19
+ "src/opensmi/core/lifecycle_mixin.py",
20
+ "src/opensmi/core/logging.py",
21
+ "src/opensmi/core/meta.py",
22
+ "src/opensmi/core/mixin_helpers.py",
23
+ "src/opensmi/core/protocols.py",
24
+ "src/opensmi/core/repr_mixin.py",
25
+ "src/opensmi/core/signal.py",
26
+ "src/opensmi/core/subscription_manager.py",
27
+ "src/opensmi/core/ua.py",
28
+ "src/opensmi/core/ua_enums.py",
29
+ "src/opensmi/core/ua_node_util.py",
30
+ "src/opensmi/core/unit_all.py",
31
+ "src/opensmi/core/unit_base.py",
32
+ "src/opensmi/core/unset.py",
33
+ "tests/test_signal.py",
34
+ "tests/test_unit.py",
35
+ "tools/auto_generate_units.py"
36
+ ]
37
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.1",
3
+ "distance": 0,
4
+ "node": "g00bee2346bf90929caf7a2fb0ea251f864e2174c",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-09-15"
8
+ }
@@ -0,0 +1,21 @@
1
+ # SPDX-FileCopyrightText: 2026 OpenSMI Contributors
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """Common functionality for both server and client."""
6
+
7
+ from importlib import metadata
8
+
9
+ from .async_task_mixin import AsyncTaskMixin as AsyncTaskMixin
10
+ from .enums import LifecycleState as LifecycleState
11
+ from .lifecycle_mixin import LifecycleMixin as LifecycleMixin
12
+ from .lifecycle_mixin import lifecycle as lifecycle
13
+ from .logging import LogFormat as LogFormat
14
+ from .logging import setup_logging as setup_logging
15
+ from .signal import Signal as Signal
16
+ from .ua_enums import MachineryItemState as MachineryItemState
17
+ from .ua_enums import MachineryOperationMode as MachineryOperationMode
18
+ from .ua_enums import SkillState as SkillState
19
+ from .unit_all import Unit as Unit
20
+
21
+ __version__ = metadata.version("OpenSMI-Core")
@@ -0,0 +1,55 @@
1
+ # SPDX-FileCopyrightText: 2026 OpenSMI Contributors
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """Mixin for reliable tracking of fire-and-forget asyncio tasks."""
6
+
7
+ import asyncio
8
+ from collections.abc import Coroutine
9
+ from typing import Any
10
+
11
+
12
+ class AsyncTaskMixin:
13
+ """Mixin for reliable tracking of fire-and-forget asyncio tasks.
14
+
15
+ Avoids such tasks disappearing while executing when garbage collected
16
+ (https://docs.python.org/3/library/asyncio-task.html#creating-tasks).
17
+ """
18
+
19
+ __tasks: set[asyncio.Task[None]] | None = None
20
+
21
+ def _create_task(
22
+ self,
23
+ coro: Coroutine[Any, Any, None], # pyright: ignore[reportExplicitAny]
24
+ *,
25
+ name: str,
26
+ ) -> None:
27
+ """Schedule and track a background coroutine.
28
+
29
+ The coroutine must return ``None``.
30
+ """
31
+ if self.__tasks is None:
32
+ self.__tasks = set()
33
+
34
+ task = asyncio.create_task(coro, name=name)
35
+ self.__tasks.add(task)
36
+ task.add_done_callback(self.__tasks.discard)
37
+
38
+ @property
39
+ def _pending_tasks(self) -> set[asyncio.Task[None]]:
40
+ """Return currently running tracked tasks."""
41
+ if self.__tasks is None:
42
+ return set()
43
+ return self.__tasks.copy()
44
+
45
+ async def _cancel_tasks(self) -> None:
46
+ """Cancel and await all tracked tasks."""
47
+ if self.__tasks is None:
48
+ return # nothing to cancel
49
+ tasks = self.__tasks.copy()
50
+
51
+ for task in tasks:
52
+ _ = task.cancel()
53
+
54
+ if tasks:
55
+ _ = await asyncio.gather(*tasks, return_exceptions=True)