Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
702bfdb
feat(ontology): generate the metamodel table from the pilot's SysML.e…
devin-ai-integration[bot] Oct 3, 2026
473cafa
fix(ontology): check a multiply-typed subject as its most specific rd…
devin-ai-integration[bot] Oct 4, 2026
617f6d1
feat(ontology): record the metamodel's enumerations and their literals
devin-ai-integration[bot] Oct 4, 2026
8478a40
feat(python): generate metaclass classes and read metamodel JSON
devin-ai-integration[bot] Oct 4, 2026
52bdf3f
fix(ontology): treat an upper bound above one as multi-valued
devin-ai-integration[bot] Oct 4, 2026
c222f81
fix(python): refine metamodel reader contracts
devin-ai-integration[bot] Oct 4, 2026
00a6b35
chore: merge develop into feature/python-metamodel-reader
devin-ai-integration[bot] Oct 4, 2026
8f52556
docs(python): add a metamodel classes and JSON guide page
devin-ai-integration[bot] Oct 4, 2026
93b60ac
fix(python): fix API docs and CI type checking
devin-ai-integration[bot] Oct 4, 2026
48b25cf
Merge remote-tracking branch 'origin/develop' into feature/ontology-p…
devin-ai-integration[bot] Oct 4, 2026
6b329ae
chore: merge develop into feature/python-metamodel-reader
devin-ai-integration[bot] Oct 4, 2026
f32b26a
ci(python): install protobuf stubs for the metamodel type check
devin-ai-integration[bot] Oct 4, 2026
5bdc124
fix(python): validate reference ranges and unwrap standalone envelopes
devin-ai-integration[bot] Oct 4, 2026
4f18fb6
feat(python): let read_json skip the reference range check
devin-ai-integration[bot] Oct 4, 2026
9a7a0ac
fix(ontology): treat an ecore upper bound above one as multi-valued
devin-ai-integration[bot] Oct 4, 2026
3a7244c
Merge remote-tracking branch 'origin/develop' into feature/ontology-p…
devin-ai-integration[bot] Oct 4, 2026
d94fb1e
fix(ontology): read ecore upper bounds as EMF does, -2 unspecified in…
devin-ai-integration[bot] Oct 4, 2026
2a4c6c6
chore: merge ontology-pilot-metamodel updates
devin-ai-integration[bot] Oct 4, 2026
232528b
style(ontology): preserve generator test spacing
devin-ai-integration[bot] Oct 4, 2026
86645d8
fix(ontology): keep the upstream upper-bound rule after merging
devin-ai-integration[bot] Oct 4, 2026
9b78c1a
fix(build): restore the build-release-wasm recipe lost in a merge
devin-ai-integration[bot] Oct 4, 2026
59aa5c4
chore: merge ontology-pilot-metamodel updates
devin-ai-integration[bot] Oct 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,29 @@ jobs:
- install-solvers
- download-corpora

# The metamodel table is generated from the pilot's SysML.ecore at the pin;
# a pin bump without regenerating it fails here.
- restore_cache:
keys:
- pilot-metamodel-v1-{{ checksum "scripts/download-pilot-metamodel.sh" }}-{{ checksum "scripts/pilot-pin.sh" }}

- run:
name: Download the pilot metamodel
command: ./scripts/download-pilot-metamodel.sh

- save_cache:
key: pilot-metamodel-v1-{{ checksum "scripts/download-pilot-metamodel.sh" }}-{{ checksum "scripts/pilot-pin.sh" }}
paths:
- build/pilot-metamodel

- run:
name: Check the metamodel table matches the pinned SysML.ecore
command: make ontology-table-check

- run:
name: Check generated Python metaclasses are current
command: make python-metamodel-check

# The corpora gate alone, so its per-root verdict lines are legible in the
# log and a skip cannot hide behind a green suite.
- run:
Expand Down Expand Up @@ -993,7 +1016,7 @@ jobs:
command: |
make python-install
# Pinned and wheel-only, as in .github/workflows/pr.yml.
pip install --only-binary :all: pytest==9.0.3 pytest-mock==3.15.1 psutil==7.2.2 pytest-cov==7.0.0 fmpy==0.3.32
pip install --only-binary :all: pytest==9.0.3 pytest-mock==3.15.1 psutil==7.2.2 pytest-cov==7.0.0 fmpy==0.3.32 mypy==2.4.0 types-protobuf==7.35.1.20260906 'pyright[nodejs]==1.1.414'

# The integration tests connect to a service on the standard port with
# auto_start=False, which is the explicit opt-in to one the client does not
Expand Down Expand Up @@ -1027,7 +1050,7 @@ jobs:
# service is provided here, so its absence is the bug, not a pass.
- run:
name: Run Python client tests
command: OPENSYSML_REQUIRE_SERVICE=1 OPENSYSML_REQUIRE_REFERENCE_FMUS=1 make python-coverage
command: OPENSYSML_REQUIRE_SERVICE=1 OPENSYSML_REQUIRE_REFERENCE_FMUS=1 OPENSYSML_REQUIRE_TYPECHECKERS=1 make python-coverage

# The repository scripts the Go static checks run are Python too; running
# them and their tests under coverage here credits what those checks execute.
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1240,7 +1240,7 @@ jobs:
make python-install
# Pinned and wheel-only: an unpinned resolve runs whatever was
# published today, and a source distribution runs its own build code.
pip install --only-binary :all: pytest==9.0.3 pytest-mock==3.15.1 psutil==7.2.2 fmpy==0.3.32
pip install --only-binary :all: pytest==9.0.3 pytest-mock==3.15.1 psutil==7.2.2 fmpy==0.3.32 mypy==2.4.0 types-protobuf==7.35.1.20260906 'pyright[nodejs]==1.1.414'

# The FMI runner test's FMUs, same pin as the Go gate's.
- name: Cache the Reference-FMUs
Expand Down Expand Up @@ -1279,6 +1279,7 @@ jobs:
- name: Run Python client tests
env:
OPENSYSML_REQUIRE_SERVICE: 1
OPENSYSML_REQUIRE_TYPECHECKERS: 1
run: make python-test

- name: Verify Python client import
Expand Down
20 changes: 19 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: all build build-sysml build-prod build-wasm-prod build-lsp build-grpc build-engine build-core build-syntax build-sysml-wasm build-release-wasm build-wasm build-wasm-wasip1 build-wasm-js wasm-check static-check windows-versioninfo-check man man-check install-tree pgo-profile conformance conformance-pkg conformance-rust conformance-julia conformance-matlab test test-shard coverage lint clean install help fuml-expected python-test python-coverage scripts-coverage node-coverage python-install proto proto-buf python-proto proto-ts proto-rust proto-lint proto-breaking vscode-grammar vscode-build vscode-package docs docs-install docs-serve docs-engine-assets docs-counts docs-check changelog-check changelog-render self-model
.PHONY: all build build-sysml build-prod build-wasm-prod build-lsp build-grpc build-engine build-core build-syntax build-sysml-wasm build-release-wasm build-wasm build-wasm-wasip1 build-wasm-js wasm-check static-check windows-versioninfo-check man man-check install-tree pgo-profile conformance conformance-pkg conformance-rust conformance-julia conformance-matlab test test-shard coverage lint clean install help ontology-table ontology-table-check python-metamodel python-metamodel-check fuml-expected python-test python-coverage scripts-coverage node-coverage python-install proto proto-buf python-proto proto-ts proto-rust proto-lint proto-breaking vscode-grammar vscode-build vscode-package docs docs-install docs-serve docs-engine-assets docs-counts docs-check changelog-check changelog-render self-model

# Version information
# Only release tags describe a build; the moving `nightly` tag is not a version.
Expand Down Expand Up @@ -322,6 +322,24 @@ stdlib-snapshot-check: ## Verify the committed library snapshot matches the bund
go run -C $(TOOLS_DIR) ./gen/snapshot -check
@echo "✓ stdlib.snapshot is current"

ontology-table: ## Regenerate the metamodel table from the pilot SysML.ecore that scripts/pilot-pin.sh pins
./scripts/download-pilot-metamodel.sh
go run -C $(TOOLS_DIR) ./gen/ontology
@echo "✓ internal/translate/rdf/ontology/table.go regenerated"

ontology-table-check: ## Verify the committed metamodel table matches the pinned pilot SysML.ecore, as CI does
./scripts/download-pilot-metamodel.sh
go run -C $(TOOLS_DIR) ./gen/ontology -check
@echo "✓ internal/translate/rdf/ontology/table.go is current"

python-metamodel: ## Regenerate Python metaclass classes from the ontology table
go run -C $(TOOLS_DIR) ./gen/pymetamodel
@echo "✓ Python metamodel generated"

python-metamodel-check: ## Verify generated Python metaclass classes are current
go run -C $(TOOLS_DIR) ./gen/pymetamodel -check
@echo "✓ Python metamodel is current"

fuml-expected: ## Regenerate docs/project/fuml-referee-expected.json from the pinned fUML reference implementation (needs a JDK)
./scripts/fuml-expected.sh
@echo "✓ fuml-referee-expected.json regenerated"
Expand Down
1 change: 1 addition & 0 deletions changes/unreleased/metamodel-reader-validation.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **The metamodel JSON reader unwraps standalone DataVersion envelopes, excludes namespaces with owner metadata from roots, rejects references to the wrong metaclass by default, and rejects non-finite real values.** This reports malformed exported values when read, lets callers opt out of range checking with `check_ranges=False`, and resolves custom metaclasses through `supertypes=`.
1 change: 1 addition & 0 deletions changes/unreleased/ontology-bounded-many.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **Ecore upper bounds above one are multi-valued in the ontology table.** `MultiplicityRange::bound` and `Flow::flowEnd` (upper bound 2) were marked single-valued; they are now `Many`, so api-json writes them as arrays.
1 change: 1 addition & 0 deletions changes/unreleased/ontology-pilot-metamodel.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **The metamodel table is generated from the OMG SysML v2 metamodel version 20250201, read from the pinned pilot implementation's `SysML.ecore`, and records each property's ordering, derivation, redefinitions, subsettings and opposite.** It was pinned to the 202407 rendering of `Open-MBEE/sysmlv2-rdf-ontology`, which has not moved since. The table now declares `FlowUsage`, `PayloadFeature`, `FlowEnd`, `TerminateActionUsage` and the other metaclasses added since, so a type owns them through a `sysml:FeatureMembership` and lists them in `sysml:ownedFeature`, as it owns any feature; `nonunique` is written `sysml:isUnique false`, since the metamodel no longer declares `isNonunique`. Graphs written by earlier releases still read. `ontology.Property` gains `Ordered`, `Derived`, `Redefines`, `Subsets` and `Opposite`, `ontology.Class` gains `Abstract`, and the ontology gate reports a subject typed by an abstract metaclass. CI fails when the table drifts from the pinned metamodel (`make ontology-table-check`).
1 change: 1 addition & 0 deletions changes/unreleased/python-metamodel-reader.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **Add generated SysML metaclasses and a standalone JSON element reader to the Python client.** Read API and toolkit exports as a lazy typed graph without loading JSON into the engine.
3 changes: 2 additions & 1 deletion client/python/opensysml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
TypeMismatchError, UnpinnedReleaseError, UnsignedReleaseError,
UnsupportedOperationError, UnsupportedValueError, WrongKindError,
)
from opensysml.metamodel import read_json

__all__ = [
"Connection", "Model", "Symbol", "Diagnostic", "EnumLiteral", "Instance",
Expand Down Expand Up @@ -106,7 +107,7 @@
"TypeMismatchError", "UnpinnedReleaseError", "UnsignedReleaseError",
"UnsupportedOperationError", "UnsupportedValueError",
"WrongKindError",
"load", "loads", "parse_sources", "connect", "convert", "migrate",
"load", "loads", "parse_sources", "connect", "convert", "migrate", "read_json",
# "eval" is deprecated in favour of "evaluate", so it is not exported.
"evaluate", "instantiate",
"DEFAULT_PORT", "split_target",
Expand Down
31 changes: 31 additions & 0 deletions client/python/opensysml/metamodel/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Generated metamodel classes and a reader for exported JSON documents."""

# pyright: reportUnsupportedDunderAll=false

from ._generated import *
from ._generated import __all__ as _generated_all
from ._reader import ElementGraph, read_json
from ._runtime import (
Many,
MalformedDocument,
MalformedValue,
MetamodelError,
NotSupplied,
Opt,
UnknownJSONKey,
UnresolvedReference,
)

__all__ = [
*_generated_all,
"ElementGraph",
"Many",
"MalformedDocument",
"MalformedValue",
"MetamodelError",
"NotSupplied",
"Opt",
"UnknownJSONKey",
"UnresolvedReference",
"read_json",
]
Loading
Loading