API server & client¶
The API server & client guide covers the
resource model, the git-backed commit semantics, and the /x/ extension
endpoints end to end.
longeron.server¶
Requires the server extra (pip install "longeron[server]"); the
GitProjectStore itself needs only git on
PATH.
Serve a workspace as an OMG Systems Modeling API server (git-backed).
longeron serve [path] (or serve() / create_app()) exposes a
directory of .sysml files – or a single file – over the REST resource
model of the OMG Systems Modeling API & Services specification, the same
surface the pilot-implementation servers offer and clients like pymbe (and
longeron.client) consume:
GET /projects
GET /projects/{projectId}
GET /projects/{projectId}/commits
POST /projects/{projectId}/commits
GET /projects/{projectId}/commits/{commitId}
GET /projects/{projectId}/commits/{commitId}/elements (paged)
GET /projects/{projectId}/commits/{commitId}/elements/{elementId}
GET /projects/{projectId}/commits/{commitId}/roots
Storage is git-backed and honest: the served path is the project, and an
API commit is a git commit that touched the .sysml sources beneath it
(listed via git log). Elements at a historic commit are parsed from
git show <sha>:<path> blobs through the content-addressed model cache
(longeron.workspace), so revisiting a ref is as fast as a warm load.
The uncommitted working tree is always exposed as the head pseudo-commit
working. Everything is read-only except POST .../commits, which
accepts pilot-style identity/payload change records and
materializes them: the changes are imported onto the working-tree model
and the affected files are rewritten as .sysml text. The server never
runs git commit – agents and tools must not auto-commit user
repositories; review the diff and commit yourself, which is exactly the
point of the git mapping.
Endpoints under /x/ are longeron extensions (no pilot server has
them): POST /x/validate, POST /x/instantiate/{qname},
POST /x/simulate/{qname}, POST /x/interpret/{qname}, and
GET /x/render/{qname}.svg wrap the
validator, interpreter, and headless renderer.
Security: this is a local-first development server – no authentication, no
TLS – and it binds to 127.0.0.1 by default. Do not expose it beyond a
trusted network. Requires the server extra (FastAPI, uvicorn, pyecore);
the one external tool is git on PATH (without it the workspace is
still served, as a single working commit).
- longeron.server.WORKING_COMMIT_ID = 'working'¶
the pseudo-commit id under which the uncommitted working tree is served
- class longeron.server.GitProjectStore(path='.')[source]¶
Bases:
objectOne served workspace: project/commit/element views over a git repo.
Usable on its own (no FastAPI needed) –
create_app()wraps it in HTTP routes. All git access is read-only (rev-parse,log,ls-tree,show);apply_commit()writes.sysmlfiles to the working tree but never touches the git index or history.- git_commits()[source]¶
API commit records for the git commits that touched the served
.sysmlsources, oldest first.previousCommitchains within this filtered list (the project’s history, not the whole repo’s).
- commits()[source]¶
All commits, ending with the
workingpseudo-commit for the uncommitted working tree (equal to head content when clean).
- resolve_commit(commit_id)[source]¶
Normalize a commit id (
working, a full sha, or any git rev the repo can resolve) or raiseSysMLError.- Return type:
- model_at(commit_id)[source]¶
The merged model at a commit; historic refs are parsed from
git showblobs and memoized (refs are immutable), the working tree is loaded throughlongeron.load()and memoized behind a stat fingerprint of the served files (edits invalidate).- Return type:
- records_at(commit_id)[source]¶
Flat API records at a commit (memoized: per immutable ref, and for the working tree until its stat fingerprint changes – so a paginated listing projects the model once, not once per page).
- apply_commit(body)[source]¶
Materialize a POSTed commit into the working tree.
The body is a pilot-style commit (
{"change": [{"identity": {"@id": ...}, "payload": {...}|null}, ...]}) or a bare list of such entries / flat records. Semantics per change entry, against the element ids of the working-tree model:unknown id + payload – add: the new element records (with their membership records naming an owner, and any typing / specialization relationship records) are imported and attached;
known element id + payload – update: name, short name, flag, and body fields are patched onto the element;
known relationship-record id + payload – retarget: the owner’s typing/specialization entry is rewritten;
payload
null– delete the element (or relationship).
Only the
.sysmlfiles owning affected top-level elements are rewritten (regenerated withlongeron.to_sysml(), which normalizes formatting); untouched files are never rewritten. The result is left uncommitted on purpose: tools must not auto-commit user repositories, so reviewgit diffand commit yourself.
- longeron.server.create_app(path='.')[source]¶
A FastAPI app serving
path(requireslongeron[server]).- Return type:
- longeron.server.serve(path='.', *, host='127.0.0.1', port=9000)[source]¶
Run the API server (blocking).
longeron serve [path] --port N.Binds to
127.0.0.1by default: the server is local-first and does no authentication. Plainuvicorn.run– no signal-based reload tricks, so this works identically on Windows and POSIX.- Return type:
longeron.client¶
Requires the client extra (pip install "longeron[client]").
Typed client for OMG Systems Modeling API servers.
Client talks to any server exposing the pilot-implementation REST
resource model (projects -> commits -> paginated elements) – including
longeron serve (longeron.server) and the OMG pilot servers. It
ports the good bones of pymbe’s APIClient (Link-header pagination,
project/commit browsing, the POST identity/payload change form)
without the traitlets/ipywidgets machinery:
from longeron.client import Client
with Client("http://localhost:9000") as client:
project = client.list_projects()[0]["@id"]
model = client.fetch_model(project) # working tree
old = client.fetch_model(project, commit=sha) # any git commit
fetch_model rebuilds a longeron.model.Model from the flat API
records via longeron.api.model_from_api_records() – the derived
source/target endpoint arrays every pilot-style server serializes
make the records navigable, so structure, ownership, typing, and
specialization all come back. push_commit sends changes the other way.
Requires the client extra (httpx): pip install 'longeron[client]'.
Pure Python; works identically on Windows and POSIX.
- class longeron.client.Client(base_url='http://localhost:9000', *, page_size=2000, timeout=30.0, http=None)[source]¶
Bases:
objectA synchronous Systems Modeling API client.
base_urlnames the server (default the pilot-conventionalhttp://localhost:9000). Passhttpto supply a pre-configuredhttpx.Client-compatible object instead – e.g. a StarletteTestClientwrapping an app in-process, which is how longeron’s own test suite exercises client and server together without a network.- list_elements(project, commit=None)[source]¶
All element records at a commit (default: the working tree / head), transparently following pagination.
- fetch_model(project, commit=None)[source]¶
Download and rebuild the model at a commit (default: working tree). See
longeron.api.model_from_api_records()for the structural fidelity contract.- Return type:
- push_commit(project, changes, *, description='')[source]¶
POST a commit.
changesis either a list of change entries (pilot{"identity": {"@id": ...}, "payload": {...}|null}form, or flat records, which are wrapped) or a wholeModel, which is projected to API records first (that projection needs pyecore:longeron[ecore]).Against
longeron serve, the server materializes the commit by rewriting the affected.sysmlfiles in its working tree – it never runsgit commit(tools must not auto-commit user repos); the response’swrittenfield lists the files to review.
- validate(commit=None, *, strict_imports=False)[source]¶
POST /x/validate(longeron servers only).strict_importsis forwarded to the server, mirroringlongeron.validation.validate(): additionally warn for bare standard-library names that resolve only through the implicit library-visibility hop.
- instantiate(qname, commit=None, **bindings)[source]¶
POST /x/instantiate/{qname}(longeron servers only).
- simulate(qname, events=None, inputs=None, commit=None)[source]¶
POST /x/simulate/{qname}(longeron servers only).
- interpret(qname, strategy='nominal', seed=None, commit=None, bindings=None, selection=None)[source]¶
POST /x/interpret/{qname}(longeron servers only): an M0 interpretation of the population underqname– the JSON shape oflongeron.m0.Interpretation.to_dict().