simulo 0.7.0__tar.gz → 0.7.1__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.
Files changed (80) hide show
  1. simulo-0.7.1/MANIFEST.in +9 -0
  2. simulo-0.7.1/PKG-INFO +87 -0
  3. simulo-0.7.1/PYPI.md +56 -0
  4. simulo-0.7.1/pyproject.toml +98 -0
  5. simulo-0.7.1/src/simulo.egg-info/PKG-INFO +87 -0
  6. simulo-0.7.1/src/simulo.egg-info/SOURCES.txt +35 -0
  7. simulo-0.7.0/PKG-INFO +0 -190
  8. simulo-0.7.0/README.md +0 -158
  9. simulo-0.7.0/pyproject.toml +0 -107
  10. simulo-0.7.0/src/simulo.egg-info/PKG-INFO +0 -190
  11. simulo-0.7.0/src/simulo.egg-info/SOURCES.txt +0 -72
  12. simulo-0.7.0/tests/test_callbacks_manifest.py +0 -182
  13. simulo-0.7.0/tests/test_cartpole_e2e.py +0 -203
  14. simulo-0.7.0/tests/test_cartpole_eval_e2e.py +0 -280
  15. simulo-0.7.0/tests/test_cartpole_eval_lean_submit.py +0 -166
  16. simulo-0.7.0/tests/test_cartpole_lean_submit.py +0 -92
  17. simulo-0.7.0/tests/test_cartpole_resume_e2e.py +0 -244
  18. simulo-0.7.0/tests/test_cli.py +0 -252
  19. simulo-0.7.0/tests/test_cli_auth_commands.py +0 -114
  20. simulo-0.7.0/tests/test_cli_env_preset_error.py +0 -85
  21. simulo-0.7.0/tests/test_cli_models.py +0 -794
  22. simulo-0.7.0/tests/test_cli_recordings.py +0 -462
  23. simulo-0.7.0/tests/test_cli_run_cloud.py +0 -152
  24. simulo-0.7.0/tests/test_cloud_submit_e2e.py +0 -253
  25. simulo-0.7.0/tests/test_config.py +0 -121
  26. simulo-0.7.0/tests/test_credentials.py +0 -313
  27. simulo-0.7.0/tests/test_discovery.py +0 -77
  28. simulo-0.7.0/tests/test_discovery_transitive.py +0 -83
  29. simulo-0.7.0/tests/test_fake_control_plane.py +0 -155
  30. simulo-0.7.0/tests/test_hello_submit.py +0 -106
  31. simulo-0.7.0/tests/test_http.py +0 -136
  32. simulo-0.7.0/tests/test_jobs_api.py +0 -271
  33. simulo-0.7.0/tests/test_jobs_cli.py +0 -487
  34. simulo-0.7.0/tests/test_learning_surface.py +0 -450
  35. simulo-0.7.0/tests/test_learning_typing.py +0 -83
  36. simulo-0.7.0/tests/test_local_stream_e2e.py +0 -365
  37. simulo-0.7.0/tests/test_login.py +0 -360
  38. simulo-0.7.0/tests/test_manifest.py +0 -37
  39. simulo-0.7.0/tests/test_manifest_pip_dependencies.py +0 -112
  40. simulo-0.7.0/tests/test_namespace_coexistence_thin.py +0 -24
  41. simulo-0.7.0/tests/test_no_stray_namespace_init.py +0 -32
  42. simulo-0.7.0/tests/test_packaging.py +0 -229
  43. simulo-0.7.0/tests/test_process_retry_e2e.py +0 -150
  44. simulo-0.7.0/tests/test_protocol_conformance.py +0 -53
  45. simulo-0.7.0/tests/test_spawn_cloud.py +0 -247
  46. simulo-0.7.0/tests/test_submit_api.py +0 -279
  47. simulo-0.7.0/tests/test_submit_end_to_end.py +0 -250
  48. simulo-0.7.0/tests/test_submit_handle.py +0 -142
  49. simulo-0.7.0/tests/test_torch_free_import.py +0 -62
  50. {simulo-0.7.0 → simulo-0.7.1}/setup.cfg +0 -0
  51. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/__init__.py +0 -0
  52. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/__init__.py +0 -0
  53. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/_entrypoint.py +0 -0
  54. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/_mounts.py +0 -0
  55. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/_runner.py +0 -0
  56. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/app.py +0 -0
  57. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/asset.py +0 -0
  58. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/bundle.py +0 -0
  59. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/cli.py +0 -0
  60. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/config.py +0 -0
  61. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/credentials.py +0 -0
  62. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/discovery.py +0 -0
  63. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/http.py +0 -0
  64. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/jobs_api.py +0 -0
  65. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/learning.py +0 -0
  66. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/login.py +0 -0
  67. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/manifest.py +0 -0
  68. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/mode.py +0 -0
  69. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/packaging.py +0 -0
  70. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/registry.py +0 -0
  71. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/runtime.py +0 -0
  72. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/stub.py +0 -0
  73. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/submit_api.py +0 -0
  74. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/_client/volume.py +0 -0
  75. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/callbacks.py +0 -0
  76. {simulo-0.7.0 → simulo-0.7.1}/src/simulo/py.typed +0 -0
  77. {simulo-0.7.0 → simulo-0.7.1}/src/simulo.egg-info/dependency_links.txt +0 -0
  78. {simulo-0.7.0 → simulo-0.7.1}/src/simulo.egg-info/entry_points.txt +0 -0
  79. {simulo-0.7.0 → simulo-0.7.1}/src/simulo.egg-info/requires.txt +0 -0
  80. {simulo-0.7.0 → simulo-0.7.1}/src/simulo.egg-info/top_level.txt +0 -0
@@ -0,0 +1,9 @@
1
+ # Public-metadata discretion boundary (see release.yml Guard 5): the sdist is
2
+ # PUBLIC on PyPI's "Download files" page just like the wheel, but setuptools'
3
+ # sdist command auto-includes README.md and any top-level tests/ directory
4
+ # regardless of the `readme = "PYPI.md"` pyproject setting. Exclude the
5
+ # internal docs and test suite explicitly so only PYPI.md ships as prose.
6
+ exclude README.md
7
+ exclude CLAUDE.md
8
+ exclude CHANGELOG.md
9
+ prune tests
simulo-0.7.1/PKG-INFO ADDED
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: simulo
3
+ Version: 0.7.1
4
+ Summary: Simulo SDK and CLI — define robotics simulation and training apps in Python and run them on the Simulo cloud.
5
+ Author-email: Simulo Team <team@simulo.ai>
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://simulo.ai
8
+ Keywords: robotics,simulation,reinforcement-learning,simulo
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: BSD License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Typing :: Typed
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+ Requires-Dist: simulo-interfaces<0.2,>=0.1
19
+ Provides-Extra: dev
20
+ Requires-Dist: black>=24.0; extra == "dev"
21
+ Requires-Dist: isort>=5.13; extra == "dev"
22
+ Requires-Dist: ruff>=0.5; extra == "dev"
23
+ Requires-Dist: mypy>=1.10; extra == "dev"
24
+ Requires-Dist: pytest>=8.2; extra == "dev"
25
+ Requires-Dist: build>=1.2; extra == "dev"
26
+ Requires-Dist: twine>=5.1; extra == "dev"
27
+ Provides-Extra: release
28
+ Requires-Dist: commitizen>=3.27; extra == "release"
29
+ Requires-Dist: build>=1.2; extra == "release"
30
+ Requires-Dist: twine>=5.1; extra == "release"
31
+
32
+ # simulo
33
+
34
+ The Simulo SDK and CLI — define robotics simulation and training apps in Python,
35
+ submit them to the Simulo cloud, monitor jobs, and retrieve trained models.
36
+
37
+ Simulo is a cloud-first robotics simulation and training platform. Write your app
38
+ against a small, stable Python API; Simulo handles running it.
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ pip install simulo
44
+ ```
45
+
46
+ Requires Python 3.11+.
47
+
48
+ ## Quickstart
49
+
50
+ Log in once to submit to the Simulo cloud:
51
+
52
+ ```bash
53
+ simulo login
54
+ ```
55
+
56
+ Write an app:
57
+
58
+ ```python
59
+ # app.py
60
+ import simulo
61
+
62
+ runtime = simulo.Runtime.from_registry("simulo/python-cpu:3.11")
63
+ app = simulo.App("hello", runtime=runtime)
64
+
65
+
66
+ @app.job(timeout=5 * 60)
67
+ def hello(name: str = "world", repeat: int = 3) -> dict:
68
+ for i in range(repeat):
69
+ print(f"[hello] {i + 1}/{repeat}: hello, {name}!")
70
+ return {"greeting": f"hello, {name}", "repeat": repeat}
71
+
72
+
73
+ @app.local_entrypoint
74
+ def main(name: str = "world", repeat: int = 3) -> None:
75
+ handle = hello.spawn(name=name, repeat=repeat)
76
+ print(f"Submitted job: {handle.job_name}")
77
+ ```
78
+
79
+ Run it:
80
+
81
+ ```bash
82
+ simulo run app.py --name robot --repeat 5
83
+ ```
84
+
85
+ Without logging in, `simulo run` packages the app locally without submitting it.
86
+
87
+ Learn more at [simulo.ai](https://simulo.ai).
simulo-0.7.1/PYPI.md ADDED
@@ -0,0 +1,56 @@
1
+ # simulo
2
+
3
+ The Simulo SDK and CLI — define robotics simulation and training apps in Python,
4
+ submit them to the Simulo cloud, monitor jobs, and retrieve trained models.
5
+
6
+ Simulo is a cloud-first robotics simulation and training platform. Write your app
7
+ against a small, stable Python API; Simulo handles running it.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pip install simulo
13
+ ```
14
+
15
+ Requires Python 3.11+.
16
+
17
+ ## Quickstart
18
+
19
+ Log in once to submit to the Simulo cloud:
20
+
21
+ ```bash
22
+ simulo login
23
+ ```
24
+
25
+ Write an app:
26
+
27
+ ```python
28
+ # app.py
29
+ import simulo
30
+
31
+ runtime = simulo.Runtime.from_registry("simulo/python-cpu:3.11")
32
+ app = simulo.App("hello", runtime=runtime)
33
+
34
+
35
+ @app.job(timeout=5 * 60)
36
+ def hello(name: str = "world", repeat: int = 3) -> dict:
37
+ for i in range(repeat):
38
+ print(f"[hello] {i + 1}/{repeat}: hello, {name}!")
39
+ return {"greeting": f"hello, {name}", "repeat": repeat}
40
+
41
+
42
+ @app.local_entrypoint
43
+ def main(name: str = "world", repeat: int = 3) -> None:
44
+ handle = hello.spawn(name=name, repeat=repeat)
45
+ print(f"Submitted job: {handle.job_name}")
46
+ ```
47
+
48
+ Run it:
49
+
50
+ ```bash
51
+ simulo run app.py --name robot --repeat 5
52
+ ```
53
+
54
+ Without logging in, `simulo run` packages the app locally without submitting it.
55
+
56
+ Learn more at [simulo.ai](https://simulo.ai).
@@ -0,0 +1,98 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "simulo"
7
+ version = "0.7.1"
8
+ description = "Simulo SDK and CLI — define robotics simulation and training apps in Python and run them on the Simulo cloud."
9
+ readme = "PYPI.md"
10
+ requires-python = ">=3.11"
11
+ license = { text = "BSD-3-Clause" }
12
+ authors = [{ name = "Simulo Team", email = "team@simulo.ai" }]
13
+ keywords = ["robotics", "simulation", "reinforcement-learning", "simulo"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: BSD License",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Typing :: Typed",
22
+ ]
23
+ # Torch-free by construction: depends only on the contract layer. Heavy
24
+ # imports (e.g. torch) belong inside the user's `runtime.imports()` guard,
25
+ # resolved only at job-execution time — never in this distribution.
26
+ dependencies = ["simulo-interfaces>=0.1,<0.2"]
27
+
28
+ [project.optional-dependencies]
29
+ dev = ["black>=24.0", "isort>=5.13", "ruff>=0.5", "mypy>=1.10", "pytest>=8.2", "build>=1.2", "twine>=5.1"]
30
+ # `dev` carries build/twine but deliberately not commitizen; `release` below
31
+ # adds commitizen for cutting version bumps without a second build/twine copy.
32
+ release = ["commitizen>=3.27", "build>=1.2", "twine>=5.1"]
33
+
34
+ [project.scripts]
35
+ simulo = "simulo._client.cli:main"
36
+
37
+ [project.urls]
38
+ Homepage = "https://simulo.ai"
39
+
40
+ # Namespace packaging: this is the only distribution that ships
41
+ # `src/simulo/__init__.py`, so sibling `simulo.*` distributions can share the
42
+ # top-level `simulo` name — do not add another top-level __init__.py to a
43
+ # sibling distribution. `namespaces = true` keeps setuptools from choking on
44
+ # the shared top-level name.
45
+ [tool.setuptools.packages.find]
46
+ where = ["src"]
47
+ namespaces = true
48
+
49
+ [tool.setuptools.package-data]
50
+ "simulo" = ["py.typed"]
51
+
52
+ [tool.mypy]
53
+ python_version = "3.11"
54
+ mypy_path = ["src"]
55
+ namespace_packages = true
56
+ explicit_package_bases = true
57
+ strict = true
58
+
59
+ [tool.pytest.ini_options]
60
+ testpaths = ["tests"]
61
+ addopts = "--import-mode=importlib"
62
+ markers = [
63
+ "isaac: requires NVIDIA Isaac Sim / IsaacLab (skipped on dev machines and in PR CI)",
64
+ "gpu: requires a CUDA GPU (skipped on dev machines and in PR CI)",
65
+ ]
66
+
67
+ [tool.isort]
68
+ profile = "black"
69
+ line_length = 120
70
+ known_first_party = ["simulo"]
71
+
72
+ [tool.ruff]
73
+ line-length = 120
74
+ src = ["src"]
75
+
76
+ [tool.black]
77
+ line-length = 120
78
+ target-version = ["py311"]
79
+
80
+ # --- Commitizen ------------------------------------------------------------
81
+ # `cz bump` creates the version-bump commit + tag locally; CI publishes to
82
+ # PyPI on tag push. version_provider = "pep621" reads/writes [project].version
83
+ # directly; there is no in-tree __version__ mirror to keep in sync
84
+ # (version_files = []).
85
+ #
86
+ # The FIRST release (0.7.0) was a hand-written bump commit, not `cz bump` —
87
+ # 0.1.0 -> 0.7.0 is not a conventional-commit increment. 0.7.0 (not 0.2.0) is
88
+ # deliberate: it intentionally exceeds a version already published under this
89
+ # same PyPI project name, so `pip install simulo` resolves to this package.
90
+ [tool.commitizen]
91
+ name = "cz_conventional_commits"
92
+ version_provider = "pep621"
93
+ version_files = []
94
+ tag_format = "simulo-v$version"
95
+ update_changelog_on_bump = true
96
+ changelog_incremental = true
97
+ major_version_zero = true
98
+ bump_message = "chore(release): bump simulo to v$new_version"
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: simulo
3
+ Version: 0.7.1
4
+ Summary: Simulo SDK and CLI — define robotics simulation and training apps in Python and run them on the Simulo cloud.
5
+ Author-email: Simulo Team <team@simulo.ai>
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://simulo.ai
8
+ Keywords: robotics,simulation,reinforcement-learning,simulo
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: BSD License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Typing :: Typed
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+ Requires-Dist: simulo-interfaces<0.2,>=0.1
19
+ Provides-Extra: dev
20
+ Requires-Dist: black>=24.0; extra == "dev"
21
+ Requires-Dist: isort>=5.13; extra == "dev"
22
+ Requires-Dist: ruff>=0.5; extra == "dev"
23
+ Requires-Dist: mypy>=1.10; extra == "dev"
24
+ Requires-Dist: pytest>=8.2; extra == "dev"
25
+ Requires-Dist: build>=1.2; extra == "dev"
26
+ Requires-Dist: twine>=5.1; extra == "dev"
27
+ Provides-Extra: release
28
+ Requires-Dist: commitizen>=3.27; extra == "release"
29
+ Requires-Dist: build>=1.2; extra == "release"
30
+ Requires-Dist: twine>=5.1; extra == "release"
31
+
32
+ # simulo
33
+
34
+ The Simulo SDK and CLI — define robotics simulation and training apps in Python,
35
+ submit them to the Simulo cloud, monitor jobs, and retrieve trained models.
36
+
37
+ Simulo is a cloud-first robotics simulation and training platform. Write your app
38
+ against a small, stable Python API; Simulo handles running it.
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ pip install simulo
44
+ ```
45
+
46
+ Requires Python 3.11+.
47
+
48
+ ## Quickstart
49
+
50
+ Log in once to submit to the Simulo cloud:
51
+
52
+ ```bash
53
+ simulo login
54
+ ```
55
+
56
+ Write an app:
57
+
58
+ ```python
59
+ # app.py
60
+ import simulo
61
+
62
+ runtime = simulo.Runtime.from_registry("simulo/python-cpu:3.11")
63
+ app = simulo.App("hello", runtime=runtime)
64
+
65
+
66
+ @app.job(timeout=5 * 60)
67
+ def hello(name: str = "world", repeat: int = 3) -> dict:
68
+ for i in range(repeat):
69
+ print(f"[hello] {i + 1}/{repeat}: hello, {name}!")
70
+ return {"greeting": f"hello, {name}", "repeat": repeat}
71
+
72
+
73
+ @app.local_entrypoint
74
+ def main(name: str = "world", repeat: int = 3) -> None:
75
+ handle = hello.spawn(name=name, repeat=repeat)
76
+ print(f"Submitted job: {handle.job_name}")
77
+ ```
78
+
79
+ Run it:
80
+
81
+ ```bash
82
+ simulo run app.py --name robot --repeat 5
83
+ ```
84
+
85
+ Without logging in, `simulo run` packages the app locally without submitting it.
86
+
87
+ Learn more at [simulo.ai](https://simulo.ai).
@@ -0,0 +1,35 @@
1
+ MANIFEST.in
2
+ PYPI.md
3
+ pyproject.toml
4
+ src/simulo/__init__.py
5
+ src/simulo/callbacks.py
6
+ src/simulo/py.typed
7
+ src/simulo.egg-info/PKG-INFO
8
+ src/simulo.egg-info/SOURCES.txt
9
+ src/simulo.egg-info/dependency_links.txt
10
+ src/simulo.egg-info/entry_points.txt
11
+ src/simulo.egg-info/requires.txt
12
+ src/simulo.egg-info/top_level.txt
13
+ src/simulo/_client/__init__.py
14
+ src/simulo/_client/_entrypoint.py
15
+ src/simulo/_client/_mounts.py
16
+ src/simulo/_client/_runner.py
17
+ src/simulo/_client/app.py
18
+ src/simulo/_client/asset.py
19
+ src/simulo/_client/bundle.py
20
+ src/simulo/_client/cli.py
21
+ src/simulo/_client/config.py
22
+ src/simulo/_client/credentials.py
23
+ src/simulo/_client/discovery.py
24
+ src/simulo/_client/http.py
25
+ src/simulo/_client/jobs_api.py
26
+ src/simulo/_client/learning.py
27
+ src/simulo/_client/login.py
28
+ src/simulo/_client/manifest.py
29
+ src/simulo/_client/mode.py
30
+ src/simulo/_client/packaging.py
31
+ src/simulo/_client/registry.py
32
+ src/simulo/_client/runtime.py
33
+ src/simulo/_client/stub.py
34
+ src/simulo/_client/submit_api.py
35
+ src/simulo/_client/volume.py
simulo-0.7.0/PKG-INFO DELETED
@@ -1,190 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: simulo
3
- Version: 0.7.0
4
- Summary: Simulo thin client — the Modal-inspired, torch-free user-facing SDK. Provides simulo.App / Runtime / Volume / Asset, @app.job, the source packager, and the `simulo` CLI. Depends only on simulo-interfaces.
5
- Author-email: Simulo Team <team@simulo.ai>
6
- License: BSD-3-Clause
7
- Project-URL: Homepage, https://simulo.ai
8
- Project-URL: Source, https://github.com/simulo-org/simulo-platform
9
- Keywords: robotics,simulation,reinforcement-learning,thin-client,simulo
10
- Classifier: Development Status :: 3 - Alpha
11
- Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: BSD License
13
- Classifier: Operating System :: OS Independent
14
- Classifier: Programming Language :: Python :: 3.11
15
- Classifier: Programming Language :: Python :: 3.12
16
- Classifier: Typing :: Typed
17
- Requires-Python: >=3.11
18
- Description-Content-Type: text/markdown
19
- Requires-Dist: simulo-interfaces<0.2,>=0.1
20
- Provides-Extra: dev
21
- Requires-Dist: black>=24.0; extra == "dev"
22
- Requires-Dist: isort>=5.13; extra == "dev"
23
- Requires-Dist: ruff>=0.5; extra == "dev"
24
- Requires-Dist: mypy>=1.10; extra == "dev"
25
- Requires-Dist: pytest>=8.2; extra == "dev"
26
- Requires-Dist: build>=1.2; extra == "dev"
27
- Requires-Dist: twine>=5.1; extra == "dev"
28
- Provides-Extra: release
29
- Requires-Dist: commitizen>=3.27; extra == "release"
30
- Requires-Dist: build>=1.2; extra == "release"
31
- Requires-Dist: twine>=5.1; extra == "release"
32
-
33
- # simulo
34
-
35
- The Simulo **thin client** — the Modal-inspired, user-facing SDK you install with
36
- `pip install simulo`.
37
-
38
- This distribution is **platform-only and torch-free**. It provides the cloud/packaging
39
- surface and depends only on [`simulo-interfaces`](../simulo-interfaces):
40
-
41
- - `simulo.App`, `simulo.Runtime`, `simulo.Volume`, `simulo.Asset`
42
- - `@app.job` and `@app.local_entrypoint`
43
- - `simulo.callbacks` (`ResumableCheckpoint`, `CommitVolume`, `DebugOnAnomaly`)
44
- - the source **packager** and the `simulo run` CLI (submit)
45
-
46
- Heavy imports (`torch`, Isaac, …) never live in this package. They are written inside the
47
- user's `runtime.imports()` guard and resolved only during **execution** — by the
48
- `simulo-backend` runner today (the local-simulation stand-in for the cloud worker), and by
49
- the cloud worker eventually.
50
-
51
- ## Submit vs. execute
52
-
53
- Submit and execute are cleanly separated:
54
-
55
- | Step | Who | What it does |
56
- |------|-----|--------------|
57
- | **Submit** | the user (`simulo run app.py`) | runs `@app.local_entrypoint` in discovery mode (torch-free) → `spawn()`/`submit()` **write the package** (manifest + `source/`) to disk — and, in cloud mode, upload it + create a job on the control plane. NEVER trains, NEVER invokes the backend. |
58
- | **Execute** | `simulo-backend run-package` (worker/system launcher; the **sole executor**) | imports the packaged source in execution mode and calls the `@app.job` — the real training. Invoked directly for the local simulation, and by `simulo-backend worker` in the cloud. |
59
-
60
- ## Offline vs. cloud mode
61
-
62
- The SAME `simulo run` serves both; the presence of a cloud target selects the mode:
63
-
64
- | Mode | When | What `spawn()` does |
65
- |------|------|---------------------|
66
- | **Offline (local disk)** | no credentials, no `SIMULO_API_URL`/`SIMULO_ENV` — or `SIMULO_SUBMIT=local` forces it | writes the package to disk; you execute it yourself with `simulo-backend run-package` |
67
- | **Cloud** | logged in (`simulo login`), or `SIMULO_API_URL`/`SIMULO_ENV` names a target | ALSO tars + uploads the package (`POST /v1/packages` + archive PUT) and creates a job (`POST /v1/jobs`); `simulo run` then follows the job's logs to completion by default (`--detach` to skip), and `JobHandle.get()` polls the platform for the real result |
68
-
69
- Cloud quickstart (staging):
70
-
71
- ```bash
72
- SIMULO_ENV=staging simulo login # OAuth PKCE via browser loopback -> ~/.simulo/credentials (0600)
73
- simulo run examples/hello/app.py # uploads, creates the job, follows its logs
74
- simulo result # the job's result JSON
75
- ```
76
-
77
- A worker must be polling the control plane to execute cloud jobs — on a GPU box:
78
-
79
- ```bash
80
- SIMULO_API_URL=https://api.staging.simulo.ai SIMULO_WORKER_TOKEN=<token> \
81
- simulo-backend worker # claim -> download -> run-package -> stream logs -> complete
82
- ```
83
-
84
- The full demo script (staging AND the zero-AWS local stack) is
85
- `context/verification-steps/cloud-submit-demo-runbook.md`; the automated full-stack
86
- proof is `tests/integration/` at the repo root (markers `cp_integration` / `cloud_e2e`).
87
-
88
- This mirrors Modal: the runtime imports the module and calls the function; it does **not**
89
- run `python app.py`. The job body the author wrote runs unchanged (source-preserving).
90
-
91
- ## Namespace
92
-
93
- `simulo` is a **hybrid namespace**. The thin client is the only distribution that ships
94
- `simulo/__init__.py`; it calls `pkgutil.extend_path` so the PEP 420 namespace portions
95
- shipped by `simulo-backend` (`simulo.core`, `simulo.backend`, `simulo.recording`) and
96
- `simulo-interfaces` (`simulo.interfaces`) coexist under the same top-level `simulo`.
97
-
98
- ## Modes
99
-
100
- A single mode-aware package, driven by `SIMULO_MODE`:
101
-
102
- | Mode | `runtime.imports()` |
103
- |------|---------------------|
104
- | `discovery` (default) | installs a stub import finder, records deferred top-level imports, runs no job body — the torch-free **submit** path |
105
- | `execution` | `contextlib.nullcontext()` — real imports; set explicitly by the `simulo-backend` runner when it **executes** a package |
106
-
107
- Discovery is the default so any bare `import` of a user app stays torch-free; `simulo
108
- run` submits on that default. Execution is only ever set by the sole executor
109
- (`simulo-backend run-package`).
110
-
111
- ## One user command — submit
112
-
113
- `simulo run` is the canonical — and only — submit command:
114
-
115
- ```bash
116
- simulo run app.py --num-envs 4096 --max-iterations 200
117
- ```
118
-
119
- It runs the `@app.local_entrypoint` in discovery mode (torch-free). Its `spawn()` /
120
- `submit()` calls **write the package** — a content-addressed `<digest>/source/` tree plus
121
- `<digest>/simulo.manifest.json` — and print where it landed. The manifest records the
122
- entrypoint, runtime image + env, jobs (resources/timeout/retries/resume), volumes, the
123
- submitted `args`, and the deferred `remote_imports` (e.g. `["torch"]`). `spawn()` returns
124
- a `JobHandle` exposing `.package_path` / `.job_id`; it does **not** return a result —
125
- submit never trains.
126
-
127
- `simulo run` imports the file as a non-`__main__` module and invokes the registered
128
- entrypoint explicitly (argparse is built from its signature; `--num-envs` maps to the
129
- `num_envs` parameter). A direct `python app.py` does **not** submit:
130
- `@app.local_entrypoint` detects the `__main__` run, prints the exact equivalent
131
- `simulo run` command to stderr, and exits 2 — so a script wrapping the `python` form
132
- fails loudly instead of silently not submitting.
133
-
134
- ## Execute (the sole executor)
135
-
136
- Submit does not train. Executing a package is a separate step owned entirely by the
137
- `simulo-backend` runner — a worker/system launcher surfaced as a CLI today only for the
138
- local simulation:
139
-
140
- ```bash
141
- simulo-backend run-package <package> --job train
142
- ```
143
-
144
- It imports the same packaged source in execution mode and calls the `@app.job` body —
145
- resolving the real `torch` / Isaac imports there. (Eventually the cloud worker invokes it
146
- and `JobHandle.get()` streams the result back; today `get()` raises a friendly
147
- `JobResultUnavailable` pointing at the package + the execute command.) Executing locally
148
- therefore needs the GPU runtime installed (`pip install simulo-backend`). See
149
- [`examples/cartpole`](examples/cartpole/) for a full, GPU-proven submit → execute walkthrough.
150
-
151
- ## Observe — `simulo jobs` / `simulo logs` / `simulo result`
152
-
153
- Once a package executes, the thin client observes it **over HTTP only** — it never reads
154
- the executor's run store from disk. Submit/observe and execute behave as if on **two
155
- separate machines**: eventually a cloud event triggers execution and the client streams
156
- from the real control plane; locally, *you* are that cloud event, and a deliberately-thin
157
- stdlib server stands in for the control plane. The wire contract (job-record schema, the
158
- four `GET /v1/jobs*` endpoints, byte-offset log semantics) is the durable piece — it
159
- lives in `simulo.interfaces.platform.runs` and survives the move to the real cloud.
160
-
161
- The two-terminal story on one box:
162
-
163
- ```bash
164
- # Terminal B — the "pretend cloud" (needs simulo-backend installed):
165
- simulo-backend serve # local stand-in for the cloud jobs API (127.0.0.1)
166
- simulo-backend run-package <package> --job train # you are the cloud event; prints SIMULO_JOB_ID=<id> first
167
-
168
- # Terminal A — the user's machine (torch-free thin client, HTTP only):
169
- simulo run app.py --num-envs 64 # submit: writes the package (never executes)
170
- simulo logs <job-id> --follow # stream live training output; exits 0/1 with the job
171
- simulo result <job-id> # the job's result JSON (404->error until success)
172
- simulo jobs # table of runs: id, job, status, started, exit
173
- ```
174
-
175
- Notes:
176
-
177
- - The **job id is printed by `run-package` at execution** (first line,
178
- `SIMULO_JOB_ID=...`), not at submit — a run only exists once execution starts.
179
- - `simulo logs <id> --follow` on a job that does not exist *yet* waits for it to appear,
180
- so you can arm the tail in terminal A before triggering `run-package` in terminal B.
181
- - Reconnecting is just re-reading: log chunks are addressed by **byte offset**, so a new
182
- `simulo logs <id>` replays the full stream from 0.
183
- - `SIMULO_API_URL` points the client at a different API (default
184
- `http://127.0.0.1:8765`); `SIMULO_API_TOKEN`, when set, is sent as a bearer token.
185
- With credentials saved by `simulo login`, their token + recorded `api_base_url`
186
- are used instead. Bearer over plaintext `http://` is refused for any
187
- non-loopback host (the https-when-token guard).
188
- - `simulo recordings <job-id> [name|--all] [-o PATH]` downloads a job's MCAP
189
- recording(s) via a presigned URL (`GET /v1/jobs/{id}/recordings`) — open them in
190
- Lichtblick or read them with the `mcap` library.