draftwright 0.3.9__tar.gz → 0.4.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.
- {draftwright-0.3.9 → draftwright-0.4.0}/CHANGELOG.md +156 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/PKG-INFO +15 -1
- {draftwright-0.3.9 → draftwright-0.4.0}/README.md +14 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/docs/adr/README.md +2 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/pyproject.toml +4 -1
- {draftwright-0.3.9 → draftwright-0.4.0}/skills/SKILL.md +99 -43
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/__init__.py +1 -3
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/_core.py +134 -11
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/_geometry.py +57 -1
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/analysis.py +13 -20
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/annotate.py +1 -1
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/annotations/_common.py +75 -12
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/annotations/balloons.py +125 -25
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/annotations/from_model.py +1264 -615
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/annotations/holes.py +371 -124
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/annotations/orchestrator.py +52 -25
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/annotations/sections.py +137 -32
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/builder.py +154 -427
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/cli.py +36 -63
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/compose.py +23 -47
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/drawing.py +424 -153
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/layout.py +81 -6
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/linting/__init__.py +2 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/linting/coverage.py +283 -18
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/make_drawing.py +1 -2
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/model/__init__.py +16 -2
- draftwright-0.4.0/src/draftwright/model/callout.py +335 -0
- draftwright-0.4.0/src/draftwright/model/compiled.py +1060 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/model/declare.py +148 -19
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/model/detect.py +82 -25
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/model/ir.py +214 -6
- draftwright-0.4.0/src/draftwright/model/planner.py +750 -0
- draftwright-0.4.0/src/draftwright/py.typed +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/__init__.py +4 -1
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/_features.py +89 -24
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/levels.py +65 -20
- draftwright-0.4.0/src/draftwright/recognition/pads.py +137 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/slots.py +99 -2
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/registry.py +11 -3
- draftwright-0.4.0/src/draftwright/sheet.py +1764 -0
- draftwright-0.4.0/src/draftwright/sheet_emit.py +1231 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/pocketed.json +37 -1
- draftwright-0.4.0/tests/test_add_dimension.py +1332 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_agents_guide.py +2 -2
- draftwright-0.4.0/tests/test_balloon_ring_standoff.py +78 -0
- draftwright-0.4.0/tests/test_compiled_plan_boundary.py +1192 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_declare.py +438 -63
- draftwright-0.4.0/tests/test_deprecation_dates.py +153 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_detect_once.py +3 -3
- draftwright-0.4.0/tests/test_dimension_role_vocabulary.py +378 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_drawing_encapsulation.py +77 -3
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_e2e_slice.py +3 -1
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_e2e_standards.py +70 -16
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_fits.py +3 -3
- draftwright-0.4.0/tests/test_grid_lattice_convention.py +327 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_import_boundaries.py +0 -1
- draftwright-0.4.0/tests/test_issue_885_prismatic_coverage.py +126 -0
- draftwright-0.4.0/tests/test_label_provenance.py +206 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_layout.py +80 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_lint_reconciliation.py +3 -3
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_make_drawing.py +937 -293
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_object_aspects.py +6 -6
- draftwright-0.4.0/tests/test_parameter_id.py +510 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_pmi.py +3 -1
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_pocket_pattern.py +8 -7
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_pocket_pattern_recognition.py +29 -1
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_private_test_attr_reads.py +0 -7
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_render_seam.py +36 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_script_detail_parity.py +79 -50
- draftwright-0.4.0/tests/test_sheet_emit.py +3361 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_sheet_gdt.py +12 -12
- draftwright-0.4.0/tests/test_sheet_identity_invariant.py +805 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_sheet_notes.py +14 -14
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_sheet_of.py +3 -3
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_sheet_section.py +1 -1
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_sheet_tables.py +3 -1
- draftwright-0.4.0/tests/test_slanted_blind_step.py +283 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_slot_pattern.py +10 -8
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_solve_trace.py +5 -2
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_strip_layout.py +64 -0
- draftwright-0.4.0/tests/test_suppression_marks.py +553 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_tolerances.py +64 -40
- draftwright-0.3.9/src/draftwright/model/planner.py +0 -320
- draftwright-0.3.9/src/draftwright/sheet.py +0 -1016
- draftwright-0.3.9/src/draftwright/sheet_dsl.py +0 -35
- draftwright-0.3.9/src/draftwright/sheet_emit.py +0 -766
- draftwright-0.3.9/tests/test_sheet_emit.py +0 -1280
- {draftwright-0.3.9 → draftwright-0.4.0}/.gitignore +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/LICENSE +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/annotations/__init__.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/export.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/fits.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/fonts/IBMPlexMono-Regular.ttf +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/fonts/IBMPlexSansCondensed-Regular.ttf +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/fonts/LICENSE-IBMPlexMono-OFL.txt +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/fonts/LICENSE-IBMPlexSansCondensed-OFL.txt +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/fonts/__init__.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/intents.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/linting/issues.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/linting/structural.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/linting/suggest.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/pmi.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/projection.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/_record.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/chamfers.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/countersinks.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/fillets.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/flats.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/grooves.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/plates.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/recognition/turned.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/repair.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/src/draftwright/score.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/_kernel.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/_layout_sig.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/grm03_thumbwheel_drive_screw.step +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/nist_ctc_01_asme1_ap203.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/nist_ctc_02_asme1_ap203.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/nist_ctc_02_asme1_ap242.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/nist_ctc_03_asme1_ap203.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/nist_ctc_03_asme1_ap242.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/nist_ctc_04_asme1_ap203.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/nist_ctc_04_asme1_ap242.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/nist_ctc_05_asme1_ap203.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/nist_ctc_05_asme1_ap242.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/fixtures/tuner_jig_blind_obround_pockets.step +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/bracket_section.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/centered_rebate.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/chamfered.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/filleted.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/flange_dense.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/grid_plate.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/grooved_shaft.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/hex_bar.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/holed_slot.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/prismatic_ladder.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/scattered_plate.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/side_drilled.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/refactor_golden/turned_stepped.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_architecture_docs.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_carve_free_position_callers.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_dense_sheet_canary.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_detect_registry.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_export_dxf_zoom.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_fillets_adjacency.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_gdt_placement.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_layout_cleanliness.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_layout_hypothesis.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_layout_property.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_lint_box_cache.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_lint_structural.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_linting.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_note_verb.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_occupancy_boxes.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_part_model.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_pitch_dim_footprint.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_private_test_imports.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_recogniser_contract.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_recognition.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_refactor_golden.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_registry.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_score.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_slot_pattern_recognition.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_turned_steps.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.0}/tests/test_witness_label_reconciliation.py +0 -0
|
@@ -1,5 +1,161 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## v0.4.0 — 2026-08-02
|
|
6
|
+
|
|
7
|
+
**The compat-exit release.** Every surface whose documented removal target was 0.4.0 is gone,
|
|
8
|
+
and every deprecation that remains now says when it goes — in the message the caller sees, not
|
|
9
|
+
only in a release note. ADR 0005 §4's rule is that an alias carries a tracking issue *and* a
|
|
10
|
+
removal date, because "a facade with no exit date is a failure mode"; this release is that rule
|
|
11
|
+
being kept rather than restated. `docs/deprecations.md` is the new index, and
|
|
12
|
+
`tests/test_deprecation_dates.py` fails any deprecation that names no removal.
|
|
13
|
+
|
|
14
|
+
Also lands ADR 0016's declared-dimensioning work (#867): a `dimension(feature, role)` is
|
|
15
|
+
referential — it names a measurement and carries no number — and an authored set means omission
|
|
16
|
+
is suppression, enforced at the compiled-plan boundary rather than by a flag renderers check.
|
|
17
|
+
|
|
18
|
+
**Read this before upgrading:** two removals break *without a release that warned you*, because
|
|
19
|
+
their deprecation never appeared in a shipped version. See *Removed (breaking)* below and
|
|
20
|
+
`docs/deprecations.md`.
|
|
21
|
+
|
|
22
|
+
### Removed (breaking)
|
|
23
|
+
|
|
24
|
+
Compat surfaces whose documented removal target was 0.4.0 (#720, ADR 0005 §4 — every alias
|
|
25
|
+
carries a tracking issue *and* a removal date, or the facade is permanent by accident):
|
|
26
|
+
|
|
27
|
+
- **The seven `Drawing` compat aliases** — `_named` / `_anno_view` / `_pinned` /
|
|
28
|
+
`_build_issues`, and `_pattern_callouts` / `_patterned_holes` / `_dropped_callout_diams`.
|
|
29
|
+
These were private, and the public reads have existed since #699: use `dwg.registry`
|
|
30
|
+
(`in reg`, `names()`, `issues`, `pinned_names()`) and `dwg.coverage`, or the `Drawing` verbs
|
|
31
|
+
`annotations()` / `iter_annotations()` / `get_annotation()` / `view_of()`.
|
|
32
|
+
**Note the asymmetry.** A *read* — `dwg._named` — now raises `AttributeError`. A *write* —
|
|
33
|
+
`dwg._pinned = {...}` — does **not**: these were properties with setters, and `Drawing` has
|
|
34
|
+
no `__slots__`, so assignment now quietly creates an unrelated instance attribute that no
|
|
35
|
+
longer reaches the registry or coverage owner. Writes therefore fail silently rather than
|
|
36
|
+
loudly. Grep for `\._(named|anno_view|pinned|build_issues|pattern_callouts|patterned_holes|dropped_callout_diams)\b`
|
|
37
|
+
before upgrading; mutate through `registry.add()` / `pin()` / `record_issue()` /
|
|
38
|
+
`restore_issues()` and the `CoverageState` methods instead.
|
|
39
|
+
- **The `draftwright.sheet_dsl` module** — an import alias for `draftwright.sheet` since the
|
|
40
|
+
#640 rename. Import `Sheet` from `draftwright` or `draftwright.sheet`.
|
|
41
|
+
- **`generate_script`**, including its `draftwright.__all__` entry. It has raised since #940
|
|
42
|
+
retired the imperative emitter; it is now simply absent, so the failure is an `ImportError`
|
|
43
|
+
at the top of a script rather than a `RuntimeError` part-way through one. Use
|
|
44
|
+
`--script` / `emit_sheet_script`.
|
|
45
|
+
- **The bespoke `--style imperative` error message.** `--style` itself is unchanged and still
|
|
46
|
+
accepts its sole value `sheet`; `imperative` is now an unrecognised value like any typo,
|
|
47
|
+
rather than one carrying its own explanation of the #940 retirement.
|
|
48
|
+
|
|
49
|
+
- **Bare dimension-role spellings** — `sheet.dimension(f, "width")`. Use the parameter id,
|
|
50
|
+
`"width.length"`; `dimension_ids()` on a handle lists the valid ones. The bare role is the
|
|
51
|
+
*family* spelling: it selects every parameter carrying it, which is how
|
|
52
|
+
`dimension(step, "step")` quietly declared two measurements. In an authored set, where
|
|
53
|
+
omission means suppression, silently declaring an extra one is the mirror image of the rule
|
|
54
|
+
— so it now raises rather than resolving. (A *discriminated* bare role, used with `axis=`,
|
|
55
|
+
is unaffected: that is how variants like `grid_pitch.length.row` are addressed, and it never
|
|
56
|
+
warned.)
|
|
57
|
+
- **The `Sheet.dimension(kind=…, value=…)` call shape** — use `Sheet.measured_dimension(...)`.
|
|
58
|
+
`dimension` is now solely the ADR 0016 referential verb: it names a feature and a parameter
|
|
59
|
+
id and reads the value off the geometry.
|
|
60
|
+
|
|
61
|
+
Those last two break **without a release that warns you**. They were deprecated after v0.3.9
|
|
62
|
+
and removed in 0.4.0, so the `DeprecationWarning` never appeared in a released version —
|
|
63
|
+
upgrading from v0.3.9 or earlier goes straight from working to a raise. That is deliberate
|
|
64
|
+
(ADR 0016); this entry and `docs/deprecations.md` are the only notice you get, so both
|
|
65
|
+
failures name their replacement rather than raising about argument counts.
|
|
66
|
+
|
|
67
|
+
### Deprecated
|
|
68
|
+
|
|
69
|
+
- **The legacy `Drawing.export` shapes now emit `DeprecationWarning`** (#987) — they were
|
|
70
|
+
announced as deprecated in v0.3.1 and then said nothing at runtime for four minor releases,
|
|
71
|
+
which would have made their 0.5.0 removal a silent break. Three cases warn:
|
|
72
|
+
- `export()` with `formats=` **omitted or `None`** — the legacy default, which writes
|
|
73
|
+
SVG + DXF and returns an `(svg, dxf)` **tuple** rather than the `{format: path}` dict.
|
|
74
|
+
- the **`svg=` / `dxf=` booleans**. The suggested replacement names the formats *that call*
|
|
75
|
+
selected, so following it cannot change what gets written.
|
|
76
|
+
- passing a boolean **alongside** `formats=`, where it is silently ignored — `formats` wins,
|
|
77
|
+
and now says so.
|
|
78
|
+
|
|
79
|
+
**If you promote `DeprecationWarning` to an error, previously-passing exports will now
|
|
80
|
+
raise.** Migration: `export(out, formats=("svg", "dxf"))` and read the dict. `make_drawing`
|
|
81
|
+
is unaffected — it returns the same tuple and does not warn.
|
|
82
|
+
|
|
83
|
+
### Added
|
|
84
|
+
|
|
85
|
+
- **`sheet.add_dimension(feature, role)` — ask the planner to carry one more
|
|
86
|
+
measurement** (ADR 0016 / #872). Referential: it names a feature and a role and
|
|
87
|
+
carries **no number**, so the value still comes from the geometry and a size lives in
|
|
88
|
+
exactly one place. It changes *selection*, not derivation — a request can never
|
|
89
|
+
introduce a number the part does not have. Requesting something the planner already
|
|
90
|
+
emits is a deliberate no-op, so a script can ask without first knowing the rule set's
|
|
91
|
+
mind. `sheet.auto_dimensions()` states the source explicitly (optional in this
|
|
92
|
+
release; #874 makes it mandatory).
|
|
93
|
+
- **Suppressing a dimension marks it; it no longer leaks into the callout** (ADR 0016 /
|
|
94
|
+
#875). `PlannedDimension.suppressed` was honoured at thirteen render sites but not by
|
|
95
|
+
the compound hole-callout path, so a suppressed counterbore still printed. The group
|
|
96
|
+
keeps its engineering data either way — what changes is whether a value reaches the
|
|
97
|
+
page. Suppressing the bore ⌀ while a counterbore, spotface or countersink segment
|
|
98
|
+
remains now **raises** and names the orphan: `⌀20 THRU ⌴ ⌀32 ↓ 1.5` has no reading with
|
|
99
|
+
its leading term removed, and silently dropping the segments would discard authored
|
|
100
|
+
intent while silently restoring the head would make the drawing say something the
|
|
101
|
+
script does not.
|
|
102
|
+
- **Addressable dimension identity** (#869/#870/#871): every planned measurement now has
|
|
103
|
+
a stable `DimensionId(feature, parameter)`, and correlated measurements that must be
|
|
104
|
+
named as one — a grid pattern's row and column pitch, a step ladder — group into an
|
|
105
|
+
`AddressableDimension`. This is what a `dimension(...)` line will name, and what
|
|
106
|
+
suppression and provenance key on.
|
|
107
|
+
|
|
108
|
+
### Changed
|
|
109
|
+
|
|
110
|
+
- **`Sheet.dimension(kind=…, value=…)` is now `Sheet.measured_dimension(...)`**
|
|
111
|
+
(ADR 0016 / #873), and `model.declare.authored_dimension` is
|
|
112
|
+
`model.declare.measured_dimension` to match. This **reserves** the name `dimension` for
|
|
113
|
+
the referential verb ADR 0016 defines — name a feature and a role, carry no number, let
|
|
114
|
+
the engine read the value off the geometry — which `Drawing.dimension` already is and
|
|
115
|
+
`Sheet.dimension` will become. The verb that carries an explicit number needed a name
|
|
116
|
+
saying so first. The old spelling was a transitional overload during development and is
|
|
117
|
+
**removed in this same release** (#720) rather than shipping — `Sheet.dimension` is solely
|
|
118
|
+
the referential verb, and the old keyword call raises with `measured_dimension` named. See
|
|
119
|
+
*Removed (breaking)* above. Generated AP242 scripts emit `measured_dimension` and so arrive
|
|
120
|
+
un-deprecated.
|
|
121
|
+
- **`Sheet` handles address features by identity, not position** (#908/#910/#912). A
|
|
122
|
+
handle, tolerance, GD&T origin, section request or dimension intent now follows *its*
|
|
123
|
+
feature through a `features` reorder instead of naming whatever took the slot.
|
|
124
|
+
Reordering with `reverse()`/`sort()` preserves every reference; deleting or replacing
|
|
125
|
+
a referenced feature raises rather than silently retargeting a neighbour. `of()` now
|
|
126
|
+
accepts a handle, and negative indices resolve uniformly across `of()`,
|
|
127
|
+
`add_dimension()` and the GD&T verbs.
|
|
128
|
+
|
|
129
|
+
### Fixed
|
|
130
|
+
|
|
131
|
+
- **`sheet.envelope()` measured the file, not the part** (#977). An AP242 STEP import is a
|
|
132
|
+
compound of the solid *plus its PMI presentation geometry* — annotation planes, leader
|
|
133
|
+
curves — and the declared verb measured all of it. On the NIST CTC-01 fixture it declared
|
|
134
|
+
1170 × 650 where the part is 800 × 450: an envelope 370 mm too wide, silently, in anything
|
|
135
|
+
declared by hand. `step_level()` had the same exposure, offsetting every step position by
|
|
136
|
+
the annotation overhang. Both now measure the solid body, sharing the helper the engine
|
|
137
|
+
already used for exactly this (`_analyse` and `Sheet.model`).
|
|
138
|
+
- **A declared envelope's frame origin sat a half-height below a detected one** (#977). It
|
|
139
|
+
used `bbox_min.Z` where the detector uses the bbox centre. **Dimension output is unchanged** —
|
|
140
|
+
envelope sizes derive from `bbox_min`/`bbox_max`, and the overall height is compiled from the
|
|
141
|
+
model bbox — but `frame.origin` is the generic feature *site*, so **a GD&T control frame,
|
|
142
|
+
surface finish or note targeting a hand-declared `sheet.envelope()` was anchored at the
|
|
143
|
+
bottom face rather than the centre, and its leader now moves to the centre**. That is a
|
|
144
|
+
visible change on drawings carrying such an annotation; drawings without one are unaffected.
|
|
145
|
+
Scripts generated by `--script` were never affected either way: they bake the detected frame
|
|
146
|
+
explicitly rather than calling the verb.
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
- **Front-view dimensions join the placement solve instead of committing to the strip**
|
|
150
|
+
(#894): they previously took strip space before the global solve ran, so a
|
|
151
|
+
higher-ranked dimension could find its space already gone. Priority only ranks
|
|
152
|
+
candidates that are *in* the solve.
|
|
153
|
+
- **A hole callout reads the feature's own `through` fact** (#868) rather than inferring
|
|
154
|
+
it from whether a depth parameter happens to be present — so a suppressed depth can no
|
|
155
|
+
longer make a blind hole print `THRU`.
|
|
156
|
+
- **The balloon ring clears the view it annotates after a hole-table escalation**
|
|
157
|
+
(#901/#903).
|
|
158
|
+
|
|
3
159
|
## v0.3.9 — 2026-07-26
|
|
4
160
|
|
|
5
161
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: draftwright
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Automated technical-drawing generation for build123d
|
|
5
5
|
Project-URL: Homepage, https://github.com/pzfreo/draftwright
|
|
6
6
|
Project-URL: Repository, https://github.com/pzfreo/draftwright
|
|
@@ -834,6 +834,20 @@ sheet.hole(features.m3_bore).thread("M3x0.5").finish("1.6") # tapped + Ra on t
|
|
|
834
834
|
An object-sourced script carries an inline tip pointing at exactly this edit; a STEP-sourced
|
|
835
835
|
script keeps the detected numbers (there's no object to reference).
|
|
836
836
|
|
|
837
|
+
Every generated script ends by naming the drawing it built, so you can critique or inspect it
|
|
838
|
+
before (or instead of) exporting — one build, not two:
|
|
839
|
+
|
|
840
|
+
```python
|
|
841
|
+
drawing = sheet.build()
|
|
842
|
+
|
|
843
|
+
for issue in drawing.lint(): # ISO/coverage critique of THIS drawing
|
|
844
|
+
print(issue.severity, issue.code, issue.message)
|
|
845
|
+
|
|
846
|
+
drawing.export("part", formats=("pdf",))
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
`sheet.export(...)` remains the one-liner for handwritten scripts that just want the file.
|
|
850
|
+
|
|
837
851
|
See [`docs/multi-feature-object-reference-workflow.md`](docs/multi-feature-object-reference-workflow.md)
|
|
838
852
|
for a complete, runnable walkthrough of this pattern on a multi-feature turned part —
|
|
839
853
|
including the backward-compatible refactor, external threads (no `.thread()` on a step —
|
|
@@ -138,6 +138,20 @@ sheet.hole(features.m3_bore).thread("M3x0.5").finish("1.6") # tapped + Ra on t
|
|
|
138
138
|
An object-sourced script carries an inline tip pointing at exactly this edit; a STEP-sourced
|
|
139
139
|
script keeps the detected numbers (there's no object to reference).
|
|
140
140
|
|
|
141
|
+
Every generated script ends by naming the drawing it built, so you can critique or inspect it
|
|
142
|
+
before (or instead of) exporting — one build, not two:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
drawing = sheet.build()
|
|
146
|
+
|
|
147
|
+
for issue in drawing.lint(): # ISO/coverage critique of THIS drawing
|
|
148
|
+
print(issue.severity, issue.code, issue.message)
|
|
149
|
+
|
|
150
|
+
drawing.export("part", formats=("pdf",))
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`sheet.export(...)` remains the one-liner for handwritten scripts that just want the file.
|
|
154
|
+
|
|
141
155
|
See [`docs/multi-feature-object-reference-workflow.md`](docs/multi-feature-object-reference-workflow.md)
|
|
142
156
|
for a complete, runnable walkthrough of this pattern on a multi-feature turned part —
|
|
143
157
|
including the backward-compatible refactor, external threads (no `.thread()` on a step —
|
|
@@ -32,6 +32,7 @@ architecture** table; open retired or superseded records only for design history
|
|
|
32
32
|
| [0013](0013-uniform-recognition-and-shared-package.md) | A uniform recogniser/feature contract (with `b123d-recognisers` as its deferred shared deployment) | Enforce a uniform geometry-only recogniser contract internally; defer package extraction until there is a second consumer. | Accepted; Phase 1 in progress; extraction deferred | `test_recogniser_contract.py`, `test_import_boundaries.py` |
|
|
33
33
|
| [0014](0014-collect-then-solve-annotation-placement.md) | Collect-then-solve annotation placement (as built) | Collect, select, assign, and deterministically solve annotations per corridor before rendering. | Accepted; supersedes 0009 | `test_carve_free_position_callers.py`, `test_strip_layout.py`, `test_layout_property.py`, `test_import_boundaries.py` |
|
|
34
34
|
| [0015](0015-part-drawing-compiler-as-built.md) | The part-drawing compiler, as built | Use one detected-or-declared feature IR and planner-fed dimension groups as the compiler waist. | Accepted; supersedes 0008 | `test_part_model.py`, `test_detect_once.py`, `test_import_boundaries.py` |
|
|
35
|
+
| [0016](0016-declared-dimensioning-intent.md) | Declared dimensioning intent: capture what to measure, let the engine place it | Declare which measurements matter as scale-independent intent routed through the planner and corridor solve; never hardcode dimension geometry. | Accepted; epic #867 complete; phase 6 landed (#940) | `test_compiled_plan_boundary.py`, `test_label_provenance.py`, `test_sheet_emit.py`, `test_add_dimension.py` |
|
|
35
36
|
|
|
36
37
|
## Historical records
|
|
37
38
|
|
|
@@ -46,6 +47,7 @@ architecture** table; open retired or superseded records only for design history
|
|
|
46
47
|
- Compiler and state ownership: 0001 → 0005 → 0015.
|
|
47
48
|
- Recognition and public declaration: 0007 → 0013 → 0011 → 0015.
|
|
48
49
|
- Layout and placement: 0004 → 0014 → 0012.
|
|
50
|
+
- Declared intent and the editable surface: 0001 → 0011 → 0012 → 0016.
|
|
49
51
|
- Quality and correction: 0002, with provenance from 0010.
|
|
50
52
|
|
|
51
53
|
Tracking issue: #745.
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "draftwright"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "Automated technical-drawing generation for build123d"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -101,6 +101,9 @@ precision = 1
|
|
|
101
101
|
exclude_lines = [
|
|
102
102
|
"pragma: no cover",
|
|
103
103
|
"if TYPE_CHECKING:",
|
|
104
|
+
# `@overload` stubs are typing declarations: Python discards the bodies, so they can
|
|
105
|
+
# never execute and counting them as missed coverage measures nothing (#963).
|
|
106
|
+
"@overload",
|
|
104
107
|
]
|
|
105
108
|
|
|
106
109
|
[tool.mypy]
|
|
@@ -17,9 +17,12 @@ to be installed in the execution environment.
|
|
|
17
17
|
2. **Builder (`build_drawing`)** — the same pipeline, but it hands back a live
|
|
18
18
|
`Drawing` you can edit before export.
|
|
19
19
|
|
|
20
|
-
Requires `draftwright >= 0.
|
|
20
|
+
Requires `draftwright >= 0.4.0` and `build123d-drafting-helpers >= 0.14.1`.
|
|
21
21
|
Install: `pip install draftwright`.
|
|
22
22
|
|
|
23
|
+
(The old floor said 0.1.9, which cannot run this guide: none of the feature-backed
|
|
24
|
+
verbs existed then, and the dotted parameter ids in Step 2 are new in 0.4.0.)
|
|
25
|
+
|
|
23
26
|
**Design model (worth knowing before you edit):** the engine is *deterministic*
|
|
24
27
|
— no AI inside it — and you refine a drawing by **stating domain intent**
|
|
25
28
|
(dimension this feature, section through here) and letting the engine **place
|
|
@@ -79,13 +82,16 @@ Then verify (Step 3). For most parts you are done here.
|
|
|
79
82
|
|
|
80
83
|
## Step 2 — Customise with the Drawing builder
|
|
81
84
|
|
|
82
|
-
`build_drawing(...)` returns a live `Drawing`. **Edit it in *domain* vocabulary
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
`
|
|
85
|
+
`build_drawing(...)` returns a live `Drawing`. **Edit it in *domain* vocabulary —
|
|
86
|
+
name a detected *feature* and the measurement you want; the engine decides the
|
|
87
|
+
offset, stacking, and strip slot.** You give *what*, never *where on the page*:
|
|
88
|
+
placement is automatic and constraint-based.
|
|
89
|
+
|
|
90
|
+
Prefer the feature-backed verbs (`dimension` / `locate` / `callout` / `note` /
|
|
91
|
+
`drop`) over the raw page-coordinate primitives. The low-level API (`place_dim`,
|
|
92
|
+
`add`, `add_view`, the view-coordinate plumbing) is **deprecated** — see
|
|
93
|
+
`docs/deprecations.md` — because a raw coordinate does not route through the
|
|
94
|
+
layout solve, so it cannot be re-flowed when anything around it moves.
|
|
89
95
|
|
|
90
96
|
```python
|
|
91
97
|
from draftwright import build_drawing
|
|
@@ -107,61 +113,103 @@ dwg.views # {"front","plan","side","iso"} → (visible, hidden
|
|
|
107
113
|
dwg.draft / dwg.scale / dwg.page_w / dwg.page_h
|
|
108
114
|
```
|
|
109
115
|
|
|
110
|
-
**Add a
|
|
111
|
-
|
|
116
|
+
**Add a dimension by naming a feature and a measurement** — the engine derives the
|
|
117
|
+
value from the geometry and owns the placement:
|
|
112
118
|
|
|
113
119
|
```python
|
|
114
120
|
# side ∈ {"above","below","left","right"}; view ∈ {"front","plan","side"}.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
env = next(f for f in dwg.model().features if f.kind == "envelope")
|
|
122
|
+
hole = next(f for f in dwg.model().features if f.kind == "hole")
|
|
123
|
+
|
|
124
|
+
dwg.dimension(env, "length", role="width", side="above", view="front")
|
|
125
|
+
dwg.locate(hole) # locating dimensions for the feature
|
|
126
|
+
dwg.callout(hole) # a ⌀ callout the auto-pass missed
|
|
118
127
|
|
|
119
|
-
dwg.
|
|
128
|
+
dwg.drop(hole) # stop dimensioning this feature
|
|
129
|
+
|
|
130
|
+
name = next(iter(dwg.annotations())) # names come from annotations(); they are
|
|
131
|
+
dwg.remove(name) # engine-assigned, so don't guess one
|
|
120
132
|
```
|
|
121
133
|
|
|
122
|
-
**
|
|
123
|
-
|
|
124
|
-
|
|
134
|
+
**Mind the two spellings.** On `Drawing.dimension` the second argument is the
|
|
135
|
+
parameter *kind* (`"length"`, `"diameter"`) and `role=` discriminates between
|
|
136
|
+
same-kind parameters — an envelope has three `length` params with roles `width` /
|
|
137
|
+
`height` / `depth`, so `dimension(env, "length")` alone is ambiguous and raises,
|
|
138
|
+
naming them. `feature.parameters()` returns `DimParameter` objects carrying
|
|
139
|
+
`.kind` and `.role`, so `[(p.kind, p.role) for p in feature.parameters()]` is how
|
|
140
|
+
to see what a feature accepts.
|
|
141
|
+
|
|
142
|
+
On the `Sheet` facade the same measurement is one dotted **parameter id** —
|
|
143
|
+
`"width.length"` — and `dimension_ids()` on a handle lists them. Use the id there
|
|
144
|
+
rather than the bare family role (`"width"`): the bare spelling is deprecated,
|
|
145
|
+
because it is what let a single call silently declare two dimensions.
|
|
146
|
+
|
|
147
|
+
`place_dim(p1, p2, side, view, …)` still exists for raw page coordinates, but it is
|
|
148
|
+
the **escape hatch of last resort** (ADR 0012) and is deprecated: it bypasses the
|
|
149
|
+
layout solve, so nothing re-flows around it.
|
|
150
|
+
|
|
151
|
+
**Add a diameter callout on a hole the auto-pass missed** — find the bore in the
|
|
152
|
+
model IR and hand it to `callout()`. This is what the `feature_not_dimensioned`
|
|
153
|
+
lint suggestion hands you (it emits `dwg.callout(f)` — say *what*, not *where*):
|
|
125
154
|
|
|
126
155
|
```python
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if abs(f.diameter - 4.0) < 0.2:
|
|
131
|
-
callout = HoleCallout(f.diameter, count=f.count, through=f.through,
|
|
132
|
-
depth=f.depth, draft=dwg.draft)
|
|
133
|
-
elbow = (f.page_pos[0] + 15, f.page_pos[1] + 10, 0)
|
|
134
|
-
dwg.add(Leader((*f.page_pos, 0), elbow, "", dwg.draft, callout=callout),
|
|
135
|
-
name="hole_4")
|
|
156
|
+
for f in dwg.model().features:
|
|
157
|
+
if f.kind == "hole" and abs(f.diameter - 4.0) < 0.2:
|
|
158
|
+
dwg.callout(f) # engine picks the view, leader and elbow
|
|
136
159
|
```
|
|
137
160
|
|
|
138
|
-
**
|
|
139
|
-
exact spot). Prefer the above; this couples you to page mechanics:
|
|
161
|
+
**Free text** at a chosen point is `note()` — a domain verb, not an escape hatch:
|
|
140
162
|
|
|
141
163
|
```python
|
|
142
|
-
|
|
143
|
-
dwg.add(Leader(tip=dwg.at("front", 10, 0, 5), elbow=(8, 40, 0),
|
|
144
|
-
label="ø4 BORE", draft=dwg.draft), "ldr_bore")
|
|
164
|
+
dwg.note("ø4 BORE", dwg.at("front", 10, 0, 5), view="front")
|
|
145
165
|
```
|
|
146
166
|
|
|
147
167
|
Then re-lint and export:
|
|
148
168
|
|
|
149
169
|
```python
|
|
150
170
|
issues = dwg.lint() # list of LintIssue; [] when clean
|
|
151
|
-
|
|
171
|
+
paths = dwg.export("drawings/bracket", formats=("svg", "dxf", "pdf"))
|
|
172
|
+
svg, dxf = paths["svg"], paths["dxf"]
|
|
152
173
|
```
|
|
153
174
|
|
|
154
|
-
`
|
|
175
|
+
Pass `formats=` and read the `{format: path}` dict. Calling `export()` with no
|
|
176
|
+
`formats` — or with the `svg=`/`dxf=` booleans — takes the legacy path and returns
|
|
177
|
+
a `(svg, dxf)` tuple. Both are deprecated (v0.3.1) and removed in 0.5.0, and both
|
|
178
|
+
warn from 0.4.0. See `docs/deprecations.md`.
|
|
179
|
+
|
|
180
|
+
`make_drawing(...)` is unaffected and does not warn: it still returns
|
|
181
|
+
`(svg_path, dxf_path)`, and passes `formats=` internally to get them.
|
|
182
|
+
|
|
183
|
+
`make_drawing(...)` is `build_drawing(...).export(formats=("svg", "dxf"))`, unpacked to a
|
|
184
|
+
tuple — not a bare `.export()`, which is the deprecated shape above.
|
|
155
185
|
|
|
156
|
-
**
|
|
186
|
+
**Section views** come from the section verb rather than from projecting a view by
|
|
187
|
+
hand. The two entry points are *not* equivalent:
|
|
157
188
|
|
|
158
189
|
```python
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
190
|
+
from draftwright import Sheet
|
|
191
|
+
|
|
192
|
+
# Sheet.section() FORCES a cut, wherever you point it.
|
|
193
|
+
cut = Sheet.from_part(part, number="DWG-042").section().build()
|
|
194
|
+
"section_aa" in cut.views # True
|
|
195
|
+
# section(feature) cuts through that feature; section(at=y) at an explicit Y.
|
|
196
|
+
|
|
197
|
+
# Drawing.section() adds only the AUTOMATIC A–A, which fires just for qualifying
|
|
198
|
+
# hidden internal geometry (a counterbore, spotface, or blind bottom). It returns
|
|
199
|
+
# the placed annotation names, or [] when no section is warranted — so on a plain
|
|
200
|
+
# through-holed block it does nothing at all.
|
|
201
|
+
dwg.section()
|
|
163
202
|
```
|
|
164
203
|
|
|
204
|
+
Arbitrary **auxiliary** views have no public verb: `add_view()` was the way to
|
|
205
|
+
project one and is deprecated, so a custom viewing direction is not currently part
|
|
206
|
+
of the supported surface.
|
|
207
|
+
|
|
208
|
+
`add_view()` and the view-coordinate plumbing (`set_view_coordinates`,
|
|
209
|
+
`drop_view_coordinates`, and the `vc.pp(...)` projector) are **deprecated** (#817):
|
|
210
|
+
view projection is engine plumbing, and hand-placed views do not participate in the
|
|
211
|
+
compose-then-pack layout.
|
|
212
|
+
|
|
165
213
|
---
|
|
166
214
|
|
|
167
215
|
## Step 3 — Verify
|
|
@@ -179,9 +227,9 @@ mcp__build123d-mcp__inspect_drawing(svg_path='drawings/part_name.svg')
|
|
|
179
227
|
**A — Drawing from a STEP file**:
|
|
180
228
|
|
|
181
229
|
```python
|
|
182
|
-
from draftwright import
|
|
230
|
+
from draftwright.sheet_emit import generate_sheet_script
|
|
183
231
|
|
|
184
|
-
|
|
232
|
+
generate_sheet_script(
|
|
185
233
|
"path/to/part.step",
|
|
186
234
|
out="scripts/drawings/bracket",
|
|
187
235
|
title="BRACKET", number="DWG-042",
|
|
@@ -189,6 +237,13 @@ generate_script(
|
|
|
189
237
|
)
|
|
190
238
|
```
|
|
191
239
|
|
|
240
|
+
This writes a declarative `Sheet` script: one named line per detected feature, then the
|
|
241
|
+
dimension set it draws. Comment a feature line out to drop that feature; edit a value
|
|
242
|
+
freely; re-run the file. (`generate_script`, the older imperative flavour, was retired in
|
|
243
|
+
#940 and deleted in 0.4.0 — importing it now fails; use `generate_sheet_script` above.) The
|
|
244
|
+
CLI equivalent is `draftwright part.step
|
|
245
|
+
--script --out scripts/drawings/bracket`.
|
|
246
|
+
|
|
192
247
|
**B — Drawing an in-session object** (hand-write the script):
|
|
193
248
|
|
|
194
249
|
```python
|
|
@@ -235,7 +290,7 @@ crit = dwg.lint_summary()
|
|
|
235
290
|
for i in dwg.lint():
|
|
236
291
|
print(i.severity, i.code, i.message)
|
|
237
292
|
if getattr(i, "suggestion", None):
|
|
238
|
-
print(" fix:", i.suggestion) # e.g. dwg.
|
|
293
|
+
print(" fix:", i.suggestion) # e.g. dwg.callout(...) / dwg.dimension(...)
|
|
239
294
|
|
|
240
295
|
# 3. Self-repair — auto-applies the mechanically-fixable issues (overlapping
|
|
241
296
|
# labels pushed apart, wrong-side dims flipped). Runs by default inside
|
|
@@ -249,8 +304,9 @@ dwg.pin(name) # name from dwg.annotations(); dwg.unpin(name) to rele
|
|
|
249
304
|
|
|
250
305
|
Codes are domain-meaningful (`feature_not_dimensioned`, `feature_count_mismatch`,
|
|
251
306
|
`callout_dropped`, `location_ref_dropped`, `step_dim_dropped`, …), so a fix is
|
|
252
|
-
always expressible through the domain API (`
|
|
253
|
-
never the page-layout internals. Loop until `passed` (or the score
|
|
307
|
+
always expressible through the domain API (`dimension`, `locate`, `callout`,
|
|
308
|
+
`features`), never the page-layout internals. Loop until `passed` (or the score
|
|
309
|
+
plateaus).
|
|
254
310
|
|
|
255
311
|
Coverage-only check, standalone:
|
|
256
312
|
|
|
@@ -24,7 +24,6 @@ from typing import TYPE_CHECKING
|
|
|
24
24
|
# on every TAB press (#313). Each name maps to the submodule that provides it.
|
|
25
25
|
_LAZY = {
|
|
26
26
|
"build_drawing": "draftwright.builder",
|
|
27
|
-
"generate_script": "draftwright.builder",
|
|
28
27
|
"make_drawing": "draftwright.builder",
|
|
29
28
|
"Drawing": "draftwright.drawing",
|
|
30
29
|
"FeatureInfo": "draftwright.drawing",
|
|
@@ -69,7 +68,7 @@ _sys.modules[__name__].__class__ = _DraftwrightModule
|
|
|
69
68
|
|
|
70
69
|
|
|
71
70
|
if TYPE_CHECKING: # static analysers / IDEs — no runtime import, no kernel cost
|
|
72
|
-
from draftwright.builder import build_drawing,
|
|
71
|
+
from draftwright.builder import build_drawing, make_drawing
|
|
73
72
|
from draftwright.compose import choose_scale
|
|
74
73
|
from draftwright.drawing import Drawing, FeatureInfo
|
|
75
74
|
from draftwright.linting import lint_feature_coverage
|
|
@@ -92,7 +91,6 @@ __all__ = [
|
|
|
92
91
|
"build_drawing",
|
|
93
92
|
"choose_scale",
|
|
94
93
|
"extract_pmi",
|
|
95
|
-
"generate_script",
|
|
96
94
|
"lint_feature_coverage",
|
|
97
95
|
"make_drawing",
|
|
98
96
|
]
|