sysml 0.1.0__py3-none-win_amd64.whl
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.
- sysml/__init__.py +5 -0
- sysml/_native/RUST-STANDARD-LIBRARY-NOTICES.html +29357 -0
- sysml/_native/THIRD-PARTY-NOTICES.txt +1102 -0
- sysml/_native/sysmlv2_abi.dll +0 -0
- sysml/base.py +358 -0
- sysml/classes.py +14291 -0
- sysml/classes.pyi +13769 -0
- sysml/library.py +151 -0
- sysml/stdlib/Domain Libraries/Analysis/.meta.json +10 -0
- sysml/stdlib/Domain Libraries/Analysis/.project.json +27 -0
- sysml/stdlib/Domain Libraries/Analysis/AnalysisTooling.sysml +34 -0
- sysml/stdlib/Domain Libraries/Analysis/SampledFunctions.sysml +119 -0
- sysml/stdlib/Domain Libraries/Analysis/StateSpaceRepresentation.sysml +143 -0
- sysml/stdlib/Domain Libraries/Analysis/TradeStudies.sysml +171 -0
- sysml/stdlib/Domain Libraries/Cause and Effect/.meta.json +8 -0
- sysml/stdlib/Domain Libraries/Cause and Effect/.project.json +23 -0
- sysml/stdlib/Domain Libraries/Cause and Effect/CausationConnections.sysml +83 -0
- sysml/stdlib/Domain Libraries/Cause and Effect/CauseAndEffect.sysml +81 -0
- sysml/stdlib/Domain Libraries/Geometry/.meta.json +8 -0
- sysml/stdlib/Domain Libraries/Geometry/.project.json +27 -0
- sysml/stdlib/Domain Libraries/Geometry/ShapeItems.sysml +899 -0
- sysml/stdlib/Domain Libraries/Geometry/SpatialItems.sysml +168 -0
- sysml/stdlib/Domain Libraries/Metadata/.meta.json +10 -0
- sysml/stdlib/Domain Libraries/Metadata/.project.json +19 -0
- sysml/stdlib/Domain Libraries/Metadata/ImageMetadata.sysml +78 -0
- sysml/stdlib/Domain Libraries/Metadata/ModelingMetadata.sysml +143 -0
- sysml/stdlib/Domain Libraries/Metadata/ParametersOfInterestMetadata.sysml +39 -0
- sysml/stdlib/Domain Libraries/Metadata/RiskMetadata.sysml +100 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/.meta.json +30 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/.project.json +23 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQ.sysml +42 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQAcoustics.sysml +439 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQAtomicNuclear.sysml +2726 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQBase.sysml +206 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQCharacteristicNumbers.sysml +1991 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQChemistryMolecular.sysml +1353 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQCondensedMatter.sysml +1223 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQElectromagnetism.sysml +2333 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQInformation.sysml +958 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQLight.sysml +1537 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQMechanics.sysml +1564 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQSpaceTime.sysml +1169 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/ISQThermodynamics.sysml +1256 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/MeasurementRefCalculations.sysml +30 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/MeasurementReferences.sysml +526 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/Quantities.sysml +107 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/QuantityCalculations.sysml +70 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/SI.sysml +378 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/SIPrefixes.sysml +48 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/TensorCalculations.sysml +50 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/Time.sysml +274 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/USCustomaryUnits.sysml +260 -0
- sysml/stdlib/Domain Libraries/Quantities and Units/VectorCalculations.sysml +62 -0
- sysml/stdlib/Domain Libraries/Requirement Derivation/.meta.json +8 -0
- sysml/stdlib/Domain Libraries/Requirement Derivation/.project.json +19 -0
- sysml/stdlib/Domain Libraries/Requirement Derivation/DerivationConnections.sysml +63 -0
- sysml/stdlib/Domain Libraries/Requirement Derivation/RequirementDerivation.sysml +39 -0
- sysml/stdlib/Kernel Libraries/Kernel Data Type Library/.meta.json +9 -0
- sysml/stdlib/Kernel Libraries/Kernel Data Type Library/.project.json +11 -0
- sysml/stdlib/Kernel Libraries/Kernel Data Type Library/Collections.kerml +177 -0
- sysml/stdlib/Kernel Libraries/Kernel Data Type Library/ScalarValues.kerml +23 -0
- sysml/stdlib/Kernel Libraries/Kernel Data Type Library/VectorValues.kerml +64 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/.meta.json +23 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/.project.json +15 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/BaseFunctions.kerml +80 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/BooleanFunctions.kerml +22 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/CollectionFunctions.kerml +68 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/ComplexFunctions.kerml +47 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/ControlFunctions.kerml +117 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/DataFunctions.kerml +43 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/IntegerFunctions.kerml +43 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/NaturalFunctions.kerml +27 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/NumericalFunctions.kerml +43 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/OccurrenceFunctions.kerml +154 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/RationalFunctions.kerml +49 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/RealFunctions.kerml +56 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/ScalarFunctions.kerml +33 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/SequenceFunctions.kerml +111 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/StringFunctions.kerml +25 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/TrigFunctions.kerml +35 -0
- sysml/stdlib/Kernel Libraries/Kernel Function Library/VectorFunctions.kerml +273 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/.meta.json +22 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/.project.json +15 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/Base.kerml +95 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/Clocks.kerml +156 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/ControlPerformances.kerml +135 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/FeatureReferencingPerformances.kerml +190 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/KerML.kerml +483 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/Links.kerml +67 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/Metaobjects.kerml +58 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/Objects.kerml +212 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/Observation.kerml +161 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/Occurrences.kerml +992 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/Performances.kerml +293 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/SpatialFrames.kerml +197 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/StatePerformances.kerml +145 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/Transfers.kerml +281 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/TransitionPerformances.kerml +66 -0
- sysml/stdlib/Kernel Libraries/Kernel Semantic Library/Triggers.kerml +188 -0
- sysml/stdlib/LICENSE +277 -0
- sysml/stdlib/NOTICE +27 -0
- sysml/stdlib/Systems Library/.meta.json +27 -0
- sysml/stdlib/Systems Library/.project.json +19 -0
- sysml/stdlib/Systems Library/Actions.sysml +557 -0
- sysml/stdlib/Systems Library/Allocations.sysml +29 -0
- sysml/stdlib/Systems Library/AnalysisCases.sysml +38 -0
- sysml/stdlib/Systems Library/Attributes.sysml +25 -0
- sysml/stdlib/Systems Library/Calculations.sysml +37 -0
- sysml/stdlib/Systems Library/Cases.sysml +71 -0
- sysml/stdlib/Systems Library/Connections.sysml +60 -0
- sysml/stdlib/Systems Library/Constraints.sysml +44 -0
- sysml/stdlib/Systems Library/Flows.sysml +126 -0
- sysml/stdlib/Systems Library/Interfaces.sysml +89 -0
- sysml/stdlib/Systems Library/Items.sysml +153 -0
- sysml/stdlib/Systems Library/Metadata.sysml +32 -0
- sysml/stdlib/Systems Library/Parts.sysml +81 -0
- sysml/stdlib/Systems Library/Ports.sysml +54 -0
- sysml/stdlib/Systems Library/Requirements.sysml +194 -0
- sysml/stdlib/Systems Library/StandardViewDefinitions.sysml +123 -0
- sysml/stdlib/Systems Library/States.sysml +103 -0
- sysml/stdlib/Systems Library/SysML.sysml +539 -0
- sysml/stdlib/Systems Library/UseCases.sysml +57 -0
- sysml/stdlib/Systems Library/VerificationCases.sysml +103 -0
- sysml/stdlib/Systems Library/Views.sysml +164 -0
- sysml/toolkit.py +373 -0
- sysml/toolkit_table.py +665 -0
- sysml-0.1.0.dist-info/METADATA +87 -0
- sysml-0.1.0.dist-info/RECORD +134 -0
- sysml-0.1.0.dist-info/WHEEL +5 -0
- sysml-0.1.0.dist-info/licenses/LICENSE +202 -0
- sysml-0.1.0.dist-info/licenses/NOTICE +7 -0
- sysml-0.1.0.dist-info/licenses/stdlib/LICENSE +277 -0
- sysml-0.1.0.dist-info/licenses/stdlib/NOTICE +27 -0
- sysml-0.1.0.dist-info/top_level.txt +1 -0
|
Binary file
|
sysml/base.py
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"""Runtime for the generated SDK: element base class, property
|
|
2
|
+
descriptors, the Model entry point, and the payload backend.
|
|
3
|
+
|
|
4
|
+
Design contract: generated classes never see a backend directly —
|
|
5
|
+
every property access routes through Model._backend.get(). A property
|
|
6
|
+
read returns whatever the backend gave: the SysML Toolkit reports its
|
|
7
|
+
own unimplemented members, so the SDK never second-guesses a result.
|
|
8
|
+
|
|
9
|
+
Collision rule (Python backend): every public runtime member on Element
|
|
10
|
+
contains an underscore (element_id, backend_handle, metaclass_name,
|
|
11
|
+
get_raw). Spec property and operation names are strict lowerCamelCase
|
|
12
|
+
and can never contain one, so a generated descriptor can never shadow a
|
|
13
|
+
runtime member. tools/gen_classes.py enforces the invariant at
|
|
14
|
+
generation time.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import Any, Iterable, Optional
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SdkError(Exception):
|
|
23
|
+
"""Base of all SDK-specific errors."""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class NotComputed(SdkError):
|
|
27
|
+
"""A property the backend reports it does not compute.
|
|
28
|
+
|
|
29
|
+
Reserved for a backend that says so itself; the SDK never infers it
|
|
30
|
+
from an empty result.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class NotImplementedInToolkit(SdkError):
|
|
35
|
+
"""A specification member the SysML Toolkit does not answer: raised
|
|
36
|
+
when the SysML Toolkit reports the member as not implemented, and for
|
|
37
|
+
every operation on a payload model."""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ReadOnly(SdkError):
|
|
41
|
+
"""Edit attempted on a read-only backend (payload-backed model)."""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class Gone(SdkError):
|
|
45
|
+
"""The element no longer exists in the backend's current state."""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class UnresolvedReference(SdkError):
|
|
49
|
+
"""A reference that did not resolve — a SysML Toolkit `@ref`
|
|
50
|
+
spelling passthrough (non-standard, best-effort) or a dangling `@id`.
|
|
51
|
+
|
|
52
|
+
The SDK requires resolved models: typed navigation throws instead of
|
|
53
|
+
yielding placeholder objects. The
|
|
54
|
+
message carries everything known about the reference; `get_raw()`
|
|
55
|
+
still exposes the raw value for forensics.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _is_id_ref(v: Any) -> bool:
|
|
60
|
+
return isinstance(v, dict) and set(v.keys()) == {"@id"}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class P:
|
|
64
|
+
"""Descriptor for one spec property (generated classes declare these).
|
|
65
|
+
|
|
66
|
+
shape: A=array, B=boolean, N=nullable, R=required ref, S/E=scalar.
|
|
67
|
+
derived: the XMI derived flag (spec information, not a promise
|
|
68
|
+
about what any particular backend computes).
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
__slots__ = ("name", "shape", "derived", "symbol", "code")
|
|
72
|
+
|
|
73
|
+
def __init__(self, name: str, shape: str, derived: bool, symbol: str = "", code: str = ""):
|
|
74
|
+
self.name = name
|
|
75
|
+
self.shape = shape
|
|
76
|
+
self.derived = derived
|
|
77
|
+
# Static dispatch data, resolved at generation time for the declaring class:
|
|
78
|
+
# the binding library function that answers this member and its result shape. A backend
|
|
79
|
+
# that routes by name (the payload one) ignores them.
|
|
80
|
+
self.symbol = symbol
|
|
81
|
+
self.code = code
|
|
82
|
+
|
|
83
|
+
def __set_name__(self, owner: type, attr: str) -> None:
|
|
84
|
+
if attr != self.name: # generated code always matches; guard anyway
|
|
85
|
+
self.name = attr
|
|
86
|
+
|
|
87
|
+
def __get__(self, obj: Optional["Element"], objtype: type | None = None):
|
|
88
|
+
if obj is None:
|
|
89
|
+
return self
|
|
90
|
+
model = obj._model
|
|
91
|
+
raw = model._backend.read(obj._handle, self)
|
|
92
|
+
if raw is None and self.shape == "A":
|
|
93
|
+
return [] # absent arrays normalize to empty (typed-surface rule)
|
|
94
|
+
return _wrap(model, raw, obj, self.name)
|
|
95
|
+
|
|
96
|
+
def __set__(self, obj: "Element", value: Any) -> None:
|
|
97
|
+
raise ReadOnly(
|
|
98
|
+
f"{type(obj).__name__}.{self.name}: property assignment requires an "
|
|
99
|
+
f"edit transaction on a live backend (payload models are read-only)"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _wrap(model: "Model", raw: Any, owner: "Element" = None, prop: str = "?"):
|
|
104
|
+
def _at() -> str:
|
|
105
|
+
if owner is None:
|
|
106
|
+
return prop
|
|
107
|
+
return f"{type(owner).__name__}.{prop} (element {owner._handle})"
|
|
108
|
+
|
|
109
|
+
if _is_id_ref(raw):
|
|
110
|
+
try:
|
|
111
|
+
return model.element(raw["@id"])
|
|
112
|
+
except Gone:
|
|
113
|
+
raise UnresolvedReference(
|
|
114
|
+
f"dangling reference @id={raw['@id']!r} at {_at()}: target is "
|
|
115
|
+
f"not in this model; the SDK requires resolved models"
|
|
116
|
+
) from None
|
|
117
|
+
if isinstance(raw, dict) and "@ref" in raw:
|
|
118
|
+
raise UnresolvedReference(
|
|
119
|
+
f"unresolved reference {raw['@ref']!r} at {_at()} (the SysML Toolkit's "
|
|
120
|
+
f"@ref passthrough is non-standard best-effort); the SDK requires "
|
|
121
|
+
f"resolved models — use .get_raw({prop!r}) for the raw value"
|
|
122
|
+
)
|
|
123
|
+
if isinstance(raw, list):
|
|
124
|
+
return [_wrap(model, v, owner, prop) for v in raw]
|
|
125
|
+
return raw
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class Op:
|
|
129
|
+
"""A spec operation. Carries the same static dispatch data as `P` plus the
|
|
130
|
+
parameter list; the backend decides whether it can be called."""
|
|
131
|
+
|
|
132
|
+
__slots__ = ("name", "params", "symbol", "code", "param_types")
|
|
133
|
+
|
|
134
|
+
def __init__(self, name: str, params: list[str], symbol: str = "", code: str = "",
|
|
135
|
+
param_types: tuple = ()):
|
|
136
|
+
self.name = name
|
|
137
|
+
self.params = params
|
|
138
|
+
self.symbol = symbol
|
|
139
|
+
self.code = code
|
|
140
|
+
self.param_types = param_types
|
|
141
|
+
|
|
142
|
+
def __get__(self, obj, objtype=None):
|
|
143
|
+
if obj is None:
|
|
144
|
+
return self
|
|
145
|
+
op = self
|
|
146
|
+
|
|
147
|
+
def _call(*args):
|
|
148
|
+
model = obj._model
|
|
149
|
+
raw = model._backend.call(obj._handle, op, args)
|
|
150
|
+
if raw is None and op.code == "H":
|
|
151
|
+
return []
|
|
152
|
+
return _wrap(model, raw, obj, op.name)
|
|
153
|
+
|
|
154
|
+
_call.__name__ = self.name
|
|
155
|
+
return _call
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class Element:
|
|
159
|
+
"""Base of every generated metaclass.
|
|
160
|
+
|
|
161
|
+
A wrapper holds (model, backend handle); identity is by the
|
|
162
|
+
backend's stable element id. Payload backends use the
|
|
163
|
+
element id itself as the handle.
|
|
164
|
+
|
|
165
|
+
Public runtime members must contain an underscore (collision rule —
|
|
166
|
+
see the module docstring): the spec property `metaclass` on
|
|
167
|
+
MetadataFeature/MetadataUsage is a generated descriptor like any
|
|
168
|
+
other, so the runtime accessor is spelled `metaclass_name`.
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
__slots__ = ("_model", "_handle")
|
|
172
|
+
|
|
173
|
+
def __init__(self, model: "Model", handle: Any):
|
|
174
|
+
self._model = model
|
|
175
|
+
self._handle = handle
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def element_id(self) -> str:
|
|
179
|
+
"""The element's stable id, via the backend's element_id(handle)."""
|
|
180
|
+
return self._model._backend.element_id(self._handle)
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def backend_handle(self) -> Any:
|
|
184
|
+
"""The backend handle this wrapper holds (= id for payload backends)."""
|
|
185
|
+
return self._handle
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def metaclass_name(self) -> str:
|
|
189
|
+
"""The element's metaclass, as the backend reports it."""
|
|
190
|
+
return self._model._backend.metaclass(self._handle)
|
|
191
|
+
|
|
192
|
+
def get_raw(self, prop: str) -> Any:
|
|
193
|
+
"""Escape hatch: the property's raw backend value, unwrapped."""
|
|
194
|
+
return self._model._backend.get(self._handle, prop)
|
|
195
|
+
|
|
196
|
+
def __eq__(self, other: object) -> bool:
|
|
197
|
+
return (
|
|
198
|
+
isinstance(other, Element)
|
|
199
|
+
and other._model is self._model
|
|
200
|
+
and other.element_id == self.element_id
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
def __hash__(self) -> int:
|
|
204
|
+
return hash(self.element_id)
|
|
205
|
+
|
|
206
|
+
def __repr__(self) -> str:
|
|
207
|
+
qn = self._model._backend.get(self._handle, "qualifiedName")
|
|
208
|
+
label = qn if isinstance(qn, str) and qn else self.element_id
|
|
209
|
+
return f"<{type(self).__name__} {label}>"
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _index(elements: list[dict]) -> tuple[dict[str, dict], dict[str, str]]:
|
|
213
|
+
"""Elements by id (document order, the last of a repeated id) and ids by qualified name (the
|
|
214
|
+
first)."""
|
|
215
|
+
by_id: dict[str, dict] = {}
|
|
216
|
+
by_qname: dict[str, str] = {}
|
|
217
|
+
for e in elements:
|
|
218
|
+
eid = e.get("@id")
|
|
219
|
+
if not isinstance(eid, str):
|
|
220
|
+
continue
|
|
221
|
+
by_id[eid] = e
|
|
222
|
+
qn = e.get("qualifiedName")
|
|
223
|
+
if isinstance(qn, str) and qn:
|
|
224
|
+
by_qname.setdefault(qn, eid)
|
|
225
|
+
return by_id, by_qname
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class PayloadLibrary:
|
|
229
|
+
"""A standard library read from a full-form interchange element array, such as the
|
|
230
|
+
library JSON published with the SDK. Index it once and pass it to any number of payload
|
|
231
|
+
models: their references into the library then resolve by the library's normative ids."""
|
|
232
|
+
|
|
233
|
+
def __init__(self, elements: list[dict]):
|
|
234
|
+
self._by_id, self._by_qname = _index(elements)
|
|
235
|
+
|
|
236
|
+
def __len__(self) -> int:
|
|
237
|
+
return len(self._by_id)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class PayloadBackend:
|
|
241
|
+
"""Read-only backend over a full-form interchange element array.
|
|
242
|
+
|
|
243
|
+
The Backend protocol is defined over opaque per-backend
|
|
244
|
+
element *handles*; an id-keyed backend like this one uses element
|
|
245
|
+
ids as its handles.
|
|
246
|
+
|
|
247
|
+
With a library, an id or qualified name the payload does not hold is looked up in the library;
|
|
248
|
+
the library's elements are not the model's, so `all_handles` lists the payload's only.
|
|
249
|
+
"""
|
|
250
|
+
|
|
251
|
+
def __init__(self, elements: list[dict], library: Optional[PayloadLibrary] = None):
|
|
252
|
+
self._by_id, self._by_qname = _index(elements)
|
|
253
|
+
self._library = library
|
|
254
|
+
|
|
255
|
+
def _require(self, handle: str) -> dict:
|
|
256
|
+
el = self._by_id.get(handle)
|
|
257
|
+
if el is None and self._library is not None:
|
|
258
|
+
el = self._library._by_id.get(handle)
|
|
259
|
+
if el is None:
|
|
260
|
+
raise Gone(f"no element {handle} in this payload")
|
|
261
|
+
return el
|
|
262
|
+
|
|
263
|
+
def get(self, handle: str, prop: str) -> Any:
|
|
264
|
+
return self._require(handle).get(prop)
|
|
265
|
+
|
|
266
|
+
def read(self, handle: str, prop: "P") -> Any:
|
|
267
|
+
return self.get(handle, prop.name)
|
|
268
|
+
|
|
269
|
+
def call(self, handle: str, op: "Op", args: tuple) -> Any:
|
|
270
|
+
raise NotImplementedInToolkit(
|
|
271
|
+
f"{op.name}(): operations are not available on payload models; "
|
|
272
|
+
f"load the model through the SysML Toolkit backend"
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
def metaclass(self, handle: str) -> str:
|
|
276
|
+
return self._require(handle)["@type"]
|
|
277
|
+
|
|
278
|
+
def element_id(self, handle: str) -> str:
|
|
279
|
+
self._require(handle)
|
|
280
|
+
return handle
|
|
281
|
+
|
|
282
|
+
def resolve(self, qualified_name: str) -> Optional[str]:
|
|
283
|
+
handle = self._by_qname.get(qualified_name)
|
|
284
|
+
if handle is None and self._library is not None:
|
|
285
|
+
handle = self._library._by_qname.get(qualified_name)
|
|
286
|
+
return handle
|
|
287
|
+
|
|
288
|
+
def all_handles(self) -> Iterable[str]:
|
|
289
|
+
return self._by_id.keys()
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
class Model:
|
|
293
|
+
"""Entry point: wraps a backend and mints typed wrappers by metaclass."""
|
|
294
|
+
|
|
295
|
+
def __init__(self, backend):
|
|
296
|
+
from . import classes # registry import deferred to avoid a cycle
|
|
297
|
+
|
|
298
|
+
self._backend = backend
|
|
299
|
+
self._registry: dict[str, type] = classes.REGISTRY
|
|
300
|
+
self._cache: dict[str, Element] = {}
|
|
301
|
+
|
|
302
|
+
@classmethod
|
|
303
|
+
def from_full_json(cls, elements: list[dict], library: Optional[PayloadLibrary] = None) -> "Model":
|
|
304
|
+
"""A model read from a full-form interchange element array. With `library`, references
|
|
305
|
+
into the standard library resolve against it; its elements are not listed as the model's."""
|
|
306
|
+
return cls(PayloadBackend(elements, library))
|
|
307
|
+
|
|
308
|
+
@classmethod
|
|
309
|
+
def from_toolkit(cls, *paths: "str | os.PathLike", sources: dict[str, str] | None = None,
|
|
310
|
+
library_dir: "str | os.PathLike | None" = None) -> "Model":
|
|
311
|
+
"""A model read directly from the SysML Toolkit through the binding library (abi/)."""
|
|
312
|
+
from .toolkit import ToolkitBackend # deferred: ctypes and the library load on demand
|
|
313
|
+
|
|
314
|
+
return cls(ToolkitBackend.open(paths, sources=sources, library_dir=library_dir))
|
|
315
|
+
|
|
316
|
+
def element(self, handle) -> Element:
|
|
317
|
+
w = self._cache.get(handle)
|
|
318
|
+
if w is None:
|
|
319
|
+
mc = self._backend.metaclass(handle) # raises Gone if absent
|
|
320
|
+
klass = self._registry.get(mc, Element)
|
|
321
|
+
w = klass(self, handle)
|
|
322
|
+
self._cache[handle] = w
|
|
323
|
+
return w
|
|
324
|
+
|
|
325
|
+
def resolve(self, qualified_name: str) -> Optional[Element]:
|
|
326
|
+
handle = self._backend.resolve(qualified_name)
|
|
327
|
+
return None if handle is None else self.element(handle)
|
|
328
|
+
|
|
329
|
+
def all(self) -> list[Element]:
|
|
330
|
+
"""Every element of the model (a payload's library elements are not the model's)."""
|
|
331
|
+
return [self.element(h) for h in self._backend.all_handles()]
|
|
332
|
+
|
|
333
|
+
def elements_of_type(self, klass, *, exact: bool = False) -> list[Element]:
|
|
334
|
+
if isinstance(klass, str):
|
|
335
|
+
klass = self._registry[klass]
|
|
336
|
+
out = []
|
|
337
|
+
for h in self._backend.all_handles():
|
|
338
|
+
w = self.element(h)
|
|
339
|
+
ok = type(w) is klass if exact else isinstance(w, klass)
|
|
340
|
+
if ok:
|
|
341
|
+
out.append(w)
|
|
342
|
+
return out
|
|
343
|
+
|
|
344
|
+
@property
|
|
345
|
+
def roots(self) -> list[Element]:
|
|
346
|
+
"""Top-level namespaces. Ownerless alone is not enough: the
|
|
347
|
+
SysML Toolkit serializes memberships with owner: null (as in
|
|
348
|
+
data/bigger.full.json), so non-namespace ownerless elements are
|
|
349
|
+
excluded."""
|
|
350
|
+
from .classes import Namespace # deferred: avoids import cycle
|
|
351
|
+
|
|
352
|
+
return [
|
|
353
|
+
w
|
|
354
|
+
for h in self._backend.all_handles()
|
|
355
|
+
if not self._backend.get(h, "owner")
|
|
356
|
+
for w in [self.element(h)]
|
|
357
|
+
if isinstance(w, Namespace)
|
|
358
|
+
]
|