lockwire 0.2.3__tar.gz → 0.2.4__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.
- {lockwire-0.2.3 → lockwire-0.2.4}/PKG-INFO +11 -7
- {lockwire-0.2.3 → lockwire-0.2.4}/README.md +7 -5
- {lockwire-0.2.3 → lockwire-0.2.4}/pyproject.toml +5 -3
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/__init__.py +1 -1
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/api.py +20 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/checks.py +329 -22
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/cli.py +192 -24
- lockwire-0.2.4/src/lockwire/confine.py +31 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/copy.py +11 -3
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/edit.py +18 -10
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/arm/contract.yaml +7 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/humanoid/contract.yaml +92 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/quadruped/contract.yaml +13 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/rover/contract.yaml +5 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/mcp_server.py +28 -6
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/mechanism.py +25 -8
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/mesh_dae.py +2 -1
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/page.py +27 -4
- lockwire-0.2.4/src/lockwire/parts_list.py +164 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/report.py +14 -2
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/scene_urdf.py +21 -5
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/schema.py +55 -8
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/serve.py +28 -29
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/start_operation.py +20 -10
- lockwire-0.2.4/src/lockwire/statics.py +284 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/urdf.py +88 -9
- lockwire-0.2.3/src/lockwire/statics.py +0 -77
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/__main__.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/_filelock.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/advice.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/api_payload.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/bench.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/blame.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/catalog.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/catalog_seed.yaml +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/cli_line.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/constraints.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/describe.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/emit_ts.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/arm/LICENSE +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/arm/NOTICE +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/arm/plan.yaml +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/arm/scene.glb +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/arm/starter.json +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/drone/contract.yaml +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/drone/plan.yaml +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/drone/scene.glb +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/drone/starter.json +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/humanoid/NOTICE +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/humanoid/plan.yaml +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/humanoid/scene.glb +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/humanoid/starter.json +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/quadruped/NOTICE +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/quadruped/plan.yaml +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/quadruped/scene.glb +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/quadruped/starter.json +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/rover/NOTICE +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/rover/plan.yaml +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/rover/scene.glb +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/rover/starter.json +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/examples/servo-bench.yaml +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/export_mhs.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/factdiff.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/forces.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/gitref.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/hw.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/mesh_simple.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/plan.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/plan_payload.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/plugins.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/report_html.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/report_json.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/review_draft.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/scan.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/scene.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/scene_import.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/scene_view.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/sdf.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/units.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/vcs.py +0 -0
- {lockwire-0.2.3 → lockwire-0.2.4}/src/lockwire/whatif.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lockwire
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: The physical-assumption contract for robots: checks that a robot's declared parts (power, weight, bus, torque) add up
|
|
5
5
|
Keywords: robotics,urdf,ros,preflight,lockfile,ci,hardware,drone
|
|
6
6
|
Author: Shivansh
|
|
@@ -19,7 +19,9 @@ Requires-Dist: pydantic>=2.13.4
|
|
|
19
19
|
Requires-Dist: rich>=15.0.0
|
|
20
20
|
Requires-Dist: ruamel-yaml>=0.19.1
|
|
21
21
|
Requires-Dist: typer>=0.26.8
|
|
22
|
-
Requires-Dist:
|
|
22
|
+
Requires-Dist: xacro>=2.1.1
|
|
23
|
+
Requires-Dist: mcp>=2.2.0 ; extra == 'mcp'
|
|
24
|
+
Requires-Dist: pyjwt>=2.15 ; extra == 'mcp'
|
|
23
25
|
Requires-Dist: fastapi>=0.141.1 ; extra == 'serve'
|
|
24
26
|
Requires-Dist: uvicorn>=0.52.4 ; extra == 'serve'
|
|
25
27
|
Requires-Python: >=3.12
|
|
@@ -198,9 +200,9 @@ VIOLATION budgets/bud.power.pm02-5v — observed 35.20 W (draw mode: nominal), e
|
|
|
198
200
|
action: shed load on rail 'rail.pm02-5v' or raise its capacity with provenance
|
|
199
201
|
VIOLATION budgets/bud.power.pm02-5v.7w-mode — observed 17.20 W (draw mode: 7W), expected <= 15.60 W (Δ +1.60 W (+10%))
|
|
200
202
|
… (same rail, Jetson in its 7 W mode: the radio's transmit peak still tips it over)
|
|
201
|
-
not scored
|
|
203
|
+
not scored budgets/bud.mass.payload — observed mass unknown for dev.companion.jetson-orin-nano, dev.camera.oak-d-lite, dev.magnetometer.ist8310; total not scored, expected every device and link in this budget to declare a mass
|
|
202
204
|
… (more not-scored lines: things the lockfile does not declare yet, listed, never hidden)
|
|
203
|
-
scored
|
|
205
|
+
scored 9: 7 add up, 2 do not · 10 not scored
|
|
204
206
|
|
|
205
207
|
NO-GO — 2 violation(s), 0 warning(s)
|
|
206
208
|
$ echo $?
|
|
@@ -217,7 +219,7 @@ integration of published parts, and the two vendors' own numbers still do not ad
|
|
|
217
219
|
Nobody printed "this build is broken". Nobody printed "5 A" either: that is 25 W / 5 V, a
|
|
218
220
|
quotient of figures published on different pages. The records disagree with each other, and
|
|
219
221
|
you find out before you apply power. Give the Jetson its own regulator
|
|
220
|
-
(`tests/fixtures/x500/contract_corrected.yaml`) and the same check passes
|
|
222
|
+
(`tests/fixtures/x500/contract_corrected.yaml`) and the same check passes: `GO — records agree (10 scored); 10 check(s) not scored`.
|
|
221
223
|
|
|
222
224
|
## Your own robot
|
|
223
225
|
|
|
@@ -241,7 +243,9 @@ Any field you hand-edited (including `robot.name`) is silently overwritten back
|
|
|
241
243
|
| `start` | the contract was written (or an existing one kept); no page is written | the URDF/SDF could not be parsed, or the contract could not be read or written | — | — |
|
|
242
244
|
|
|
243
245
|
`NOT SCORED` (exit 3) means no comparison had both operands: it is not a pass and not a failure.
|
|
246
|
+
|
|
244
247
|
The `scored N: …` line above the verdict is where a script should look.
|
|
248
|
+
`lockwire check --strict` makes a `GO with notes` run exit 1 (the `NO-GO` code); the table does not change.
|
|
245
249
|
|
|
246
250
|
## In CI
|
|
247
251
|
|
|
@@ -252,7 +256,7 @@ The `scored N: …` line above the verdict is where a script should look.
|
|
|
252
256
|
contract: lockwire.yaml
|
|
253
257
|
```
|
|
254
258
|
|
|
255
|
-
Inputs: `contract` (default `lockwire.yaml`), `version` (pin a PyPI release; default installs the action's own code), `python-version` (default 3.12).
|
|
259
|
+
Inputs: `contract` (default `lockwire.yaml`), `version` (pin a PyPI release; default installs the action's own code), `strict` (default `false`; `true` passes `--strict`), `python-version` (default 3.12).
|
|
256
260
|
Or just `pipx install lockwire && lockwire check lockwire.yaml`.
|
|
257
261
|
|
|
258
262
|
## Pre-commit
|
|
@@ -260,7 +264,7 @@ Or just `pipx install lockwire && lockwire check lockwire.yaml`.
|
|
|
260
264
|
```yaml
|
|
261
265
|
repos:
|
|
262
266
|
- repo: https://github.com/Shivansh2703/lockwire
|
|
263
|
-
rev: v0.2.
|
|
267
|
+
rev: v0.2.3
|
|
264
268
|
hooks:
|
|
265
269
|
- id: lockwire-check
|
|
266
270
|
```
|
|
@@ -166,9 +166,9 @@ VIOLATION budgets/bud.power.pm02-5v — observed 35.20 W (draw mode: nominal), e
|
|
|
166
166
|
action: shed load on rail 'rail.pm02-5v' or raise its capacity with provenance
|
|
167
167
|
VIOLATION budgets/bud.power.pm02-5v.7w-mode — observed 17.20 W (draw mode: 7W), expected <= 15.60 W (Δ +1.60 W (+10%))
|
|
168
168
|
… (same rail, Jetson in its 7 W mode: the radio's transmit peak still tips it over)
|
|
169
|
-
not scored
|
|
169
|
+
not scored budgets/bud.mass.payload — observed mass unknown for dev.companion.jetson-orin-nano, dev.camera.oak-d-lite, dev.magnetometer.ist8310; total not scored, expected every device and link in this budget to declare a mass
|
|
170
170
|
… (more not-scored lines: things the lockfile does not declare yet, listed, never hidden)
|
|
171
|
-
scored
|
|
171
|
+
scored 9: 7 add up, 2 do not · 10 not scored
|
|
172
172
|
|
|
173
173
|
NO-GO — 2 violation(s), 0 warning(s)
|
|
174
174
|
$ echo $?
|
|
@@ -185,7 +185,7 @@ integration of published parts, and the two vendors' own numbers still do not ad
|
|
|
185
185
|
Nobody printed "this build is broken". Nobody printed "5 A" either: that is 25 W / 5 V, a
|
|
186
186
|
quotient of figures published on different pages. The records disagree with each other, and
|
|
187
187
|
you find out before you apply power. Give the Jetson its own regulator
|
|
188
|
-
(`tests/fixtures/x500/contract_corrected.yaml`) and the same check passes
|
|
188
|
+
(`tests/fixtures/x500/contract_corrected.yaml`) and the same check passes: `GO — records agree (10 scored); 10 check(s) not scored`.
|
|
189
189
|
|
|
190
190
|
## Your own robot
|
|
191
191
|
|
|
@@ -209,7 +209,9 @@ Any field you hand-edited (including `robot.name`) is silently overwritten back
|
|
|
209
209
|
| `start` | the contract was written (or an existing one kept); no page is written | the URDF/SDF could not be parsed, or the contract could not be read or written | — | — |
|
|
210
210
|
|
|
211
211
|
`NOT SCORED` (exit 3) means no comparison had both operands: it is not a pass and not a failure.
|
|
212
|
+
|
|
212
213
|
The `scored N: …` line above the verdict is where a script should look.
|
|
214
|
+
`lockwire check --strict` makes a `GO with notes` run exit 1 (the `NO-GO` code); the table does not change.
|
|
213
215
|
|
|
214
216
|
## In CI
|
|
215
217
|
|
|
@@ -220,7 +222,7 @@ The `scored N: …` line above the verdict is where a script should look.
|
|
|
220
222
|
contract: lockwire.yaml
|
|
221
223
|
```
|
|
222
224
|
|
|
223
|
-
Inputs: `contract` (default `lockwire.yaml`), `version` (pin a PyPI release; default installs the action's own code), `python-version` (default 3.12).
|
|
225
|
+
Inputs: `contract` (default `lockwire.yaml`), `version` (pin a PyPI release; default installs the action's own code), `strict` (default `false`; `true` passes `--strict`), `python-version` (default 3.12).
|
|
224
226
|
Or just `pipx install lockwire && lockwire check lockwire.yaml`.
|
|
225
227
|
|
|
226
228
|
## Pre-commit
|
|
@@ -228,7 +230,7 @@ Or just `pipx install lockwire && lockwire check lockwire.yaml`.
|
|
|
228
230
|
```yaml
|
|
229
231
|
repos:
|
|
230
232
|
- repo: https://github.com/Shivansh2703/lockwire
|
|
231
|
-
rev: v0.2.
|
|
233
|
+
rev: v0.2.3
|
|
232
234
|
hooks:
|
|
233
235
|
- id: lockwire-check
|
|
234
236
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "lockwire"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.4"
|
|
4
4
|
description = "The physical-assumption contract for robots: checks that a robot's declared parts (power, weight, bus, torque) add up"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -26,13 +26,15 @@ dependencies = [
|
|
|
26
26
|
"rich>=15.0.0",
|
|
27
27
|
"ruamel-yaml>=0.19.1",
|
|
28
28
|
"typer>=0.26.8",
|
|
29
|
+
"xacro>=2.1.1",
|
|
29
30
|
]
|
|
30
31
|
|
|
31
32
|
[project.optional-dependencies]
|
|
32
33
|
# Serving lockwire over MCP to an agent. Optional for the same reason as `ros2bag`:
|
|
33
34
|
# a plain install must stay lean, and the SDK is only needed by `lockwire mcp`.
|
|
34
35
|
mcp = [
|
|
35
|
-
"mcp>=2.
|
|
36
|
+
"mcp>=2.2.0",
|
|
37
|
+
"pyjwt>=2.15", # direct floor: a fresh lock must not resolve below the fixed release
|
|
36
38
|
]
|
|
37
39
|
# The Electron app's sidecar: `lockwire serve` over local HTTP. Optional for the
|
|
38
40
|
# same reason as `desktop`/`ros2bag`/`mcp` — a plain CLI install stays lean; only the
|
|
@@ -59,7 +61,7 @@ build-backend = "uv_build"
|
|
|
59
61
|
|
|
60
62
|
[dependency-groups]
|
|
61
63
|
dev = [
|
|
62
|
-
"mcp>=2.
|
|
64
|
+
"mcp>=2.2.0",
|
|
63
65
|
# tests/test_serve.py needs the sidecar (`lockwire serve`) importable and
|
|
64
66
|
# runnable as a subprocess. Same reasoning as `mcp`/`mcap` above: CI's
|
|
65
67
|
# `test` job runs a plain `uv sync --dev`, so without these here that
|
|
@@ -105,6 +105,24 @@ def start(
|
|
|
105
105
|
return start_contract(urdf, overwrite=overwrite, expected_revision=expected_revision)
|
|
106
106
|
|
|
107
107
|
|
|
108
|
+
def from_parts(
|
|
109
|
+
text: str, *, out: Path | str | None = None, catalog: Path | str | None = None
|
|
110
|
+
) -> dict[str, Any]:
|
|
111
|
+
"""Match a pasted parts list to the catalog; with ``out``, also write a draft lockfile.
|
|
112
|
+
|
|
113
|
+
Information, not a gate: a mismatch is listed, never refused. ``parts_list.match_parts``.
|
|
114
|
+
"""
|
|
115
|
+
from lockwire.parts_list import match_parts, write_draft
|
|
116
|
+
|
|
117
|
+
if not isinstance(text, str): # same plain ValueError the neighbouring functions raise
|
|
118
|
+
raise ValueError("from_parts needs the parts list as text")
|
|
119
|
+
document = match_parts(text, catalog)
|
|
120
|
+
if out is not None and not Path(out).exists():
|
|
121
|
+
write_draft(document, Path(out), catalog)
|
|
122
|
+
document["written"] = str(out)
|
|
123
|
+
return document
|
|
124
|
+
|
|
125
|
+
|
|
108
126
|
def api_schema(out: Path | str) -> None:
|
|
109
127
|
"""Write the payload union's JSON schema — ``api_payload.export_openapi``.
|
|
110
128
|
|
|
@@ -249,6 +267,7 @@ __all__ = [
|
|
|
249
267
|
"FUNCTIONS",
|
|
250
268
|
"add",
|
|
251
269
|
"api_schema",
|
|
270
|
+
"from_parts",
|
|
252
271
|
"api_types",
|
|
253
272
|
"blame",
|
|
254
273
|
"what_if",
|
|
@@ -262,6 +281,7 @@ __all__ = [
|
|
|
262
281
|
"mount_shape",
|
|
263
282
|
"move",
|
|
264
283
|
"log",
|
|
284
|
+
"place",
|
|
265
285
|
"plan",
|
|
266
286
|
"reparent",
|
|
267
287
|
"review",
|