runops 2.1.1__tar.gz → 2.1.2__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 (131) hide show
  1. {runops-2.1.1 → runops-2.1.2}/PKG-INFO +1 -1
  2. {runops-2.1.1 → runops-2.1.2}/pyproject.toml +1 -1
  3. {runops-2.1.1 → runops-2.1.2}/src/runops/__init__.py +1 -1
  4. {runops-2.1.1 → runops-2.1.2}/src/runops/cli.py +19 -3
  5. {runops-2.1.1 → runops-2.1.2}/tests/test_setup_misc.py +46 -0
  6. {runops-2.1.1 → runops-2.1.2}/uv.lock +1 -1
  7. {runops-2.1.1 → runops-2.1.2}/.agents/skills/check/SKILL.md +0 -0
  8. {runops-2.1.1 → runops-2.1.2}/.agents/skills/improve-harness/SKILL.md +0 -0
  9. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/SKILL.md +0 -0
  10. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/agents/openai.yaml +0 -0
  11. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/examples/refactor-request.md +0 -0
  12. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/references/anti-patterns.md +0 -0
  13. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/references/api-compatibility.md +0 -0
  14. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/references/packaging-modernization.md +0 -0
  15. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/references/refactor-playbook.md +0 -0
  16. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/references/verification.md +0 -0
  17. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/scripts/api_surface_snapshot.py +0 -0
  18. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/scripts/import_smoke.py +0 -0
  19. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/scripts/inspect_python_package.py +0 -0
  20. {runops-2.1.1 → runops-2.1.2}/.agents/skills/python-package-refactor/scripts/refactor_quality_gate.py +0 -0
  21. {runops-2.1.1 → runops-2.1.2}/.agents/skills/release/SKILL.md +0 -0
  22. {runops-2.1.1 → runops-2.1.2}/.agents/skills/simulator-adapter/SKILL.md +0 -0
  23. {runops-2.1.1 → runops-2.1.2}/.agents/skills/spec-reviewer/SKILL.md +0 -0
  24. {runops-2.1.1 → runops-2.1.2}/.agents/skills/sync-docs/SKILL.md +0 -0
  25. {runops-2.1.1 → runops-2.1.2}/.claude/agents/spec-reviewer.md +0 -0
  26. {runops-2.1.1 → runops-2.1.2}/.claude/rules/architecture.md +0 -0
  27. {runops-2.1.1 → runops-2.1.2}/.claude/rules/dev-workflow.md +0 -0
  28. {runops-2.1.1 → runops-2.1.2}/.claude/rules/gotchas.md +0 -0
  29. {runops-2.1.1 → runops-2.1.2}/.claude/settings.json +0 -0
  30. {runops-2.1.1 → runops-2.1.2}/.claude/skills/check/SKILL.md +0 -0
  31. {runops-2.1.1 → runops-2.1.2}/.claude/skills/improve-harness/SKILL.md +0 -0
  32. {runops-2.1.1 → runops-2.1.2}/.claude/skills/python-package-refactor/SKILL.md +0 -0
  33. {runops-2.1.1 → runops-2.1.2}/.claude/skills/release/SKILL.md +0 -0
  34. {runops-2.1.1 → runops-2.1.2}/.claude/skills/simulator-adapter/SKILL.md +0 -0
  35. {runops-2.1.1 → runops-2.1.2}/.claude/skills/spec-reviewer/SKILL.md +0 -0
  36. {runops-2.1.1 → runops-2.1.2}/.claude/skills/sync-docs/SKILL.md +0 -0
  37. {runops-2.1.1 → runops-2.1.2}/.codex/README.md +0 -0
  38. {runops-2.1.1 → runops-2.1.2}/.codex/agents/spec-reviewer.toml +0 -0
  39. {runops-2.1.1 → runops-2.1.2}/.codex/config.toml +0 -0
  40. {runops-2.1.1 → runops-2.1.2}/.codex/rules/runops.rules +0 -0
  41. {runops-2.1.1 → runops-2.1.2}/.dockerignore +0 -0
  42. {runops-2.1.1 → runops-2.1.2}/.gitattributes +0 -0
  43. {runops-2.1.1 → runops-2.1.2}/.github/assets/conversation-dark.svg +0 -0
  44. {runops-2.1.1 → runops-2.1.2}/.github/assets/conversation-light.svg +0 -0
  45. {runops-2.1.1 → runops-2.1.2}/.github/assets/hero-dark.svg +0 -0
  46. {runops-2.1.1 → runops-2.1.2}/.github/assets/hero-light.svg +0 -0
  47. {runops-2.1.1 → runops-2.1.2}/.github/assets/make_readme_art.py +0 -0
  48. {runops-2.1.1 → runops-2.1.2}/.github/workflows/ci.yml +0 -0
  49. {runops-2.1.1 → runops-2.1.2}/.github/workflows/publish.yml +0 -0
  50. {runops-2.1.1 → runops-2.1.2}/.gitignore +0 -0
  51. {runops-2.1.1 → runops-2.1.2}/.harness/manifest.toml +0 -0
  52. {runops-2.1.1 → runops-2.1.2}/.pre-commit-config.yaml +0 -0
  53. {runops-2.1.1 → runops-2.1.2}/.vscode/settings.json +0 -0
  54. {runops-2.1.1 → runops-2.1.2}/AGENTS.md +0 -0
  55. {runops-2.1.1 → runops-2.1.2}/CLAUDE.md +0 -0
  56. {runops-2.1.1 → runops-2.1.2}/LICENSE +0 -0
  57. {runops-2.1.1 → runops-2.1.2}/README.md +0 -0
  58. {runops-2.1.1 → runops-2.1.2}/SPEC.md +0 -0
  59. {runops-2.1.1 → runops-2.1.2}/docs/adapter.md +0 -0
  60. {runops-2.1.1 → runops-2.1.2}/docs/reference.md +0 -0
  61. {runops-2.1.1 → runops-2.1.2}/src/runops/adapters/__init__.py +0 -0
  62. {runops-2.1.1 → runops-2.1.2}/src/runops/adapters/base.py +0 -0
  63. {runops-2.1.1 → runops-2.1.2}/src/runops/adapters/generic.py +0 -0
  64. {runops-2.1.1 → runops-2.1.2}/src/runops/adapters/registry.py +0 -0
  65. {runops-2.1.1 → runops-2.1.2}/src/runops/case.py +0 -0
  66. {runops-2.1.1 → runops-2.1.2}/src/runops/config.py +0 -0
  67. {runops-2.1.1 → runops-2.1.2}/src/runops/errors.py +0 -0
  68. {runops-2.1.1 → runops-2.1.2}/src/runops/harness.py +0 -0
  69. {runops-2.1.1 → runops-2.1.2}/src/runops/jobgen.py +0 -0
  70. {runops-2.1.1 → runops-2.1.2}/src/runops/launchers.py +0 -0
  71. {runops-2.1.1 → runops-2.1.2}/src/runops/legacy_adapters/__init__.py +0 -0
  72. {runops-2.1.1 → runops-2.1.2}/src/runops/legacy_adapters/beach.py +0 -0
  73. {runops-2.1.1 → runops-2.1.2}/src/runops/legacy_adapters/emses.py +0 -0
  74. {runops-2.1.1 → runops-2.1.2}/src/runops/manifest.py +0 -0
  75. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/__init__.py +0 -0
  76. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/common.py +0 -0
  77. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/create.py +0 -0
  78. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/listing.py +0 -0
  79. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/migrate.py +0 -0
  80. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/notes.py +0 -0
  81. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/setup.py +0 -0
  82. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/skills.py +0 -0
  83. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/submit.py +0 -0
  84. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/sync.py +0 -0
  85. {runops-2.1.1 → runops-2.1.2}/src/runops/ops/tidy.py +0 -0
  86. {runops-2.1.1 → runops-2.1.2}/src/runops/project.py +0 -0
  87. {runops-2.1.1 → runops-2.1.2}/src/runops/runtime.py +0 -0
  88. {runops-2.1.1 → runops-2.1.2}/src/runops/skills/runops-check-status/SKILL.md +0 -0
  89. {runops-2.1.1 → runops-2.1.2}/src/runops/skills/runops-create-run/SKILL.md +0 -0
  90. {runops-2.1.1 → runops-2.1.2}/src/runops/skills/runops-maintain/SKILL.md +0 -0
  91. {runops-2.1.1 → runops-2.1.2}/src/runops/skills/runops-reference/SKILL.md +0 -0
  92. {runops-2.1.1 → runops-2.1.2}/src/runops/skills/runops-tidy/SKILL.md +0 -0
  93. {runops-2.1.1 → runops-2.1.2}/src/runops/slurm.py +0 -0
  94. {runops-2.1.1 → runops-2.1.2}/src/runops/util.py +0 -0
  95. {runops-2.1.1 → runops-2.1.2}/tests/__init__.py +0 -0
  96. {runops-2.1.1 → runops-2.1.2}/tests/conftest.py +0 -0
  97. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/.codex/rules/a.md +0 -0
  98. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/.runops/test-runs/T20260701-0001/receipt.toml +0 -0
  99. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/.runops/work/beach-x-abc/bin/beach +0 -0
  100. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/AGENTS.md +0 -0
  101. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/CLAUDE.md +0 -0
  102. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/cases/beach/plane/beach.toml +0 -0
  103. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/cases/beach/plane/case.toml +0 -0
  104. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/cases/old/beach.toml +0 -0
  105. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/cases/old/case.toml +0 -0
  106. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/launchers.toml +0 -0
  107. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/research/CURRENT.md +0 -0
  108. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/runops.toml +0 -0
  109. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/runs/AGENTS.md +0 -0
  110. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/runs/_archive/plane/R20260601-0001/manifest.toml +0 -0
  111. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/runs/plane/R20260701-0001--a/input/beach.toml +0 -0
  112. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/runs/plane/R20260701-0001--a/manifest.toml +0 -0
  113. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/runs/plane/R20260702-0001/manifest.toml +0 -0
  114. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/runs/scan/R20260701-0002/manifest.toml +0 -0
  115. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/runs/scan/survey.toml +0 -0
  116. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/simulators.toml +0 -0
  117. {runops-2.1.1 → runops-2.1.2}/tests/fixtures/v1-project/site.toml +0 -0
  118. {runops-2.1.1 → runops-2.1.2}/tests/golden/mpi_standard.sh +0 -0
  119. {runops-2.1.1 → runops-2.1.2}/tests/golden/openmp_rsc.sh +0 -0
  120. {runops-2.1.1 → runops-2.1.2}/tests/test_adapters.py +0 -0
  121. {runops-2.1.1 → runops-2.1.2}/tests/test_build.py +0 -0
  122. {runops-2.1.1 → runops-2.1.2}/tests/test_dev_harness.py +0 -0
  123. {runops-2.1.1 → runops-2.1.2}/tests/test_jobgen.py +0 -0
  124. {runops-2.1.1 → runops-2.1.2}/tests/test_legacy_adapters.py +0 -0
  125. {runops-2.1.1 → runops-2.1.2}/tests/test_lifecycle.py +0 -0
  126. {runops-2.1.1 → runops-2.1.2}/tests/test_manifest_config.py +0 -0
  127. {runops-2.1.1 → runops-2.1.2}/tests/test_migrate.py +0 -0
  128. {runops-2.1.1 → runops-2.1.2}/tests/test_scratch_tidy.py +0 -0
  129. {runops-2.1.1 → runops-2.1.2}/tests/test_skills.py +0 -0
  130. {runops-2.1.1 → runops-2.1.2}/tests/test_sweep.py +0 -0
  131. {runops-2.1.1 → runops-2.1.2}/tests/test_sync_evidence.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: runops
3
- Version: 2.1.1
3
+ Version: 2.1.2
4
4
  Summary: Run ledger and Slurm job submission for HPC simulation projects
5
5
  Project-URL: Homepage, https://github.com/Nkzono99/runops
6
6
  Project-URL: Documentation, https://github.com/Nkzono99/runops/blob/main/docs/reference.md
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "runops"
7
- version = "2.1.1"
7
+ version = "2.1.2"
8
8
  description = "Run ledger and Slurm job submission for HPC simulation projects"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -1,3 +1,3 @@
1
1
  """runops: run ledger and Slurm job submission for HPC simulation projects."""
2
2
 
3
- __version__ = "2.1.1"
3
+ __version__ = "2.1.2"
@@ -91,6 +91,19 @@ def _confirm(message: str, yes: bool) -> None:
91
91
  raise typer.Exit(1)
92
92
 
93
93
 
94
+ def _ask_install(root: Path, yes: bool) -> bool:
95
+ """Ask before creating .venv; default yes. Off a terminal, require -y."""
96
+ message = (
97
+ f"Create .venv in {root} and install simulator packages "
98
+ "(may build simulator binaries and take several minutes)?"
99
+ )
100
+ if yes:
101
+ return True
102
+ if not sys.stdin.isatty():
103
+ raise UsageError(f"{message} -- confirmation required; rerun with -y/--yes or --no-install")
104
+ return bool(typer.confirm(message, default=True))
105
+
106
+
94
107
  def _resolve(project: Project, refs: list[str]) -> list[Manifest]:
95
108
  if not refs:
96
109
  raise UsageError("give at least one RUN")
@@ -133,11 +146,14 @@ def init(
133
146
  show_default=False,
134
147
  )
135
148
  sims = [s.strip() for s in answer.split(",") if s.strip()]
136
- if sims and not no_install and any(s.split("=")[0] != "generic" for s in sims):
137
- _confirm(f"Create .venv in {root} and install simulator packages?", yes)
138
- report = init_project(root, sims, site=site, name=name, install=not no_install)
149
+ install = not no_install
150
+ if sims and install and any(s.split("=")[0] != "generic" for s in sims):
151
+ install = _ask_install(root, yes)
152
+ report = init_project(root, sims, site=site, name=name, install=install)
139
153
  if report.site_detected:
140
154
  out.print(f"site: {report.site} (guessed from host {hostname()}; use --site to change)")
155
+ if not install and not no_install:
156
+ out.print("packages not installed; ask your agent or run `runo update` later")
141
157
  for item in report.created:
142
158
  out.print(f"created {item}")
143
159
  for spec in report.installed:
@@ -165,3 +165,49 @@ def test_usage_error_exit_code(cli) -> None: # type: ignore[no-untyped-def]
165
165
  def test_cli_does_not_import_click_directly() -> None:
166
166
  source = (Path(__file__).parents[1] / "src/runops/cli.py").read_text()
167
167
  assert "import click" not in source # newer typer vendors click
168
+
169
+
170
+ def test_init_install_prompt_defaults_to_yes(
171
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch, cli
172
+ ) -> None: # type: ignore[no-untyped-def]
173
+ calls: list[bool] = []
174
+
175
+ def fake_install(project, *, upgrade): # type: ignore[no-untyped-def]
176
+ calls.append(upgrade)
177
+ return ["MPIEMSES3D"], []
178
+
179
+ monkeypatch.setattr("runops.ops.setup.install_packages", fake_install)
180
+ monkeypatch.chdir(tmp_path)
181
+ monkeypatch.setattr(
182
+ "sys.stdin", _Tty("\nemses\n\n")
183
+ ) # site: Enter, sims: emses, install: Enter
184
+ res = cli("init")
185
+ assert res.code == 0, res.err
186
+ assert "may build simulator binaries" in res.out
187
+ assert "[Y/n]" in res.out
188
+ assert calls == [False]
189
+ assert "installed MPIEMSES3D" in res.out
190
+
191
+
192
+ def test_init_install_declined_keeps_project(
193
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch, cli
194
+ ) -> None: # type: ignore[no-untyped-def]
195
+ monkeypatch.setattr(
196
+ "runops.ops.setup.install_packages",
197
+ lambda project, *, upgrade: (_ for _ in ()).throw(AssertionError("must not install")),
198
+ )
199
+ monkeypatch.chdir(tmp_path)
200
+ monkeypatch.setattr("sys.stdin", _Tty("\nemses\nn\n"))
201
+ res = cli("init")
202
+ assert res.code == 0, res.err
203
+ assert "runo update" in res.out
204
+ assert "emses" in load_toml(tmp_path / "runops.toml")["simulators"]
205
+
206
+
207
+ def test_init_install_needs_yes_off_terminal(
208
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch, cli
209
+ ) -> None: # type: ignore[no-untyped-def]
210
+ monkeypatch.chdir(tmp_path)
211
+ res = cli("init", "emses")
212
+ assert res.code == 2 and "--yes" in res.err
213
+ assert not (tmp_path / "runops.toml").exists()
@@ -525,7 +525,7 @@ wheels = [
525
525
 
526
526
  [[package]]
527
527
  name = "runops"
528
- version = "2.1.1"
528
+ version = "2.1.2"
529
529
  source = { editable = "." }
530
530
  dependencies = [
531
531
  { name = "jinja2" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes