Skip to content

Commit 32fed4b

Browse files
authored
feat!: Bump openjd-* Rust crates to the openjd-model 0.11.0 release (#375)
* feat!: Bump openjd-* Rust crates to the openjd-model 0.11.0 release openjd-rs released openjd-expr 0.10.1, openjd-model 0.10.1 and openjd-sessions 0.7.2 on 2026-09-30 (OpenJobDescription/openjd-rs#416), then openjd-model 0.11.0 and openjd-sessions 0.7.3 on 2026-10-03 (#420). This package pinned 0.10.0 / 0.10.0 / 0.7.1. Cargo.lock moves only the three crates; no transitive dependency changed. openjd-sessions has no source change in either release. One public Rust API change breaks compilation: #419 makes template::SimpleAction::script a FormatString. The constructor and the getter of PySimpleAction were the two errors. Following #373's capability-name precedent, the Python-facing SimpleAction.script is now an openjd.expr.FormatString in both directions, like its args/timeout siblings and the EmbeddedFile.data it desugars to. The new Rust-side SimpleActionKind / simple_actions / simple_action helpers are not exposed: nothing here consumes them, and step.bash..node already cover introspection. resolve_syntax_sugar changed signature but the bindings never call it. Behaviour changes, each measured through this package's Python API against both pins, with expectations copied from upstream assertions: - #419: bash/python/cmd/powershell/node steps are validated at decode with errors at the authored path (steps[0] -> bash -> args[1]). On 0.10.0, 17 of 21 upstream rejection cases decoded; 9 failed later at create_job at the desugared path, 8 were never rejected. A malformed script now fails at parse (DecodeValidationError). Non-ASCII step names no longer raise PanicException (ASCII-only sanitizer, named in the squash body but not the changelog). - #419, also named only in the squash body: the comprehension-variable check now covers a step script's authored embeddedFiles[].data. A comprehension over a let-bound name in data decoded on 0.10.0 and is now rejected at steps[0] -> script -> embeddedFiles[0] -> data. The same check on command and args is unchanged. v0 agrees on outcome and path in 4/4 cases. - #421: LIST[PATH] defaults must be relative and stay inside the template directory, are joined to it and normalized, element by element; relative submitted PATH / LIST[PATH] values are joined and normalized; defaults are constraint-checked after the join, including environment-template parameters. Absolute submitted values are returned as written. create_job without a preceding preprocess is unchanged (measured, 7 cases identical on both pins). - #410: a job environment's let failure now reads like a step script's ("script let binding 'q': ..."); the missing-extension message lists extensions sorted. - #410/#417/#418: openjd.expr memory accounting; every upstream byte figure reproduces. Some expressions that fit now exceed the limit (coercion to the target type, string slices, attribute base lookups) and some that failed now fit. No existing Python test pinned a moved figure. Unreachable from Python: URI-allowed LIST[PATH] rows (the binding hard-codes allow_uri_path_values=false, create_job_fns.rs:158; upstream test_create_job.rs covers them). The Windows rows of #421 are added as win32-only tests and were not run locally. v0 divergence: v0 preprocess_job_parameters returns LIST[PATH] defaults unjoined and does not normalize submitted '..'. openjd-specifications#191 (Template Schemas 2.2, 2.12) makes v1's behaviour normative. Recorded as two strict xfails in test_known_gaps.py and in the model report; fixing v0 is a separate change. On the #419 decode cases v0 agrees with v1 on outcome in 22/24 and on field path in 16/24; the two outcome differences are v0 rejecting Task.File.<step>_script, which predates this bump. Verified: 6323 passed / 26 skipped / 5 xfailed, coverage 94.22%. The +2 skipped are the Windows-only tests, the +2 xfailed the v0 gaps; no strict xfail flipped. ruff, black, mypy, cargo fmt, build, clippy -D warnings, test and test --doc clean. THIRD-PARTY-LICENSES.txt regenerated (three version lines) and verify mode passes. Mutants, each rebuilt, bytecode cleared, restored by checksum: reverting the pins and the adaptation kills 62 of 79 new or edited cases (the 17 survivors are controls whose behaviour 0.10.0 shares); the getter returning str kills 4; the constructor accepting str kills 4. Not done: the three-auditor review of the new tests (regression-workflow section 3) was not dispatched; the mutation results above are the author's own. TestExtremeSliceSteps pins the #418 overflow fix only in a build with overflow checks; a hatch env install of 0.10.0 already returned the right answer. BREAKING CHANGE: SimpleAction.script is an openjd.expr.FormatString instead of str, and SimpleAction(script=...) requires one. LIST[PATH] defaults must be relative and are joined with the job template directory; relative submitted PATH values are normalized. Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com> * chore(deps): Bump pyo3 to 0.29.3 for clippy 1.99 Rust 1.99.0 (stable since 2026-10-01) makes clippy flag clone_on_copy inside pyo3 0.29.2's #[pyclass(from_py_object)] expansion on Copy enums: 13 errors, which fail Rust Quality's clippy -D warnings step on every PR. pyo3 0.29.3 fixes the generated code (PyO3/pyo3#6309). Raise the floor in rust-bindings/Cargo.toml to 0.29.3 so a fresh resolve cannot pick the affected release. THIRD-PARTY-LICENSES.txt regenerated; only the four pyo3 version lines changed. Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com> --------- Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com>
1 parent 27ecd91 commit 32fed4b

13 files changed

Lines changed: 1200 additions & 36 deletions

‎Cargo.lock‎

Lines changed: 16 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎THIRD-PARTY-LICENSES.txt‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2741,16 +2741,16 @@ limitations under the License.
27412741
** itoa; version 1.0.18 -- https://crates.io/crates/itoa
27422742
** libc; version 0.2.189 -- https://crates.io/crates/libc
27432743
** manyhow-macros; version 0.11.4 -- https://crates.io/crates/manyhow-macros
2744-
** openjd-expr; version 0.10.0 -- https://crates.io/crates/openjd-expr
2745-
** openjd-model; version 0.10.0 -- https://crates.io/crates/openjd-model
2746-
** openjd-sessions; version 0.7.1 -- https://crates.io/crates/openjd-sessions
2744+
** openjd-expr; version 0.10.1 -- https://crates.io/crates/openjd-expr
2745+
** openjd-model; version 0.11.0 -- https://crates.io/crates/openjd-model
2746+
** openjd-sessions; version 0.7.3 -- https://crates.io/crates/openjd-sessions
27472747
** pin-project-lite; version 0.2.17 -- https://crates.io/crates/pin-project-lite
27482748
** portable-atomic; version 1.15.0 -- https://crates.io/crates/portable-atomic
27492749
** proc-macro2; version 1.0.107 -- https://crates.io/crates/proc-macro2
2750-
** pyo3-ffi; version 0.29.2 -- https://crates.io/crates/pyo3-ffi
2751-
** pyo3-macros-backend; version 0.29.2 -- https://crates.io/crates/pyo3-macros-backend
2752-
** pyo3-macros; version 0.29.2 -- https://crates.io/crates/pyo3-macros
2753-
** pyo3; version 0.29.2 -- https://crates.io/crates/pyo3
2750+
** pyo3-ffi; version 0.29.3 -- https://crates.io/crates/pyo3-ffi
2751+
** pyo3-macros-backend; version 0.29.3 -- https://crates.io/crates/pyo3-macros-backend
2752+
** pyo3-macros; version 0.29.3 -- https://crates.io/crates/pyo3-macros
2753+
** pyo3; version 0.29.3 -- https://crates.io/crates/pyo3
27542754
** quote; version 1.0.47 -- https://crates.io/crates/quote
27552755
** r-efi; version 6.0.0 -- https://crates.io/crates/r-efi
27562756
** rustc-hash; version 2.1.3 -- https://crates.io/crates/rustc-hash

‎reports/model-bindings-quality-evaluation-report.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,14 @@ divergence flagged in §8.
345345
* **`TokenError`, `parse_model`** — exposed on v0, absent on v1. The
346346
former is a downstream-visible surface change; the latter was
347347
internal.
348+
* **PATH / `LIST[PATH]` preprocessing** — since openjd-model 0.11.0
349+
(openjd-rs#421) v1 joins `LIST[PATH]` defaults to the template
350+
directory, applies the PATH default rules per element, and normalizes
351+
relative submitted values (`sub/../other` → `<cwd>/other`). v0 returns
352+
`LIST[PATH]` defaults unjoined and joins submitted values without
353+
normalizing. openjd-specifications#191 (§2.2, §2.12) makes the v1
354+
behaviour normative, so v0 is the side to fix. Pinned as strict xfails in
355+
`test/openjd/model_v1/test_known_gaps.py`.
348356

349357
## 6. Build and Test Results
350358

‎rust-bindings/Cargo.toml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ name = "_openjd_rs"
1212
crate-type = ["cdylib", "rlib"]
1313

1414
[dependencies]
15-
openjd-expr = "0.10.0"
16-
openjd-model = "0.10.0"
17-
openjd-sessions = "0.7.1"
15+
openjd-expr = "0.10.1"
16+
openjd-model = "0.11.0"
17+
openjd-sessions = "0.7.3"
1818
tokio = { version = "1", features = ["rt-multi-thread"] }
1919
uuid = { version = "1", features = ["v4"] }
2020
serde_json = "1"
21-
pyo3 = { version = "0.29", features = ["abi3-py39"] }
21+
pyo3 = { version = "0.29.3", features = ["abi3-py39"] }
2222
pyo3-log = "0.13"
2323
log = "0.4"
2424
pyo3-stub-gen = { version = "0.23", optional = true }

‎rust-bindings/src/model/template_types.rs‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,7 +1288,7 @@ impl PySimpleAction {
12881288
#[new]
12891289
#[pyo3(signature = (*, script, let_bindings=None, args=None, timeout=None, cancelation=None))]
12901290
fn new(
1291-
script: String,
1291+
script: PyFormatString,
12921292
let_bindings: Option<Vec<String>>,
12931293
args: Option<Vec<PyFormatString>>,
12941294
timeout: Option<PyFormatString>,
@@ -1297,7 +1297,7 @@ impl PySimpleAction {
12971297
PySimpleAction {
12981298
inner: SimpleAction {
12991299
let_bindings,
1300-
script,
1300+
script: script.inner,
13011301
args: args.map(|a| a.into_iter().map(|fs| fs.inner).collect()),
13021302
timeout: timeout.map(|t| t.inner),
13031303
cancelation: cancelation.map(|c| c.inner),
@@ -1306,8 +1306,10 @@ impl PySimpleAction {
13061306
}
13071307

13081308
#[getter]
1309-
fn script(&self) -> &str {
1310-
&self.inner.script
1309+
fn script(&self) -> PyFormatString {
1310+
PyFormatString {
1311+
inner: self.inner.script.clone(),
1312+
}
13111313
}
13121314

13131315
#[getter]

‎specs/python-model-interface.md‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,15 @@ str(job.steps[0].script.actions.onRun.command) # "render"
278278
Validate and coerce job parameter values. Accepts `str` or `pathlib.Path`
279279
for directory arguments.
280280

281+
PATH and `LIST[PATH]` follow Template Schemas §2.2 and §2.12, element-wise for
282+
lists: a default must be relative and stay inside `job_template_dir`, and is
283+
joined to it. `allow_job_template_dir_walk_up=True` lifts both conditions: an
284+
absolute default is returned as written, and a relative one may escape
285+
`job_template_dir` with `..`. A relative submitted
286+
value is joined to `current_working_dir`. Joined values are lexically
287+
normalized; an absolute submitted value is returned as written. A default's
288+
constraints are checked against the joined value. URI values are refused. Violations raise `DecodeValidationError` (openjd-rs#421).
289+
281290
```python
282291
from openjd.model._v1 import decode_job_template, preprocess_job_parameters
283292
from pathlib import Path
@@ -999,13 +1008,17 @@ dep.depends_on # str (alias: dependsOn)
9991008

10001009
```python
10011010
sa = step.bash # or .python, .cmd, .powershell, .node
1002-
sa.script # str
1011+
sa.script # FormatString
10031012
sa.let_bindings # Optional[list[str]] (alias: let)
10041013
sa.args # Optional[list[FormatString]]
10051014
sa.timeout # Optional[FormatString]
10061015
sa.cancelation # Optional[CancelationMode]
10071016
```
10081017

1018+
A `SimpleAction` is validated at decode with the checks of the `StepScript` it
1019+
desugars to, and errors name the authored path (`steps[0] -> bash -> args[1]`).
1020+
A malformed `script` format string raises `DecodeValidationError` (openjd-rs#419).
1021+
10091022
### `StepParameterSpaceDefinition` (5 typed task-parameter variants)
10101023

10111024
`StepTemplate.parameter_space` returns

‎src/openjd/_openjd_rs.pyi‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,7 +2253,7 @@ class Session:
22532253
@typing.final
22542254
class SimpleAction:
22552255
@property
2256-
def script(self) -> builtins.str: ...
2256+
def script(self) -> FormatString: ...
22572257
@property
22582258
def let_bindings(self) -> typing.Optional[builtins.list[builtins.str]]: ...
22592259
@property
@@ -2267,7 +2267,7 @@ class SimpleAction:
22672267
def __new__(
22682268
cls,
22692269
*,
2270-
script: builtins.str,
2270+
script: FormatString,
22712271
let_bindings: typing.Optional[typing.Sequence[builtins.str]] = None,
22722272
args: typing.Optional[typing.Sequence[FormatString]] = None,
22732273
timeout: typing.Optional[FormatString] = None,

0 commit comments

Comments
 (0)