OpenSMI-Core 0.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.
- opensmi_core-0.2/.github/workflows/api-docs.yml +58 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/PKG-INFO +1 -1
- {opensmi_core-0.1 → opensmi_core-0.2}/pyproject.toml +1 -1
- {opensmi_core-0.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/PKG-INFO +1 -1
- {opensmi_core-0.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/SOURCES.txt +1 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/scm_file_list.json +1 -0
- opensmi_core-0.2/src/OpenSMI_Core.egg-info/scm_version.json +8 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/base_ua_object.py +24 -5
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/ua_node_util.py +17 -10
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/unit_all.py +14 -14
- {opensmi_core-0.1 → opensmi_core-0.2}/tools/auto_generate_units.py +1 -1
- opensmi_core-0.1/src/OpenSMI_Core.egg-info/scm_version.json +0 -8
- {opensmi_core-0.1 → opensmi_core-0.2}/.github/workflows/python-publish.yml +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/.gitignore +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/.gitlab-ci.yml +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/LICENSE +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/LICENSES/MIT.txt +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/README.md +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/setup.cfg +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/dependency_links.txt +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/requires.txt +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/OpenSMI_Core.egg-info/top_level.txt +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/__init__.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/async_task_mixin.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/base_server.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/config.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/enums.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/errors.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/frozen.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/hook.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/lifecycle_mixin.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/logging.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/meta.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/mixin_helpers.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/protocols.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/repr_mixin.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/signal.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/subscription_manager.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/ua.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/ua_enums.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/unit_base.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/src/opensmi/core/unset.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/tests/test_signal.py +0 -0
- {opensmi_core-0.1 → opensmi_core-0.2}/tests/test_unit.py +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Simple workflow for deploying static content to GitHub Pages
|
|
2
|
+
name: Publish API doc to Pages
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
# Runs on pushes targeting the default branch
|
|
6
|
+
push:
|
|
7
|
+
branches: ["main"]
|
|
8
|
+
|
|
9
|
+
# Allows you to run this workflow manually from the Actions tab
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
pages: write
|
|
16
|
+
id-token: write
|
|
17
|
+
|
|
18
|
+
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
|
19
|
+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
|
20
|
+
concurrency:
|
|
21
|
+
group: "pages"
|
|
22
|
+
cancel-in-progress: false
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
# Single deploy job since we're just deploying
|
|
26
|
+
deploy:
|
|
27
|
+
environment:
|
|
28
|
+
name: github-pages
|
|
29
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout
|
|
33
|
+
uses: actions/checkout@v4
|
|
34
|
+
|
|
35
|
+
- name: Set up Python
|
|
36
|
+
uses: actions/setup-python@v6
|
|
37
|
+
with:
|
|
38
|
+
python-version: "3.13"
|
|
39
|
+
|
|
40
|
+
- name: Install dependencies
|
|
41
|
+
run: |
|
|
42
|
+
pip install pydoctor
|
|
43
|
+
|
|
44
|
+
- name: Generate API documentation
|
|
45
|
+
run: |
|
|
46
|
+
pydoctor
|
|
47
|
+
|
|
48
|
+
- name: Setup Pages
|
|
49
|
+
uses: actions/configure-pages@v5
|
|
50
|
+
|
|
51
|
+
- name: Upload artifact
|
|
52
|
+
uses: actions/upload-pages-artifact@v3
|
|
53
|
+
with:
|
|
54
|
+
path: './apidocs'
|
|
55
|
+
|
|
56
|
+
- name: Deploy to GitHub Pages
|
|
57
|
+
id: deployment
|
|
58
|
+
uses: actions/deploy-pages@v5
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OpenSMI-Core
|
|
3
|
-
Version: 0.
|
|
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
|
|
@@ -176,5 +176,5 @@ add-package = ["src/opensmi/core"]
|
|
|
176
176
|
docformat = "restructuredtext"
|
|
177
177
|
theme = "readthedocs"
|
|
178
178
|
# verbose = 1
|
|
179
|
-
warnings-as-errors = true
|
|
179
|
+
# warnings-as-errors = true
|
|
180
180
|
intersphinx = ["https://opcua-asyncio.readthedocs.io/en/latest/objects.inv"] # TODO(CaHa): does not work
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OpenSMI-Core
|
|
3
|
-
Version: 0.
|
|
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
|
|
@@ -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
|
|
80
|
-
|
|
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
|
|
88
|
-
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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,7 +1,7 @@
|
|
|
1
1
|
"""Units as type-checkable enum."""
|
|
2
2
|
|
|
3
3
|
# !!! autogenerated code, do not change manually !!!
|
|
4
|
-
# generated on 2026-09-
|
|
4
|
+
# generated on 2026-09-15 14:19:13
|
|
5
5
|
from opensmi.core.unit_base import BaseUnit
|
|
6
6
|
|
|
7
7
|
|
|
@@ -73,7 +73,7 @@ class Unit(BaseUnit):
|
|
|
73
73
|
BARREL_UK_PETROLEUM_PER_MINUTE = ("bbl (UK liq.)/min", 4863288)
|
|
74
74
|
BARREL_UK_PETROLEUM_PER_SECOND = ("bbl (UK liq.)/s", 4863537)
|
|
75
75
|
BARREL_US = ("barrel (US)", 4344908)
|
|
76
|
-
BARREL_US_PER_DAY = ("barrel
|
|
76
|
+
BARREL_US_PER_DAY = ("barrel (US)/d", 16945)
|
|
77
77
|
BARREL_US_PER_MINUTE = ("barrel (US)/min", 13633)
|
|
78
78
|
BARREL_US_PETROLEUM_PER_HOUR = ("bbl (US)/h", 4863538)
|
|
79
79
|
BARREL_US_PETROLEUM_PER_SECOND = ("bbl (US)/s", 4863539)
|
|
@@ -119,9 +119,9 @@ class Unit(BaseUnit):
|
|
|
119
119
|
BOTTLE = ("bottle", 16975)
|
|
120
120
|
BOX = ("box", 16984)
|
|
121
121
|
BRAKE_HORSE_POWER = ("BHP", 4343888)
|
|
122
|
-
BRITISH_THERMAL_UNIT_39_F = ("Btu (39 ºF)
|
|
122
|
+
BRITISH_THERMAL_UNIT_39_F = ("Btu (39 ºF)", 5125686)
|
|
123
123
|
BRITISH_THERMAL_UNIT_59_F = ("Btu (59 ºF)", 5125687)
|
|
124
|
-
BRITISH_THERMAL_UNIT_60_F = ("Btu (60 ºF)
|
|
124
|
+
BRITISH_THERMAL_UNIT_60_F = ("Btu (60 ºF)", 5125688)
|
|
125
125
|
BRITISH_THERMAL_UNIT_INTERNATIONAL_TABLE = ("BtuIT", 4346965)
|
|
126
126
|
BRITISH_THERMAL_UNIT_INTERNATIONAL_TABLE_FOOT_PER_HOUR_SQUARE_FOOT_DEGREE_FAHRENHEIT = (
|
|
127
127
|
"BtuIT·ft/(h·ft²·°F)",
|
|
@@ -167,10 +167,10 @@ class Unit(BaseUnit):
|
|
|
167
167
|
BRITISH_THERMAL_UNIT_THERMOCHEMICAL_PER_POUND_DEGREE_FAHRENHEIT = ("Btuth/(lb·°F)", 4863280)
|
|
168
168
|
BRITISH_THERMAL_UNIT_THERMOCHEMICAL_PER_POUND_DEGREE_RANKINE = ("(Btuth/°R)/lb", 5125684)
|
|
169
169
|
BRITISH_THERMAL_UNIT_THERMOCHEMICAL_PER_SECOND = ("Btuth/s", 4863282)
|
|
170
|
-
BRITISH_THERMAL_UNIT_THERMOCHEMICAL_PER_SECOND_SQUARE_FOOT_DEGREE_FAHRENHEIT = ("Btuth/(s·ft²·ºF)
|
|
170
|
+
BRITISH_THERMAL_UNIT_THERMOCHEMICAL_PER_SECOND_SQUARE_FOOT_DEGREE_FAHRENHEIT = ("Btuth/(s·ft²·ºF)", 5125943)
|
|
171
171
|
BRITISH_THERMAL_UNIT_THERMOCHEMICAL_PER_SQUARE_FOOT = ("Btuth/ft²", 5255992)
|
|
172
172
|
BRITISH_THERMAL_UNIT_THERMOCHEMICAL_PER_SQUARE_FOOT_HOUR = ("Btuth/(ft²·h)", 5125425)
|
|
173
|
-
BRITISH_THERMAL_UNIT_THERMOCHEMICAL_PER_SQUARE_FOOT_MINUTE = ("Btuth/(ft²·min)
|
|
173
|
+
BRITISH_THERMAL_UNIT_THERMOCHEMICAL_PER_SQUARE_FOOT_MINUTE = ("Btuth/(ft²·min)", 5125426)
|
|
174
174
|
BRITISH_THERMAL_UNIT_THERMOCHEMICAL_PER_SQUARE_FOOT_SECOND = ("Btuth/(ft²·s)", 5125428)
|
|
175
175
|
BRUSH = ("brush", 16968)
|
|
176
176
|
BTU_PER_CUBIC_FOOT = ("BTU/ft³", 16944)
|
|
@@ -261,7 +261,7 @@ class Unit(BaseUnit):
|
|
|
261
261
|
CENTIPOISE_PER_BAR = ("cP/bar", 4863796)
|
|
262
262
|
CENTIPOISE_PER_KELVIN = ("cP/K", 4863795)
|
|
263
263
|
CENTISTOKES = ("cSt", 13379)
|
|
264
|
-
CHAIN_BASED_ON_U_S_SURVEY_FOOT = ("ch (US survey)
|
|
264
|
+
CHAIN_BASED_ON_U_S_SURVEY_FOOT = ("ch (US survey)", 5059641)
|
|
265
265
|
CHEST = ("chest", 23090)
|
|
266
266
|
CHEVAL_VAPEUR = ("CV", 4272693)
|
|
267
267
|
CIRCULAR_MIL = ("cmil", 5059639)
|
|
@@ -562,7 +562,7 @@ class Unit(BaseUnit):
|
|
|
562
562
|
FOOT_POUND_FORCE_PER_MINUTE = ("ft·lbf/min", 4927798)
|
|
563
563
|
FOOT_POUND_FORCE_PER_SECOND = ("ft·lbf/s", 4273972)
|
|
564
564
|
FOOT_TO_THE_FOURTH_POWER = ("ft⁴", 5124663)
|
|
565
|
-
FOOT_U_S_SURVEY = ("ft (US survey)
|
|
565
|
+
FOOT_U_S_SURVEY = ("ft (US survey)", 5059889)
|
|
566
566
|
FORMAZIN_NEPHELOMETRIC_UNIT = ("FNU", 4607573)
|
|
567
567
|
FORTY_FOOT_CONTAINER = ("forty foot container", 12849)
|
|
568
568
|
FOUR_PACK = ("four pack", 20532)
|
|
@@ -1235,7 +1235,7 @@ class Unit(BaseUnit):
|
|
|
1235
1235
|
MICROWATT_PER_SQUARE_METRE = ("µW/m²", 4470837)
|
|
1236
1236
|
MICRO_INCH = ("µin", 19767)
|
|
1237
1237
|
MIL = ("mil", 5059635)
|
|
1238
|
-
MILE_BASED_ON_U_S_SURVEY_FOOT = ("mi (US survey)
|
|
1238
|
+
MILE_BASED_ON_U_S_SURVEY_FOOT = ("mi (US survey)", 5059890)
|
|
1239
1239
|
MILE_PER_HOUR_STATUTE_MILE = ("mile/h", 18509)
|
|
1240
1240
|
MILE_PER_MINUTE = ("mi/min", 5059895)
|
|
1241
1241
|
MILE_PER_SECOND = ("mi/s", 5059896)
|
|
@@ -1297,7 +1297,7 @@ class Unit(BaseUnit):
|
|
|
1297
1297
|
MILLIHENRY = ("mH", 4403508)
|
|
1298
1298
|
MILLIHENRY_PER_KILOOHM = ("mH/kΩ", 4730933)
|
|
1299
1299
|
MILLIHENRY_PER_OHM = ("mH/Ω", 4730934)
|
|
1300
|
-
MILLIHERTZ = ("mHz
|
|
1300
|
+
MILLIHERTZ = ("mHz", 5067866)
|
|
1301
1301
|
MILLIJOULE = ("mJ", 4403509)
|
|
1302
1302
|
MILLILITRE = ("ml", 5065812)
|
|
1303
1303
|
MILLILITRE_OF_WATER = ("millilitre of water", 22359)
|
|
@@ -1487,7 +1487,7 @@ class Unit(BaseUnit):
|
|
|
1487
1487
|
OERSTED = ("Oe", 13878)
|
|
1488
1488
|
OHM = ("Ω", 5195853)
|
|
1489
1489
|
OHM_CENTIMETRE = ("Ω·cm", 4404784)
|
|
1490
|
-
OHM_CIRCULAR_MIL_PER_FOOT = ("Ω·cmil/ft
|
|
1490
|
+
OHM_CIRCULAR_MIL_PER_FOOT = ("Ω·cmil/ft", 5255731)
|
|
1491
1491
|
OHM_KILOMETRE = ("Ω·km", 5059124)
|
|
1492
1492
|
OHM_METRE = ("Ω·m", 4404785)
|
|
1493
1493
|
OHM_PER_KILOMETRE = ("Ω/km", 4601142)
|
|
@@ -1598,8 +1598,8 @@ class Unit(BaseUnit):
|
|
|
1598
1598
|
PERCENT_PER_VOLT = ("%/V", 4733237)
|
|
1599
1599
|
PERCENT_VOLUME = ("percent volume", 22096)
|
|
1600
1600
|
PERCENT_WEIGHT = ("percent weight", 13872)
|
|
1601
|
-
PERM_0_C = ("perm (0 ºC)
|
|
1602
|
-
PERM_23_C = ("perm (23 ºC)
|
|
1601
|
+
PERM_0_C = ("perm (0 ºC)", 5257521)
|
|
1602
|
+
PERM_23_C = ("perm (23 ºC)", 5257522)
|
|
1603
1603
|
PERSON = ("person", 18757)
|
|
1604
1604
|
PER_MILLE_PER_PSI = ("‰/psi", 4862258)
|
|
1605
1605
|
PETABIT = ("Pbit", 4536120)
|
|
@@ -2114,7 +2114,7 @@ class Unit(BaseUnit):
|
|
|
2114
2114
|
UNIT_15_C_CALORIE = ("cal₁₅", 16689)
|
|
2115
2115
|
UNIT_30_DAY_MONTH = ("mo (30 days)", 5059382)
|
|
2116
2116
|
UNIT_8_PART_CLOUD_COVER = ("8-part cloud cover", 4273465)
|
|
2117
|
-
UNIT_POLE = ("unit pole
|
|
2117
|
+
UNIT_POLE = ("unit pole", 5256499)
|
|
2118
2118
|
USAGE_PER_TELECOMMUNICATION_LINE_AVERAGE = ("usage per telecommunication line average", 21830)
|
|
2119
2119
|
USE = ("use", 4535605)
|
|
2120
2120
|
US_GALLON_PER_MINUTE = ("gal (US) /min", 18226)
|
|
@@ -108,7 +108,7 @@ def _parse(path: Path) -> dict[str, _UneceUnit]:
|
|
|
108
108
|
|
|
109
109
|
unit = _UneceUnit(
|
|
110
110
|
name=name,
|
|
111
|
-
symbol=str(symbol),
|
|
111
|
+
symbol=str(symbol).replace("\xa0", " ").strip(), # replace non-breaking space with space,
|
|
112
112
|
common_code=str(common_code),
|
|
113
113
|
level=str(level),
|
|
114
114
|
)
|
|
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
|
|
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
|