OpenSMI-Core 0.1.1__tar.gz → 0.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.
Files changed (44) hide show
  1. {opensmi_core-0.1.1 → opensmi_core-0.2}/PKG-INFO +1 -1
  2. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/PKG-INFO +1 -1
  3. opensmi_core-0.2/src/OpenSMI_Core.egg-info/scm_version.json +8 -0
  4. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/base_ua_object.py +24 -5
  5. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/ua_node_util.py +17 -10
  6. opensmi_core-0.1.1/src/OpenSMI_Core.egg-info/scm_version.json +0 -8
  7. {opensmi_core-0.1.1 → opensmi_core-0.2}/.github/workflows/api-docs.yml +0 -0
  8. {opensmi_core-0.1.1 → opensmi_core-0.2}/.github/workflows/python-publish.yml +0 -0
  9. {opensmi_core-0.1.1 → opensmi_core-0.2}/.gitignore +0 -0
  10. {opensmi_core-0.1.1 → opensmi_core-0.2}/.gitlab-ci.yml +0 -0
  11. {opensmi_core-0.1.1 → opensmi_core-0.2}/LICENSE +0 -0
  12. {opensmi_core-0.1.1 → opensmi_core-0.2}/LICENSES/MIT.txt +0 -0
  13. {opensmi_core-0.1.1 → opensmi_core-0.2}/README.md +0 -0
  14. {opensmi_core-0.1.1 → opensmi_core-0.2}/pyproject.toml +0 -0
  15. {opensmi_core-0.1.1 → opensmi_core-0.2}/setup.cfg +0 -0
  16. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/SOURCES.txt +0 -0
  17. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/dependency_links.txt +0 -0
  18. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/requires.txt +0 -0
  19. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/scm_file_list.json +0 -0
  20. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/top_level.txt +0 -0
  21. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/__init__.py +0 -0
  22. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/async_task_mixin.py +0 -0
  23. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/base_server.py +0 -0
  24. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/config.py +0 -0
  25. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/enums.py +0 -0
  26. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/errors.py +0 -0
  27. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/frozen.py +0 -0
  28. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/hook.py +0 -0
  29. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/lifecycle_mixin.py +0 -0
  30. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/logging.py +0 -0
  31. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/meta.py +0 -0
  32. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/mixin_helpers.py +0 -0
  33. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/protocols.py +0 -0
  34. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/repr_mixin.py +0 -0
  35. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/signal.py +0 -0
  36. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/subscription_manager.py +0 -0
  37. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/ua.py +0 -0
  38. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/ua_enums.py +0 -0
  39. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/unit_all.py +0 -0
  40. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/unit_base.py +0 -0
  41. {opensmi_core-0.1.1 → opensmi_core-0.2}/src/opensmi/core/unset.py +0 -0
  42. {opensmi_core-0.1.1 → opensmi_core-0.2}/tests/test_signal.py +0 -0
  43. {opensmi_core-0.1.1 → opensmi_core-0.2}/tests/test_unit.py +0 -0
  44. {opensmi_core-0.1.1 → opensmi_core-0.2}/tools/auto_generate_units.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: OpenSMI-Core
3
- Version: 0.1.1
3
+ Version: 0.2
4
4
  Summary: Smart Machine Interface core functionality for server and client applications.
5
5
  Author-email: Carsten Harms <Carsten.Harms@dfki.de>, Simon Jungbluth <Simon.Jungbluth@smartfactory.de>
6
6
  Classifier: Development Status :: 4 - Beta
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: OpenSMI-Core
3
- Version: 0.1.1
3
+ Version: 0.2
4
4
  Summary: Smart Machine Interface core functionality for server and client applications.
5
5
  Author-email: Carsten Harms <Carsten.Harms@dfki.de>, Simon Jungbluth <Simon.Jungbluth@smartfactory.de>
6
6
  Classifier: Development Status :: 4 - Beta
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.2",
3
+ "distance": 0,
4
+ "node": "g90c7c0325f86ebe6f93c7c832b29f4672c03faa6",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-09-23"
8
+ }
@@ -21,11 +21,14 @@ _ServerType = TypeVar("_ServerType", bound="BaseServer")
21
21
  class BaseUaObject(Generic[_ServerType]):
22
22
  """Base class for all UA objects, both client- and server-side."""
23
23
 
24
+ _parent: "BaseUaObject[_ServerType] | None" = None
25
+
24
26
  def __init__(
25
27
  self,
26
28
  *,
27
29
  name: str | None = None,
28
30
  server: _ServerType | None = None,
31
+ parent: "BaseUaObject[_ServerType] | None" = None,
29
32
  **kwargs,
30
33
  ) -> None:
31
34
  """*Cooperative* constructor.
@@ -33,6 +36,8 @@ class BaseUaObject(Generic[_ServerType]):
33
36
  :param name: The name of the UA object. Defaults to the class name.
34
37
  :param server: The associated server of the UA object. Note that there must be at least one non ``None`` in
35
38
  the hierarchy.
39
+ :param parent: The parent of the UA object. Only Machines are allowed to have no parent. Can be set later before
40
+ asynchronous initialization.
36
41
  """
37
42
  if name is None:
38
43
  name = self.__class__.__name__
@@ -42,6 +47,8 @@ class BaseUaObject(Generic[_ServerType]):
42
47
 
43
48
  self._name: str = name
44
49
  self._server: _ServerType | None = server
50
+ if parent is not None:
51
+ self.parent = parent # via setter to allow optional runtime type checking
45
52
  self._ua_node: Node | None = None
46
53
  self._logger: structlog.BoundLogger = structlog.get_logger(
47
54
  f"opensmi.{self.__class__.__name__}", name=self.name
@@ -76,16 +83,17 @@ class BaseUaObject(Generic[_ServerType]):
76
83
  @property
77
84
  @deprecated("Use path instead")
78
85
  def full_name(self) -> str:
79
- parent = getattr(self, "parent", None)
80
- if isinstance(parent, BaseUaObject):
81
- return f"{parent.full_name}/{self.name}"
86
+ if self.parent is not None:
87
+ assert isinstance(self.parent, BaseUaObject)
88
+ return f"{self.parent.full_name}/{self.name}"
82
89
  return f"/{self.name}"
83
90
 
84
91
  @property
85
92
  def path(self) -> PurePosixPath:
86
93
  """Return the full path of the object."""
87
- if isinstance(parent := getattr(self, "parent", None), BaseUaObject):
88
- return parent.path / self.name
94
+ if self.parent is not None:
95
+ assert isinstance(self.parent, BaseUaObject)
96
+ return self.parent.path / self.name
89
97
  return PurePosixPath("/") / self.name
90
98
 
91
99
  @property
@@ -93,6 +101,17 @@ class BaseUaObject(Generic[_ServerType]):
93
101
  """Logger associated with the `UaObject` instance."""
94
102
  return self._logger # type: ignore
95
103
 
104
+ @property
105
+ def parent(self) -> "BaseUaObject[_ServerType] | None":
106
+ """Return the untyped parent of the UA object."""
107
+ return self._parent
108
+
109
+ @parent.setter
110
+ def parent(self, parent: "BaseUaObject[_ServerType]") -> None:
111
+ """Set the parent of the UA object. Given ``parent`` must be an instance of `BaseUaObject`."""
112
+ assert isinstance(parent, BaseUaObject)
113
+ self._parent = parent
114
+
96
115
  # TODO
97
116
  # @override
98
117
  # def _repr_items(self) -> Iterator[tuple[str, object]]:
@@ -21,6 +21,8 @@ from opensmi.core import Unit
21
21
  NULL_NODE_ID = ua.NodeId()
22
22
  """ This node id indicates an invalid Node ID and should be treated as 'None'. """
23
23
 
24
+ _LOGGER = structlog.getLogger(__name__)
25
+
24
26
 
25
27
  async def read_value(node: Node) -> Any:
26
28
  """Read the value of the given node and transforms the NULL_NODE_ID into None."""
@@ -126,17 +128,22 @@ async def get_properties(node: Node, *, logger: structlog.stdlib.BoundLogger | N
126
128
  return result
127
129
 
128
130
 
129
- async def get_type_definition(ua_node: Node) -> str:
130
- """Return the browse name of the OPC UA type definition of the given node."""
131
- try:
132
- type_definition_list = await ua_node.get_references(
133
- ua.object_ids.ObjectIds.HasTypeDefinition,
134
- ua.BrowseDirection.Forward,
135
- )
131
+ async def get_type_definition(ua_node: Node, *, default: str = "UNKNOWN") -> str:
132
+ """Return the browse name of the OPC UA type definition of the given node.
133
+
134
+ :param ua_node: OPC UA node to operate on.
135
+ :param default: Default value to return if type definition cannot be determined.
136
+ """
137
+ assert ua_node is not None, "No node node given!"
138
+ type_definition_list = await ua_node.get_references(
139
+ ua.object_ids.ObjectIds.HasTypeDefinition,
140
+ ua.BrowseDirection.Forward,
141
+ )
142
+ if len(type_definition_list) > 0:
136
143
  return type_definition_list[0].BrowseName.Name
137
- except Exception as ex:
138
- msg = f"Could not find type definition for node {ua_node.nodeid.to_string()}!"
139
- raise RuntimeError(msg) from ex
144
+
145
+ _LOGGER.warning("Could not determine type definition!", ua_node = ua_node.nodeid.to_string(), default=default)
146
+ return default
140
147
 
141
148
 
142
149
  def get_node_id(
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.1.1",
3
- "distance": 0,
4
- "node": "ga4ff41ae9039d37aefd1ee2c5848d346c782f6cc",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-09-15"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes