simulo 0.19.0__tar.gz → 0.20.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.
- {simulo-0.19.0/src/simulo.egg-info → simulo-0.20.0}/PKG-INFO +4 -2
- {simulo-0.19.0 → simulo-0.20.0}/pyproject.toml +14 -2
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/app.py +11 -32
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/artifacts.py +17 -35
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/cli.py +743 -23
- simulo-0.20.0/src/simulo/_client/export_api.py +205 -0
- simulo-0.20.0/src/simulo/_client/export_bundle.py +296 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/submit_api.py +47 -8
- {simulo-0.19.0 → simulo-0.20.0/src/simulo.egg-info}/PKG-INFO +4 -2
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo.egg-info/SOURCES.txt +2 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo.egg-info/requires.txt +3 -1
- {simulo-0.19.0 → simulo-0.20.0}/MANIFEST.in +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/PYPI.md +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/setup.cfg +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/__init__.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/__init__.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/_entrypoint.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/_mounts.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/_runner.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/asset.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/asset_api.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/asset_package.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/asset_pins.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/builtin_aliases.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/bundle.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/cancel_api.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/config.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/credentials.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/discovery.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/facades.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/http.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/jobs_api.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/learning.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/login.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/mode.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/packaging.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/preflight_api.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/preflight_render.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/registry.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/runtime.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/runtime_display.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/seed_ref.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/stub.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/templates/__init__.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/templates/inference/app.py.tmpl +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/templates/inference/simuloignore.tmpl +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/templates/scenario/app.py.tmpl +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/templates/scenario/simuloignore.tmpl +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/templates/training/app.py.tmpl +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/templates/training/simuloignore.tmpl +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/view_session_api.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/_client/volume.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/callbacks.py +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo/py.typed +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo.egg-info/dependency_links.txt +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo.egg-info/entry_points.txt +0 -0
- {simulo-0.19.0 → simulo-0.20.0}/src/simulo.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simulo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.20.0
|
|
4
4
|
Summary: Simulo SDK and CLI — define robotics simulation and training apps in Python and run them on the Simulo cloud.
|
|
5
5
|
Author-email: Simulo Team <team@simulo.ai>
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
15
15
|
Classifier: Typing :: Typed
|
|
16
16
|
Requires-Python: >=3.11
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: simulo-interfaces<0.
|
|
18
|
+
Requires-Dist: simulo-interfaces<0.15,>=0.14.0
|
|
19
19
|
Requires-Dist: mcap<2,>=1.3
|
|
20
20
|
Requires-Dist: defusedxml>=0.7.1
|
|
21
21
|
Requires-Dist: usd-core<27,>=25.5
|
|
@@ -30,6 +30,8 @@ Requires-Dist: types-defusedxml==0.7.0.20260504; extra == "dev"
|
|
|
30
30
|
Requires-Dist: pytest>=8.2; extra == "dev"
|
|
31
31
|
Requires-Dist: build>=1.2; extra == "dev"
|
|
32
32
|
Requires-Dist: twine>=5.1; extra == "dev"
|
|
33
|
+
Requires-Dist: setuptools>=68; extra == "dev"
|
|
34
|
+
Requires-Dist: wheel; extra == "dev"
|
|
33
35
|
Provides-Extra: release
|
|
34
36
|
Requires-Dist: commitizen>=3.27; extra == "release"
|
|
35
37
|
Requires-Dist: build>=1.2; extra == "release"
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "simulo"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.20.0"
|
|
8
8
|
description = "Simulo SDK and CLI — define robotics simulation and training apps in Python and run them on the Simulo cloud."
|
|
9
9
|
readme = "PYPI.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -26,7 +26,7 @@ classifiers = [
|
|
|
26
26
|
# mcap: used by `simulo recordings` to read back a downloaded recording and
|
|
27
27
|
# verify it (message count) — MIT-licensed, deps only lz4+zstandard.
|
|
28
28
|
dependencies = [
|
|
29
|
-
"simulo-interfaces>=0.
|
|
29
|
+
"simulo-interfaces>=0.14.0,<0.15",
|
|
30
30
|
"mcap>=1.3,<2",
|
|
31
31
|
# Hardened XML parsing for URDF ingestion (USD Asset Catalogs, PR-12 fix
|
|
32
32
|
# loop 2, security NIT): stdlib xml.etree.ElementTree relies on
|
|
@@ -77,6 +77,18 @@ dev = [
|
|
|
77
77
|
"pytest>=8.2",
|
|
78
78
|
"build>=1.2",
|
|
79
79
|
"twine>=5.1",
|
|
80
|
+
# setuptools/wheel: `tests/test_create_wheel_packaging.py` builds a real wheel with
|
|
81
|
+
# `python -m build --wheel --no-isolation`, which reuses THIS interpreter's
|
|
82
|
+
# already-installed setuptools/wheel instead of resolving `[build-system].requires`
|
|
83
|
+
# into a fresh, network-fetched isolated build venv. Constraints mirror
|
|
84
|
+
# `[build-system].requires` above EXACTLY so the two can never drift apart.
|
|
85
|
+
# Without this, `pip install -e ".[dev]"` in a fresh Python 3.12 venv (which no
|
|
86
|
+
# longer bundles setuptools, unlike 3.11 and earlier) leaves that test failing with
|
|
87
|
+
# `Cannot import 'setuptools.build_meta'` — measured 2026-08-12. It passed in CI
|
|
88
|
+
# only because `.github/workflows/simulo-ci.yml` installs `pip setuptools wheel` as
|
|
89
|
+
# its own step, independently of this extra, which masked the gap.
|
|
90
|
+
"setuptools>=68",
|
|
91
|
+
"wheel",
|
|
80
92
|
]
|
|
81
93
|
# `dev` carries build/twine but deliberately not commitizen; `release` below
|
|
82
94
|
# adds commitizen for cutting version bumps without a second build/twine copy.
|
|
@@ -1025,35 +1025,14 @@ class App:
|
|
|
1025
1025
|
|
|
1026
1026
|
Raises:
|
|
1027
1027
|
ValueError: ``timeout`` is not ``None`` and is not a positive
|
|
1028
|
-
integer
|
|
1029
|
-
``worker._effective_job_timeout_s`` guard — bare ``bool`` is
|
|
1030
|
-
excluded even though it is an ``int`` subclass).
|
|
1028
|
+
integer. ``True`` and ``False`` are not accepted as timeouts.
|
|
1031
1029
|
TypeError: ``produces=`` or ``consumes=`` was passed. Outputs are
|
|
1032
|
-
|
|
1033
|
-
already
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
``simulo run --from <job>[:latest|:best]``
|
|
1038
|
-
|
|
1039
|
-
Note this guard is a deliberate BEHAVIOUR CHANGE, not the
|
|
1040
|
-
formalisation of something that already failed. Neither kwarg
|
|
1041
|
-
was ever *supported*, but until PR-B8 both were silently
|
|
1042
|
-
*accepted*: ``**extra`` folded them straight into the job's
|
|
1043
|
-
resource spec, so ``@app.job(produces=["report.html"])``
|
|
1044
|
-
produced ``resources == {"produces": ["report.html"]}`` in
|
|
1045
|
-
every published client — a misconfiguration the user could
|
|
1046
|
-
not see, which is exactly why it is now rejected.
|
|
1047
|
-
|
|
1048
|
-
It is safe because the affected population is empty **by
|
|
1049
|
-
evidence, not by construction**: no use of either kwarg exists
|
|
1050
|
-
in this repo, its history, the demos, or the docs site. The
|
|
1051
|
-
residual regression path is the worker, and it is worth naming
|
|
1052
|
-
— an ALREADY-ARCHIVED package whose source contains
|
|
1053
|
-
``produces=`` now raises this ``TypeError`` at module import
|
|
1054
|
-
on an upgraded runner, before discovery or execution reaches
|
|
1055
|
-
anything else. Weigh that path first if the evidence above
|
|
1056
|
-
ever stops holding.
|
|
1030
|
+
not declared on the decorator. Callbacks such as
|
|
1031
|
+
``ResumableCheckpoint`` already declare their supported
|
|
1032
|
+
outputs. Return small JSON values from the job, or use a named
|
|
1033
|
+
volume for files another job needs. ``consumes=`` is reserved;
|
|
1034
|
+
continue from a checkpoint with
|
|
1035
|
+
``simulo run --from <job>[:latest|:best]`` instead.
|
|
1057
1036
|
"""
|
|
1058
1037
|
if timeout is not None and (isinstance(timeout, bool) or not isinstance(timeout, int) or timeout < 1):
|
|
1059
1038
|
raise ValueError(
|
|
@@ -1062,10 +1041,10 @@ class App:
|
|
|
1062
1041
|
)
|
|
1063
1042
|
if "produces" in extra:
|
|
1064
1043
|
raise TypeError(
|
|
1065
|
-
"@app.job(produces=...) is not supported
|
|
1066
|
-
"
|
|
1067
|
-
"
|
|
1068
|
-
"
|
|
1044
|
+
"@app.job(produces=...) is not supported. Callbacks such as "
|
|
1045
|
+
"ResumableCheckpoint and DebugOnAnomaly already declare their supported outputs. "
|
|
1046
|
+
"Return small JSON values from the job, or use a named Volume for files another "
|
|
1047
|
+
"job needs. Remove produces=."
|
|
1069
1048
|
)
|
|
1070
1049
|
if "consumes" in extra:
|
|
1071
1050
|
raise TypeError(
|
|
@@ -38,30 +38,24 @@ def save_artifact(
|
|
|
38
38
|
path: Union[str, bytes, "os.PathLike[str]", "os.PathLike[bytes]"],
|
|
39
39
|
kind: Union[ArtifactKind, str] = ArtifactKind.FILE,
|
|
40
40
|
) -> bool:
|
|
41
|
-
"""Register a file
|
|
41
|
+
"""Register metadata for a file produced while this job is running.
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
The worker uploads every registered file once the job completes, and it
|
|
50
|
-
appears under the job's artifacts (``simulo artifacts <job>``) with the
|
|
51
|
-
``name`` given here as its filename.
|
|
43
|
+
This validates the name, path, and kind, then records them in the running
|
|
44
|
+
job. The current managed platform does not upload general files registered
|
|
45
|
+
this way, so registration alone does not make the file available through
|
|
46
|
+
``simulo artifacts`` after the job finishes. Return small JSON values from
|
|
47
|
+
the job, use a named :class:`simulo.Volume` for files another job needs, or
|
|
48
|
+
use the supported model and recording workflows for downloadable output.
|
|
52
49
|
|
|
53
50
|
Args:
|
|
54
|
-
name: The
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
(:func:`~simulo.interfaces.platform.artifacts._validate_artifact_name`).
|
|
51
|
+
name: The registration's logical filename. It must be one safe
|
|
52
|
+
filename, never a path: separators, control characters, dots-only
|
|
53
|
+
tokens, empty values, and over-length names are rejected with
|
|
54
|
+
``ValueError``.
|
|
59
55
|
path: Filesystem path of the produced file. ``str``, ``bytes``, or any
|
|
60
56
|
``os.PathLike`` (a ``pathlib.Path`` works); bytes-ish values are
|
|
61
57
|
``os.fsdecode``-d, so a real non-UTF-8 filename registers fine.
|
|
62
|
-
Validated for usability
|
|
63
|
-
it points is contained by the worker's uploader, which skips any
|
|
64
|
-
path outside the job's own artifact roots.
|
|
58
|
+
Validated for usability: type, length, non-empty, and no NUL.
|
|
65
59
|
kind: What the output is — an
|
|
66
60
|
:class:`~simulo.interfaces.platform.enums.ArtifactKind` or its wire
|
|
67
61
|
string (e.g. ``"report"``, ``"dataset"``). Defaults to
|
|
@@ -70,27 +64,15 @@ def save_artifact(
|
|
|
70
64
|
|
|
71
65
|
Returns:
|
|
72
66
|
``True`` when the registration was kept; ``False`` when it was dropped
|
|
73
|
-
because the run already registered
|
|
74
|
-
|
|
75
|
-
step's scratch file is a mistake, and the registry warns once on stderr
|
|
76
|
-
rather than failing the run over bookkeeping.
|
|
67
|
+
because the run already registered 1000 files. Register final output,
|
|
68
|
+
not a new scratch file on every simulation step.
|
|
77
69
|
|
|
78
70
|
Raises:
|
|
79
71
|
ValueError: ``name`` is not a safe single filename, ``path`` is not
|
|
80
72
|
usable as a path, or ``kind`` is not a known artifact kind — all
|
|
81
|
-
surfaced at the call site
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
something else (see below) — one ``except ValueError`` around an
|
|
85
|
-
optional registration is a complete guard.
|
|
86
|
-
ModuleNotFoundError: ``simulo.outputs`` is installed but something IT
|
|
87
|
-
imports is missing (a broken backend install). Propagated as-is
|
|
88
|
-
rather than relabelled, because the missing module is not
|
|
89
|
-
``simulo.outputs``.
|
|
90
|
-
RuntimeError: called where the ``simulo.outputs`` registry is not
|
|
91
|
-
installed (a submit-only environment forced into execution mode) —
|
|
92
|
-
never a supported state; at submit this function is not even
|
|
93
|
-
reachable, the name resolves to a Stub.
|
|
73
|
+
surfaced at the call site before anything is registered.
|
|
74
|
+
ModuleNotFoundError: The job runtime is missing a required dependency.
|
|
75
|
+
RuntimeError: Called outside a supported job execution context.
|
|
94
76
|
"""
|
|
95
77
|
if isinstance(path, (bytes, os.PathLike)):
|
|
96
78
|
# ``os.fsdecode`` maps a bytes / PathLike path to the exact ``str`` the
|