sysml2kit 0.0.1__tar.gz → 0.2.0__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.
- sysml2kit-0.2.0/CHANGELOG.md +55 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/PKG-INFO +23 -6
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/README.md +20 -5
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/SPEC.md +21 -0
- sysml2kit-0.2.0/docs/api-client.md +28 -0
- sysml2kit-0.2.0/docs/backends.md +39 -0
- sysml2kit-0.2.0/docs/cli.md +24 -0
- sysml2kit-0.2.0/docs/concepts.md +46 -0
- sysml2kit-0.2.0/docs/index.md +24 -0
- sysml2kit-0.2.0/docs/interchange.md +31 -0
- sysml2kit-0.2.0/docs/mcp.md +34 -0
- sysml2kit-0.2.0/docs/quickstart.md +47 -0
- sysml2kit-0.2.0/docs/reference.md +31 -0
- sysml2kit-0.2.0/docs/rf-library.md +33 -0
- sysml2kit-0.2.0/docs/traceability.md +47 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/mkdocs.yml +10 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/pyproject.toml +18 -2
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/__init__.py +5 -3
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/_version.py +2 -2
- sysml2kit-0.2.0/src/sysml2kit/api/__init__.py +7 -0
- sysml2kit-0.2.0/src/sysml2kit/api/client.py +120 -0
- sysml2kit-0.2.0/src/sysml2kit/api/errors.py +12 -0
- sysml2kit-0.2.0/src/sysml2kit/api/models.py +36 -0
- sysml2kit-0.2.0/src/sysml2kit/backends/__init__.py +31 -0
- sysml2kit-0.2.0/src/sysml2kit/backends/protocol.py +38 -0
- sysml2kit-0.2.0/src/sysml2kit/backends/sysmlpy.py +445 -0
- sysml2kit-0.2.0/src/sysml2kit/cli.py +232 -0
- sysml2kit-0.2.0/src/sysml2kit/diff.py +106 -0
- sysml2kit-0.2.0/src/sysml2kit/graph.py +36 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/interchange/reader.py +2 -2
- sysml2kit-0.2.0/src/sysml2kit/interop/__init__.py +5 -0
- sysml2kit-0.2.0/src/sysml2kit/interop/requirements.py +113 -0
- sysml2kit-0.2.0/src/sysml2kit/mcp/__init__.py +1 -0
- sysml2kit-0.2.0/src/sysml2kit/mcp/_common.py +23 -0
- sysml2kit-0.2.0/src/sysml2kit/mcp/server.py +57 -0
- sysml2kit-0.2.0/src/sysml2kit/mcp/tools_model.py +240 -0
- sysml2kit-0.2.0/src/sysml2kit/mcp/tools_requirements.py +76 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/container.py +8 -0
- sysml2kit-0.2.0/src/sysml2kit/query.py +133 -0
- sysml2kit-0.2.0/src/sysml2kit/text/__init__.py +5 -0
- sysml2kit-0.2.0/src/sysml2kit/text/keywords.py +52 -0
- sysml2kit-0.2.0/src/sysml2kit/text/writer.py +179 -0
- sysml2kit-0.2.0/src/sysml2kit/validation.py +186 -0
- sysml2kit-0.2.0/src/sysml2kit/views.py +92 -0
- sysml2kit-0.2.0/src/sysml2kit/workspace.py +22 -0
- sysml2kit-0.2.0/tests/conftest.py +46 -0
- sysml2kit-0.2.0/tests/fixtures/RFParts.sysml +36 -0
- sysml2kit-0.2.0/tests/fixtures/RFRequirements.sysml +33 -0
- sysml2kit-0.2.0/tests/fixtures/SatcomTerminal28GHz.sysml +109 -0
- sysml2kit-0.2.0/tests/fixtures/vehicle.sysml +27 -0
- sysml2kit-0.2.0/tests/test_api_client.py +87 -0
- sysml2kit-0.2.0/tests/test_backend_fidelity.py +172 -0
- sysml2kit-0.2.0/tests/test_backend_sysmlpy.py +54 -0
- sysml2kit-0.2.0/tests/test_cli.py +87 -0
- sysml2kit-0.2.0/tests/test_cli_fmt.py +99 -0
- sysml2kit-0.2.0/tests/test_diff.py +61 -0
- sysml2kit-0.2.0/tests/test_interchange.py +56 -0
- sysml2kit-0.2.0/tests/test_interop.py +104 -0
- sysml2kit-0.2.0/tests/test_mcp.py +111 -0
- sysml2kit-0.2.0/tests/test_model.py +105 -0
- sysml2kit-0.2.0/tests/test_query.py +59 -0
- sysml2kit-0.2.0/tests/test_roundtrip_json.py +45 -0
- sysml2kit-0.2.0/tests/test_roundtrip_text.py +44 -0
- sysml2kit-0.2.0/tests/test_text_writer/test_vehicle_golden.sysml +27 -0
- sysml2kit-0.2.0/tests/test_text_writer.py +51 -0
- sysml2kit-0.2.0/tests/test_validation.py +82 -0
- sysml2kit-0.2.0/tests/test_values_units.py +42 -0
- sysml2kit-0.2.0/tests/test_views/test_trace_contains_all_edge_kinds.trace.mmd +9 -0
- sysml2kit-0.2.0/tests/test_views/test_tree_contains_hierarchy.tree.mmd +10 -0
- sysml2kit-0.2.0/tests/test_views.py +37 -0
- sysml2kit-0.2.0/tests/test_workspace.py +24 -0
- sysml2kit-0.2.0/tools/conformance/run_oracle.py +100 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/uv.lock +492 -2
- sysml2kit-0.0.1/CHANGELOG.md +0 -12
- sysml2kit-0.0.1/docs/index.md +0 -19
- sysml2kit-0.0.1/src/sysml2kit/cli.py +0 -26
- sysml2kit-0.0.1/tools/conformance/run_oracle.py +0 -70
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/.gitignore +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/.pre-commit-config.yaml +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/.python-version +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/CITATION.cff +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/CLAUDE.md +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/CONTRIBUTING.md +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/LICENSE +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/NOTICE +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/SECURITY.md +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/scripts/slopcheck.sh +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/interchange/__init__.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/interchange/typemap.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/interchange/writer.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/__init__.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/analysis.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/base.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/builder.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/metadata.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/relations.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/requirements.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/structure.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/values.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/py.typed +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/units.py +0 -0
- {sysml2kit-0.0.1 → sysml2kit-0.2.0}/tests/test_package.py +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0 — 2026-08-21
|
|
4
|
+
|
|
5
|
+
- **Parse fidelity**: the sysmlpy backend now walks the raw ANTLR dict
|
|
6
|
+
(`load_grammar_antlr`) instead of the lossy wrapper objects. Short names,
|
|
7
|
+
feature typing (incl. cross-package), multiplicity, attribute values with
|
|
8
|
+
units, requirement subjects and text, docs, and satisfy statements survive
|
|
9
|
+
a text parse. Upstream visitor losses (dependency statements, allocate and
|
|
10
|
+
connect endpoints, verification cases) are pinned by tests, documented in
|
|
11
|
+
SPEC.md, and filed upstream (sysmlpy #4, #5).
|
|
12
|
+
- **MCP server** (`pip install sysml2kit[mcp]`; `sysml2kit mcp serve`):
|
|
13
|
+
eight tools — model_show, model_validate, model_diff, model_export,
|
|
14
|
+
model_diagram, requirements_trace, requirements_extract, library_load.
|
|
15
|
+
- **`fmt` command** with a loss-refusing safety gate (grammar-signature and
|
|
16
|
+
model-diff comparison; `--lossy` to override, `--check` for CI).
|
|
17
|
+
- **Mermaid views** (`sysml2kit.views`): ownership tree and requirement
|
|
18
|
+
trace diagrams; `export --to mermaid` and the model_diagram tool.
|
|
19
|
+
- **Conformance oracle** pinned to windtrader-java 0.1.1 (sha256-verified,
|
|
20
|
+
out-of-process pilot parser); weekly workflow green.
|
|
21
|
+
- Downstream bridges landed as PRs: phased-array-systems#1 (op-form
|
|
22
|
+
RequirementSet) and aedl#1 (bound-form requirements); the RequirementSpec
|
|
23
|
+
field set is now frozen by a schema test.
|
|
24
|
+
|
|
25
|
+
## 0.1.0 — 2026-08-21
|
|
26
|
+
|
|
27
|
+
First working release.
|
|
28
|
+
|
|
29
|
+
- Object model: the pragmatic profile (~20 element kinds) as pydantic
|
|
30
|
+
classes, `Model` container with identity/ownership/qualified names,
|
|
31
|
+
`assign_stable_ids()` (UUIDv5), fluent builder API, `AttributeValue` with
|
|
32
|
+
unit text and provenance, pint-backed unit helpers.
|
|
33
|
+
- JSON interchange: Systems Modeling API serialization reader/writer,
|
|
34
|
+
deterministic output, `OpaqueElement` passthrough for unknown `@type`s;
|
|
35
|
+
json→model→json fixpoint property-tested.
|
|
36
|
+
- Textual notation writer: deterministic `.sysml` output; verified against
|
|
37
|
+
the sysmlpy parser (write → parse → structural compare).
|
|
38
|
+
- Traceability queries: satisfied_by/verified_by/derived_from,
|
|
39
|
+
unsatisfied/unverified requirements, allocation table, trace matrix.
|
|
40
|
+
- Validation: rules S2K001–S2K009 with severities and stable ids.
|
|
41
|
+
- Diff: element-level with `--by-name` matching for regenerated ids.
|
|
42
|
+
- API client: hand-written httpx client for the Systems Modeling API
|
|
43
|
+
(projects/branches/commits/elements reads, create_project, push_model).
|
|
44
|
+
- Parser backends: `ParserBackend` protocol; sysmlpy adapter behind the
|
|
45
|
+
`parse` extra.
|
|
46
|
+
- Interop: `extract_requirements` reading the metricKey convention, with
|
|
47
|
+
dual-form thresholds for operator-style and bound-style engines.
|
|
48
|
+
- CLI: `show` (`--traceability`), `validate`, `diff`, `export`
|
|
49
|
+
(`--stable-ids`), `version`.
|
|
50
|
+
- Docs site, conformance-oracle workflow scaffold, prose lint tooling.
|
|
51
|
+
|
|
52
|
+
## 0.0.1 — 2026-08-21
|
|
53
|
+
|
|
54
|
+
- Package skeleton published to claim the PyPI name. Importable, no usable
|
|
55
|
+
functionality yet.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sysml2kit
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: API-first Python tooling for building, querying, validating, and automating SysML v2 models
|
|
5
5
|
Project-URL: Homepage, https://github.com/jman4162/sysml2kit
|
|
6
6
|
Project-URL: Source, https://github.com/jman4162/sysml2kit
|
|
@@ -30,6 +30,8 @@ Requires-Dist: pydantic>=2.7
|
|
|
30
30
|
Requires-Dist: typer>=0.12
|
|
31
31
|
Provides-Extra: graph
|
|
32
32
|
Requires-Dist: networkx>=3.2; extra == 'graph'
|
|
33
|
+
Provides-Extra: mcp
|
|
34
|
+
Requires-Dist: mcp<2,>=1.26; extra == 'mcp'
|
|
33
35
|
Provides-Extra: parse
|
|
34
36
|
Requires-Dist: sysmlpy<0.37,>=0.36.2; extra == 'parse'
|
|
35
37
|
Description-Content-Type: text/markdown
|
|
@@ -44,8 +46,10 @@ Description-Content-Type: text/markdown
|
|
|
44
46
|
API-first Python tooling for building, querying, validating, and automating
|
|
45
47
|
SysML v2 models.
|
|
46
48
|
|
|
47
|
-
> **Status: pre-alpha.** The 0.
|
|
48
|
-
>
|
|
49
|
+
> **Status: pre-alpha.** The 0.1.x line has a working core (model, writer,
|
|
50
|
+
> interchange, queries, validation, diff, API client, parse backend); the API
|
|
51
|
+
> may still move between minor versions. Pin an exact version if you depend
|
|
52
|
+
> on it.
|
|
49
53
|
|
|
50
54
|
`sysml2kit` is the requirements/architecture/traceability layer for
|
|
51
55
|
engineering automation stacks: build a system model in Python, emit standard
|
|
@@ -131,9 +135,22 @@ SysML v2 model library consumed through this package.
|
|
|
131
135
|
|
|
132
136
|
## For agents
|
|
133
137
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
`
|
|
138
|
+
An MCP server ships behind the `mcp` extra with eight tools: `model_show`,
|
|
139
|
+
`model_validate`, `model_diff`, `model_export`, `model_diagram`,
|
|
140
|
+
`requirements_trace`, `requirements_extract`, `library_load`. Artifacts are
|
|
141
|
+
returned as file paths, not payloads.
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
pip install "sysml2kit[mcp,parse]"
|
|
145
|
+
sysml2kit mcp serve # stdio; --transport http also supported
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{"mcpServers": {"sysml2kit": {"command": "sysml2kit", "args": ["mcp", "serve"]}}}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The CLI (`sysml2kit show | validate | diff | export | fmt`) covers the same
|
|
153
|
+
operations for shell use.
|
|
137
154
|
|
|
138
155
|
## Development
|
|
139
156
|
|
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
API-first Python tooling for building, querying, validating, and automating
|
|
9
9
|
SysML v2 models.
|
|
10
10
|
|
|
11
|
-
> **Status: pre-alpha.** The 0.
|
|
12
|
-
>
|
|
11
|
+
> **Status: pre-alpha.** The 0.1.x line has a working core (model, writer,
|
|
12
|
+
> interchange, queries, validation, diff, API client, parse backend); the API
|
|
13
|
+
> may still move between minor versions. Pin an exact version if you depend
|
|
14
|
+
> on it.
|
|
13
15
|
|
|
14
16
|
`sysml2kit` is the requirements/architecture/traceability layer for
|
|
15
17
|
engineering automation stacks: build a system model in Python, emit standard
|
|
@@ -95,9 +97,22 @@ SysML v2 model library consumed through this package.
|
|
|
95
97
|
|
|
96
98
|
## For agents
|
|
97
99
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
`
|
|
100
|
+
An MCP server ships behind the `mcp` extra with eight tools: `model_show`,
|
|
101
|
+
`model_validate`, `model_diff`, `model_export`, `model_diagram`,
|
|
102
|
+
`requirements_trace`, `requirements_extract`, `library_load`. Artifacts are
|
|
103
|
+
returned as file paths, not payloads.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
pip install "sysml2kit[mcp,parse]"
|
|
107
|
+
sysml2kit mcp serve # stdio; --transport http also supported
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{"mcpServers": {"sysml2kit": {"command": "sysml2kit", "args": ["mcp", "serve"]}}}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The CLI (`sysml2kit show | validate | diff | export | fmt`) covers the same
|
|
115
|
+
operations for shell use.
|
|
101
116
|
|
|
102
117
|
## Development
|
|
103
118
|
|
|
@@ -46,6 +46,27 @@ not drop elements the profile lacks classes for.
|
|
|
46
46
|
- **Documentation is a field** (`Element.doc`), not an owned `Documentation`
|
|
47
47
|
element; the writer emits `doc /* ... */` bodies.
|
|
48
48
|
|
|
49
|
+
## Text parse fidelity (sysmlpy backend, 0.36.x)
|
|
50
|
+
|
|
51
|
+
The backend parses via ``sysmlpy.load_grammar_antlr`` and walks the raw
|
|
52
|
+
ANTLR dict (the wrapper-object loader rebuilds usage bodies lossily and is
|
|
53
|
+
not used). What survives a text round trip:
|
|
54
|
+
|
|
55
|
+
| Round-trips | Lost upstream (sysmlpy visitor discards it) |
|
|
56
|
+
|---|---|
|
|
57
|
+
| names, short names | `dependency A to B;` statements (how the writer emits verify/derive) |
|
|
58
|
+
| docs (package/part/requirement scope) | `allocate X to Y;` endpoints |
|
|
59
|
+
| feature typing, incl. cross-package | `connect a.pa to b.pb;` endpoints |
|
|
60
|
+
| multiplicity | `verification` case usages (dropped entirely) |
|
|
61
|
+
| attribute values with units | value provenance (`source`/`confidence` have no textual slot) |
|
|
62
|
+
| requirement subject and text | |
|
|
63
|
+
| satisfy (package level and inside part bodies) | |
|
|
64
|
+
|
|
65
|
+
Consequence: **satisfy traceability survives text; verify/derive/allocate
|
|
66
|
+
require the JSON interchange.** The losses are pinned by tests in
|
|
67
|
+
`tests/test_backend_fidelity.py` so an upstream sysmlpy fix surfaces as a
|
|
68
|
+
test failure.
|
|
69
|
+
|
|
49
70
|
## Identity and ownership
|
|
50
71
|
|
|
51
72
|
- Every element has a UUID `element_id`, mapping to the API JSON `@id`.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# API client
|
|
2
|
+
|
|
3
|
+
`sysml2kit.api.SysMLApiClient` is a hand-written httpx client for the OMG
|
|
4
|
+
Systems Modeling API and Services endpoints (the REST binding any conformant
|
|
5
|
+
model server exposes).
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from sysml2kit.api import SysMLApiClient
|
|
9
|
+
|
|
10
|
+
with SysMLApiClient("https://models.example.com", token="…") as client:
|
|
11
|
+
for project in client.list_projects():
|
|
12
|
+
print(project.id, project.name)
|
|
13
|
+
model = client.list_elements(project_id, commit_id) # -> sysml2kit Model
|
|
14
|
+
client.push_model(project_id, model, message="update")
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Covered in v0.1: `list_projects`, `get_project`, `list_branches`,
|
|
18
|
+
`list_commits`, `get_commit`, `get_element`, `list_elements` (returns a
|
|
19
|
+
`Model` via the interchange reader), `create_project`, and `push_model`
|
|
20
|
+
(POSTs a commit whose change set inserts the model's records). Branch
|
|
21
|
+
management and merges are not covered yet.
|
|
22
|
+
|
|
23
|
+
Failures raise `ApiError(status, detail)`. The client sends the bearer token
|
|
24
|
+
to whatever base URL you configure; use HTTPS.
|
|
25
|
+
|
|
26
|
+
Server compatibility note: the pilot API-Services implementation has JSON
|
|
27
|
+
quirks relative to the spec; compatibility is tested best-effort behind the
|
|
28
|
+
`api` pytest marker against a local server, not in default CI.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Parser backends
|
|
2
|
+
|
|
3
|
+
sysml2kit does not implement the SysML v2 grammar. Reading textual notation
|
|
4
|
+
goes through a `ParserBackend` (see `sysml2kit.backends.protocol`):
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
from sysml2kit.backends import get_backend
|
|
8
|
+
|
|
9
|
+
backend = get_backend("sysmlpy")
|
|
10
|
+
model = backend.parse(text)
|
|
11
|
+
model = backend.parse_files([path_a, path_b])
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## The sysmlpy backend
|
|
15
|
+
|
|
16
|
+
`pip install sysml2kit[parse]` installs
|
|
17
|
+
[sysmlpy](https://github.com/mycr0ft/sysmlpy) (MIT, ANTLR4-based). The
|
|
18
|
+
backend parses with `sysmlpy.load_grammar_antlr` and walks the raw ANTLR
|
|
19
|
+
dict — sysmlpy's own wrapper loader rebuilds usage bodies lossily, so the
|
|
20
|
+
wrappers are not used.
|
|
21
|
+
|
|
22
|
+
Fidelity: names, short names, docs, feature typing (including
|
|
23
|
+
cross-package), multiplicity, attribute values with units, requirement
|
|
24
|
+
subjects, and satisfy statements survive a text parse. What cannot
|
|
25
|
+
round-trip is what sysmlpy's visitor discards before we see it: `dependency`
|
|
26
|
+
statements (how the writer emits verify/derive), `allocate` and `connect`
|
|
27
|
+
endpoints, and `verification` cases (filed upstream as sysmlpy #4 and #5).
|
|
28
|
+
The fidelity table lives in SPEC.md and is pinned by
|
|
29
|
+
`tests/test_backend_fidelity.py`. Use JSON interchange when you need the
|
|
30
|
+
full traceability graph.
|
|
31
|
+
|
|
32
|
+
The dependency is capped (`sysmlpy>=0.36.2,<0.37`) because it has a single
|
|
33
|
+
maintainer; bumps are deliberate, after reading the release notes.
|
|
34
|
+
|
|
35
|
+
## Conformance oracle
|
|
36
|
+
|
|
37
|
+
A scheduled workflow (`conformance.yml`) downloads the EPL-2.0 OMG pilot
|
|
38
|
+
implementation at run time (never vendored) and checks it accepts every
|
|
39
|
+
`.sysml` file our writer emits. See `tools/conformance/run_oracle.py`.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Command line
|
|
2
|
+
|
|
3
|
+
`sysml2kit` accepts `.json` interchange files everywhere; `.sysml` inputs
|
|
4
|
+
need the parse extra (`pip install sysml2kit[parse]`).
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
sysml2kit show model.json # element tree + counts
|
|
8
|
+
sysml2kit show model.json --traceability # + requirement-to-part matrix
|
|
9
|
+
sysml2kit validate a.json b.sysml # exit 1 on error-severity issues
|
|
10
|
+
sysml2kit diff old.json new.json # exit 1 when models differ
|
|
11
|
+
sysml2kit diff old.json new.json --by-name # match by qualified name, not id
|
|
12
|
+
sysml2kit export model.sysml --to json -o model.json
|
|
13
|
+
sysml2kit export model.json --to sysml
|
|
14
|
+
sysml2kit export model.json --to json --stable-ids # UUIDv5 ids for committing
|
|
15
|
+
sysml2kit export model.json --to mermaid --diagram trace # or tree
|
|
16
|
+
sysml2kit fmt model.sysml # refuses lossy rewrites; --lossy overrides
|
|
17
|
+
sysml2kit fmt model.sysml --check # CI mode: exit 1 if it would change
|
|
18
|
+
sysml2kit mcp serve # MCP server (mcp extra)
|
|
19
|
+
sysml2kit version
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Exit codes: `validate` returns 1 when any error-severity issue is found;
|
|
23
|
+
`diff` returns 1 when the models differ; `fmt --check` returns 1 when the
|
|
24
|
+
file would change. All suit CI gates.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Concepts
|
|
2
|
+
|
|
3
|
+
## The pragmatic profile
|
|
4
|
+
|
|
5
|
+
sysml2kit implements ~20 element kinds (packages, part/port/attribute
|
|
6
|
+
definitions and usages, interfaces, connections, requirements, constraints,
|
|
7
|
+
analysis cases, metadata, and four traceability relationships), not the full
|
|
8
|
+
~270-metaclass abstract syntax. Anything outside the profile round-trips
|
|
9
|
+
through `OpaqueElement`: on JSON import an unrecognized `@type` keeps its raw
|
|
10
|
+
record and ownership links, and re-exports unchanged.
|
|
11
|
+
|
|
12
|
+
The repo's `SPEC.md` lists the profile, the pinned spec release
|
|
13
|
+
(`SysML-v2-Release` tag `2026-05`), and every known deviation.
|
|
14
|
+
|
|
15
|
+
## Identity, ownership, refs
|
|
16
|
+
|
|
17
|
+
- Every element has a UUID `element_id`, matching the API JSON `@id`.
|
|
18
|
+
- Cross-references are `Ref` objects (UUID wrappers) resolved through the
|
|
19
|
+
model, never direct Python references, so any element serializes alone.
|
|
20
|
+
- Ownership lives in the `Model` container (owner/owned maps), not on
|
|
21
|
+
elements.
|
|
22
|
+
- `Model.assign_stable_ids()` rewrites ids as UUIDv5 hashes of qualified
|
|
23
|
+
names, so generated interchange files diff cleanly under version control.
|
|
24
|
+
Run it before committing generated models.
|
|
25
|
+
|
|
26
|
+
## Values with units and provenance
|
|
27
|
+
|
|
28
|
+
`AttributeValue` holds a literal plus optional `unit` (text, e.g. `"dBW"`),
|
|
29
|
+
`source`, and `confidence`. Units stay text in the model for round-trip
|
|
30
|
+
fidelity; `sysml2kit.units` (pint) checks them during validation and offers
|
|
31
|
+
conversion helpers.
|
|
32
|
+
|
|
33
|
+
## Two output formats, one lossless
|
|
34
|
+
|
|
35
|
+
- **JSON interchange** (`sysml2kit.interchange`) is the lossless format and
|
|
36
|
+
what the Systems Modeling API speaks.
|
|
37
|
+
- **Textual notation** (`sysml2kit.text`) is deterministic and parseable, but
|
|
38
|
+
relationship kinds without a standalone textual statement (verify, derive)
|
|
39
|
+
emit as marked dependencies. Round-tripping text preserves structure;
|
|
40
|
+
round-tripping JSON preserves everything.
|
|
41
|
+
|
|
42
|
+
## Spec churn policy
|
|
43
|
+
|
|
44
|
+
The `@type` vocabulary lives in one module
|
|
45
|
+
(`sysml2kit/interchange/typemap.py`). The spec pin moves at most quarterly,
|
|
46
|
+
in a minor release, noted in the changelog.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# sysml2kit
|
|
2
|
+
|
|
3
|
+
API-first Python tooling for building, querying, validating, and automating
|
|
4
|
+
SysML v2 models.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
pip install sysml2kit # build, write, query, validate, diff
|
|
8
|
+
pip install "sysml2kit[parse]" # + read .sysml files (sysmlpy backend)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`sysml2kit` is the requirements/architecture/traceability layer for
|
|
12
|
+
engineering automation stacks: build a system model in Python, emit standard
|
|
13
|
+
SysML v2 textual notation and Systems Modeling API JSON, answer traceability
|
|
14
|
+
questions (which requirements are unsatisfied? unverified? allocated where?),
|
|
15
|
+
validate, and diff.
|
|
16
|
+
|
|
17
|
+
Reference spec release: OMG `SysML-v2-Release` tag `2026-05`. The element
|
|
18
|
+
subset and known deviations are documented in
|
|
19
|
+
[concepts](concepts.md) and the repo's `SPEC.md`.
|
|
20
|
+
|
|
21
|
+
Start with the [quickstart](quickstart.md), then the
|
|
22
|
+
[traceability](traceability.md) page — the queries there are the point of the
|
|
23
|
+
package. For antenna/RF domain content, see
|
|
24
|
+
[the RF library](rf-library.md).
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Interchange
|
|
2
|
+
|
|
3
|
+
## JSON (lossless)
|
|
4
|
+
|
|
5
|
+
`sysml2kit.interchange` reads and writes the Systems Modeling API
|
|
6
|
+
serialization: a flat list of records like
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
{"@id": "…", "@type": "PartUsage", "declaredName": "battery",
|
|
10
|
+
"owningRelatedElement": {"@id": "…"}, "definition": {"@id": "…"}}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- `model_to_json(model)` / `write_json(model, path)` — deterministic output:
|
|
14
|
+
elements sorted by qualified name, keys sorted per record, so committed
|
|
15
|
+
files diff cleanly. Pair with `model.assign_stable_ids()` for generated
|
|
16
|
+
models.
|
|
17
|
+
- `model_from_json(records_or_path)` — unknown `@type` records become
|
|
18
|
+
`OpaqueElement` and re-export byte-identically.
|
|
19
|
+
|
|
20
|
+
`json -> model -> json` is a fixpoint; the property is tested with hypothesis.
|
|
21
|
+
|
|
22
|
+
## Textual notation (readable, parseable)
|
|
23
|
+
|
|
24
|
+
`sysml2kit.text.write_model(model)` emits deterministic `.sysml` text:
|
|
25
|
+
ownership order, four-space indent, values as `= 52.0 [dBW]`, requirement
|
|
26
|
+
statements as `doc` bodies, `satisfy X by Y;` / `allocate X to Y;`
|
|
27
|
+
statements. Verify and derive have no standalone textual statement in the
|
|
28
|
+
grammar, so they emit as `dependency from A to B; // verify` — the JSON keeps
|
|
29
|
+
the precise kind.
|
|
30
|
+
|
|
31
|
+
Reading text back goes through a [parser backend](backends.md).
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# MCP server
|
|
2
|
+
|
|
3
|
+
`pip install "sysml2kit[mcp]"` and run:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
sysml2kit mcp serve # stdio (default)
|
|
7
|
+
sysml2kit mcp serve --transport http # streamable HTTP
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Client config:
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{"mcpServers": {"sysml2kit": {"command": "sysml2kit", "args": ["mcp", "serve"]}}}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Every tool takes model file paths (`.json` interchange always works;
|
|
17
|
+
`.sysml` needs the `parse` extra), returns a JSON dict with a `status` key,
|
|
18
|
+
and reports failures as `{"error": ..., "status": "failed"}` instead of
|
|
19
|
+
raising. Artifacts are returned as file paths, not payloads.
|
|
20
|
+
|
|
21
|
+
| Tool | What it does |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `model_show(path, traceability)` | Element tree, kind counts, optional trace matrix |
|
|
24
|
+
| `model_validate(path)` | S2K rule issues with severity counts |
|
|
25
|
+
| `model_diff(path_a, path_b, by_name)` | Element-level differences (capped list) |
|
|
26
|
+
| `model_export(path, out, to, stable_ids)` | Convert to interchange JSON or `.sysml` |
|
|
27
|
+
| `model_diagram(path, out, kind)` | Write a mermaid `.mmd` (trace or tree view) |
|
|
28
|
+
| `requirements_trace(path)` | Matrix plus unsatisfied/unverified lists |
|
|
29
|
+
| `requirements_extract(path)` | `RequirementSpec` list (the adapter payload) |
|
|
30
|
+
| `library_load(name, out)` | Write a packaged rf-library model as JSON |
|
|
31
|
+
|
|
32
|
+
A typical agent loop: write a `.sysml` file, `model_validate` it, fix issues,
|
|
33
|
+
`requirements_trace` to check coverage, `model_export --stable-ids` to commit
|
|
34
|
+
the interchange form, `model_diagram` to explain the result.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Quickstart
|
|
2
|
+
|
|
3
|
+
Build a model, run the traceability queries, and emit both output formats.
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from sysml2kit import Model, builder
|
|
7
|
+
from sysml2kit.query import trace_matrix, unverified_requirements
|
|
8
|
+
from sysml2kit.text import write_model
|
|
9
|
+
from sysml2kit.interchange import write_json
|
|
10
|
+
from sysml2kit.validation import validate
|
|
11
|
+
|
|
12
|
+
model = Model()
|
|
13
|
+
pkg = builder.pkg(model, "Vehicle")
|
|
14
|
+
battery = builder.part(model, "battery", owner=pkg)
|
|
15
|
+
range_req = builder.req(
|
|
16
|
+
model,
|
|
17
|
+
"REQ-001",
|
|
18
|
+
"Range",
|
|
19
|
+
owner=pkg,
|
|
20
|
+
text="The vehicle shall travel at least 400 km on one charge.",
|
|
21
|
+
)
|
|
22
|
+
builder.satisfy(model, source=battery, target=range_req)
|
|
23
|
+
|
|
24
|
+
print(unverified_requirements(model)) # [REQ-001] - nothing verifies it yet
|
|
25
|
+
print(trace_matrix(model).render()) # requirement-by-part grid
|
|
26
|
+
for issue in validate(model):
|
|
27
|
+
print(issue.rule_id, issue.severity, issue.message)
|
|
28
|
+
|
|
29
|
+
print(write_model(model)) # SysML v2 textual notation
|
|
30
|
+
write_json(model, "vehicle.json") # Systems Modeling API interchange
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The same operations from the command line:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
sysml2kit show vehicle.json --traceability
|
|
37
|
+
sysml2kit validate vehicle.json
|
|
38
|
+
sysml2kit export vehicle.json --to sysml
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Reading `.sysml` text back requires the parse extra:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from sysml2kit.backends import get_backend
|
|
45
|
+
|
|
46
|
+
model = get_backend("sysmlpy").parse(open("vehicle.sysml").read())
|
|
47
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# API reference
|
|
2
|
+
|
|
3
|
+
## Model and elements
|
|
4
|
+
|
|
5
|
+
::: sysml2kit.model.container.Model
|
|
6
|
+
|
|
7
|
+
::: sysml2kit.model.base
|
|
8
|
+
|
|
9
|
+
## Builder
|
|
10
|
+
|
|
11
|
+
::: sysml2kit.model.builder
|
|
12
|
+
|
|
13
|
+
## Queries
|
|
14
|
+
|
|
15
|
+
::: sysml2kit.query
|
|
16
|
+
|
|
17
|
+
## Validation
|
|
18
|
+
|
|
19
|
+
::: sysml2kit.validation
|
|
20
|
+
|
|
21
|
+
## Diff
|
|
22
|
+
|
|
23
|
+
::: sysml2kit.diff
|
|
24
|
+
|
|
25
|
+
## Interop
|
|
26
|
+
|
|
27
|
+
::: sysml2kit.interop.requirements
|
|
28
|
+
|
|
29
|
+
## Units
|
|
30
|
+
|
|
31
|
+
::: sysml2kit.units
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# The RF library
|
|
2
|
+
|
|
3
|
+
sysml2kit stays domain-general. Antenna/RF vocabulary lives in
|
|
4
|
+
[sysml2kit-rf-library](https://github.com/jman4162/sysml2kit-rf-library):
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
pip install sysml2kit-rf-library
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
from sysml2kit_rf_library import load_model
|
|
12
|
+
from sysml2kit.interop import extract_requirements
|
|
13
|
+
from sysml2kit.query import trace_matrix
|
|
14
|
+
|
|
15
|
+
model = load_model("satcom-terminal-t3001")
|
|
16
|
+
print(trace_matrix(model).render())
|
|
17
|
+
for spec in extract_requirements(model):
|
|
18
|
+
print(spec.id, spec.metric_key, spec.op, spec.value, spec.units)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
It ships four library packages (RFVocabulary quantity kinds with units,
|
|
22
|
+
RFParts part/port definitions, RFRequirements requirement definitions using
|
|
23
|
+
the metricKey convention, RFAnalyses analysis case definitions) plus
|
|
24
|
+
**SatcomTerminal28GHz** — a worked example mirroring the aedl `t3-001`
|
|
25
|
+
benchmark: a 28 GHz LEO uplink phased-array terminal with eight
|
|
26
|
+
machine-checkable requirements (worst-case link margin, sidelobe level,
|
|
27
|
+
independent link crosscheck, clear-sky and gain agreement, prime-power and
|
|
28
|
+
unit-cost ceilings, grating-lobe margin), each satisfied by a part and
|
|
29
|
+
verified by an analysis.
|
|
30
|
+
|
|
31
|
+
The library demonstrates the intended division of labor: domain vocabulary
|
|
32
|
+
as SysML v2 model content, generic mechanics in the kit, physics engines
|
|
33
|
+
downstream.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Traceability
|
|
2
|
+
|
|
3
|
+
The queries in `sysml2kit.query` answer the questions a requirements-driven
|
|
4
|
+
workflow actually asks:
|
|
5
|
+
|
|
6
|
+
| Question | Call |
|
|
7
|
+
|---|---|
|
|
8
|
+
| What satisfies this requirement? | `satisfied_by(model, req)` |
|
|
9
|
+
| What verifies it? | `verified_by(model, req)` |
|
|
10
|
+
| What does it derive from? | `derived_from(model, req)` |
|
|
11
|
+
| Which requirements have no satisfier? | `unsatisfied_requirements(model)` |
|
|
12
|
+
| Which have no verifier? | `unverified_requirements(model)` |
|
|
13
|
+
| What is allocated where? | `allocation_table(model)` |
|
|
14
|
+
| The whole grid at once? | `trace_matrix(model).render()` |
|
|
15
|
+
|
|
16
|
+
The four relationship kinds are first-class elements
|
|
17
|
+
(`SatisfyRelationship`, `VerifyRelationship`, `DeriveRelationship`,
|
|
18
|
+
`AllocateRelationship`) created through the builder:
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
builder.satisfy(model, source=battery, target=mass_req)
|
|
22
|
+
builder.verify(model, source=range_analysis, target=range_req)
|
|
23
|
+
builder.derive(model, source=mass_req, target=range_req)
|
|
24
|
+
builder.allocate(model, source=range_req, target=battery)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Handing requirements to an engine: the metricKey convention
|
|
28
|
+
|
|
29
|
+
A requirement usage that owns attributes `metricKey` (string), `threshold`
|
|
30
|
+
(number with unit), `op` (`>=`, `<=`, `==`, `>`, `<`), and optionally
|
|
31
|
+
`severity` (`must`/`should`/`nice`) is machine-checkable.
|
|
32
|
+
`sysml2kit.interop.extract_requirements` turns each into a `RequirementSpec`
|
|
33
|
+
carrying the threshold in both operator form (`op` + `value`) and bound form
|
|
34
|
+
(`minimum`/`maximum`), plus the satisfy/verify trace as qualified names:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from sysml2kit.interop import extract_requirements
|
|
38
|
+
|
|
39
|
+
for spec in extract_requirements(model):
|
|
40
|
+
print(spec.id, spec.metric_key, spec.op, spec.value, spec.satisfied_by)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Both forms are always populated (`>= 40` also sets `minimum=40`), so an
|
|
44
|
+
operator-style requirements engine (phased-array-systems) and a bound-style
|
|
45
|
+
one (aedl) each need only a small adapter, which lives in those packages.
|
|
46
|
+
The metric key names the entry in the engine's metrics dict; the model never
|
|
47
|
+
computes anything itself.
|
|
@@ -31,3 +31,13 @@ plugins:
|
|
|
31
31
|
|
|
32
32
|
nav:
|
|
33
33
|
- Home: index.md
|
|
34
|
+
- Quickstart: quickstart.md
|
|
35
|
+
- Concepts: concepts.md
|
|
36
|
+
- Traceability: traceability.md
|
|
37
|
+
- Interchange: interchange.md
|
|
38
|
+
- Command line: cli.md
|
|
39
|
+
- MCP server: mcp.md
|
|
40
|
+
- API client: api-client.md
|
|
41
|
+
- Parser backends: backends.md
|
|
42
|
+
- RF library: rf-library.md
|
|
43
|
+
- Reference: reference.md
|
|
@@ -50,6 +50,8 @@ dependencies = [
|
|
|
50
50
|
# after checking the release notes.
|
|
51
51
|
parse = ["sysmlpy>=0.36.2,<0.37"]
|
|
52
52
|
graph = ["networkx>=3.2"]
|
|
53
|
+
# mcp 2.0.0 removed mcp.server.fastmcp; stay on 1.x until the surface is ported.
|
|
54
|
+
mcp = ["mcp>=1.26,<2"]
|
|
53
55
|
|
|
54
56
|
[project.scripts]
|
|
55
57
|
sysml2kit = "sysml2kit.cli:app"
|
|
@@ -70,11 +72,13 @@ test = [
|
|
|
70
72
|
]
|
|
71
73
|
lint = ["mypy>=1.15", "ruff>=0.16"]
|
|
72
74
|
parse-test = ["sysmlpy>=0.36.2,<0.37"]
|
|
75
|
+
mcp-test = ["mcp>=1.26,<2"]
|
|
73
76
|
docs = ["mkdocs-material>=9.5", "mkdocstrings[python]>=0.27"]
|
|
74
77
|
dev = [
|
|
75
78
|
{ include-group = "test" },
|
|
76
79
|
{ include-group = "lint" },
|
|
77
80
|
{ include-group = "parse-test" },
|
|
81
|
+
{ include-group = "mcp-test" },
|
|
78
82
|
{ include-group = "docs" },
|
|
79
83
|
]
|
|
80
84
|
|
|
@@ -137,9 +141,16 @@ files = ["src/sysml2kit"]
|
|
|
137
141
|
plugins = ["pydantic.mypy"]
|
|
138
142
|
|
|
139
143
|
[[tool.mypy.overrides]]
|
|
140
|
-
|
|
144
|
+
# sysml2kit_rf_library is an optional runtime peer, not a dependency.
|
|
145
|
+
module = ["sysmlpy.*", "pint.*", "networkx.*", "sysml2kit_rf_library", "sysml2kit_rf_library.*"]
|
|
141
146
|
ignore_missing_imports = true
|
|
142
147
|
|
|
148
|
+
[[tool.mypy.overrides]]
|
|
149
|
+
# The MCP server class is typed loosely (SDK 1.x/2.x compatibility), so its
|
|
150
|
+
# tool decorator is Any; the tools themselves stay fully annotated.
|
|
151
|
+
module = "sysml2kit.mcp.*"
|
|
152
|
+
disallow_untyped_decorators = false
|
|
153
|
+
|
|
143
154
|
[[tool.mypy.overrides]]
|
|
144
155
|
module = "tests.*"
|
|
145
156
|
disallow_untyped_defs = false
|
|
@@ -150,7 +161,12 @@ minversion = "8.0"
|
|
|
150
161
|
testpaths = ["tests", "src/sysml2kit"]
|
|
151
162
|
addopts = ["-ra", "--strict-markers", "--strict-config", "--doctest-modules"]
|
|
152
163
|
xfail_strict = true
|
|
153
|
-
filterwarnings = [
|
|
164
|
+
filterwarnings = [
|
|
165
|
+
"error",
|
|
166
|
+
# The mcp SDK's FastMCP settings model trips this pydantic-settings warning
|
|
167
|
+
# internally; not ours to fix.
|
|
168
|
+
"ignore::pydantic_settings.exceptions.IncompleteFieldDefinitionWarning",
|
|
169
|
+
]
|
|
154
170
|
markers = [
|
|
155
171
|
"parse: requires the sysmlpy parse extra",
|
|
156
172
|
"api: requires a live Systems Modeling API server",
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
"""API-first Python tooling for building, querying, validating, and automating SysML v2 models.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
See https://github.com/jman4162/sysml2kit and SPEC.md for the element subset
|
|
4
|
+
(the "pragmatic profile") and the pinned spec release.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from importlib.metadata import PackageNotFoundError, version
|
|
8
8
|
|
|
9
|
+
from sysml2kit.model import Model, builder
|
|
10
|
+
|
|
9
11
|
try:
|
|
10
12
|
__version__ = version("sysml2kit")
|
|
11
13
|
except PackageNotFoundError: # running from a source tree without an install
|
|
12
14
|
__version__ = "0.0.0.dev0"
|
|
13
15
|
|
|
14
|
-
__all__ = ["__version__"]
|
|
16
|
+
__all__ = ["Model", "__version__", "builder"]
|