draftwright 0.3.9__tar.gz → 0.4.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.
- {draftwright-0.3.9 → draftwright-0.4.1}/CHANGELOG.md +247 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/PKG-INFO +26 -3
- {draftwright-0.3.9 → draftwright-0.4.1}/README.md +25 -2
- {draftwright-0.3.9 → draftwright-0.4.1}/docs/adr/README.md +4 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/pyproject.toml +21 -3
- {draftwright-0.3.9 → draftwright-0.4.1}/skills/SKILL.md +99 -43
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/__init__.py +8 -3
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/_core.py +311 -53
- draftwright-0.4.1/src/draftwright/_geometry.py +295 -0
- draftwright-0.4.1/src/draftwright/_warnings.py +39 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/analysis.py +124 -42
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/annotate.py +1 -1
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/annotations/_common.py +107 -17
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/annotations/balloons.py +125 -25
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/annotations/from_model.py +1602 -642
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/annotations/holes.py +567 -157
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/annotations/orchestrator.py +99 -31
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/annotations/sections.py +209 -67
- draftwright-0.4.1/src/draftwright/audit.py +249 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/builder.py +190 -431
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/cli.py +36 -63
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/compose.py +61 -54
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/drawing.py +700 -167
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/layout.py +81 -6
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/linting/__init__.py +12 -0
- draftwright-0.4.1/src/draftwright/linting/channel_coverage.py +190 -0
- draftwright-0.4.1/src/draftwright/linting/coverage.py +1320 -0
- draftwright-0.4.1/src/draftwright/linting/flat_coverage.py +207 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/linting/issues.py +4 -0
- draftwright-0.4.1/src/draftwright/linting/profiled_bore_coverage.py +122 -0
- draftwright-0.4.1/src/draftwright/linting/slot_coverage.py +315 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/make_drawing.py +1 -2
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/model/__init__.py +24 -2
- draftwright-0.4.1/src/draftwright/model/callout.py +366 -0
- draftwright-0.4.1/src/draftwright/model/compiled.py +1183 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/model/declare.py +393 -37
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/model/detect.py +183 -36
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/model/ir.py +408 -10
- draftwright-0.4.1/src/draftwright/model/planner.py +867 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/projection.py +9 -1
- draftwright-0.4.1/src/draftwright/py.typed +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/__init__.py +33 -6
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/_features.py +89 -24
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/flats.py +103 -3
- draftwright-0.4.1/src/draftwright/recognition/levels.py +346 -0
- draftwright-0.4.1/src/draftwright/recognition/pads.py +138 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/plates.py +5 -0
- draftwright-0.4.1/src/draftwright/recognition/profiled_bores.py +368 -0
- draftwright-0.4.1/src/draftwright/recognition/result.py +277 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/slots.py +226 -21
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/registry.py +120 -4
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/repair.py +11 -3
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/score.py +2 -0
- draftwright-0.4.1/src/draftwright/sheet.py +1825 -0
- draftwright-0.4.1/src/draftwright/sheet_emit.py +1306 -0
- draftwright-0.4.1/tests/conftest.py +84 -0
- draftwright-0.4.1/tests/fixtures/if_step_flat_across_cylinder.step +189 -0
- draftwright-0.4.1/tests/fixtures/issue_1058_wheel_rh.step +64624 -0
- draftwright-0.4.1/tests/fixtures/issue_909_basic_part_design_017_body.step +465 -0
- draftwright-0.4.1/tests/fixtures/issue_915_case_study_2.step +3527 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/pocketed.json +39 -3
- draftwright-0.4.1/tests/test_add_dimension.py +1358 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_agents_guide.py +2 -2
- draftwright-0.4.1/tests/test_audit_differential.py +768 -0
- draftwright-0.4.1/tests/test_balloon_ring_standoff.py +78 -0
- draftwright-0.4.1/tests/test_compiled_plan_boundary.py +1216 -0
- draftwright-0.4.1/tests/test_counting_calls.py +117 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_declare.py +492 -65
- draftwright-0.4.1/tests/test_declared_recognition_gate.py +542 -0
- draftwright-0.4.1/tests/test_deprecation_dates.py +153 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_detect_once.py +40 -38
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_detect_registry.py +12 -3
- draftwright-0.4.1/tests/test_dimension_role_vocabulary.py +378 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_drawing_encapsulation.py +105 -7
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_e2e_slice.py +3 -1
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_e2e_standards.py +70 -16
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_fits.py +3 -3
- draftwright-0.4.1/tests/test_flat_completeness.py +330 -0
- draftwright-0.4.1/tests/test_flat_stock_identity.py +240 -0
- draftwright-0.4.1/tests/test_flat_stock_opposition.py +63 -0
- draftwright-0.4.1/tests/test_grid_lattice_convention.py +327 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_import_boundaries.py +9 -1
- draftwright-0.4.1/tests/test_issue_1058_wheel_profile.py +676 -0
- draftwright-0.4.1/tests/test_issue_885_prismatic_coverage.py +126 -0
- draftwright-0.4.1/tests/test_issue_909_sloped_profile.py +150 -0
- draftwright-0.4.1/tests/test_issue_915_dense_case.py +108 -0
- draftwright-0.4.1/tests/test_issue_916_pocket_leader.py +102 -0
- draftwright-0.4.1/tests/test_issue_917_open_channel.py +189 -0
- draftwright-0.4.1/tests/test_label_provenance.py +206 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_layout.py +80 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_lint_reconciliation.py +3 -3
- draftwright-0.4.1/tests/test_location_vocabulary.py +400 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_make_drawing.py +1214 -324
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_object_aspects.py +6 -6
- draftwright-0.4.1/tests/test_parameter_id.py +537 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_part_model.py +2 -2
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_pmi.py +3 -1
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_pocket_pattern.py +8 -7
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_pocket_pattern_recognition.py +29 -1
- draftwright-0.4.1/tests/test_principal_profile_classifier.py +122 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_private_test_attr_reads.py +0 -7
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_recogniser_contract.py +35 -4
- draftwright-0.4.1/tests/test_recognition_manifest.py +567 -0
- draftwright-0.4.1/tests/test_recognition_result.py +340 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_registry.py +93 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_render_seam.py +37 -1
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_script_detail_parity.py +121 -54
- draftwright-0.4.1/tests/test_sheet_emit.py +3426 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_sheet_gdt.py +12 -12
- draftwright-0.4.1/tests/test_sheet_identity_invariant.py +807 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_sheet_notes.py +14 -14
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_sheet_of.py +3 -3
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_sheet_section.py +1 -1
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_sheet_tables.py +3 -1
- draftwright-0.4.1/tests/test_slanted_blind_step.py +291 -0
- draftwright-0.4.1/tests/test_slot_completeness.py +595 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_slot_pattern.py +10 -8
- draftwright-0.4.1/tests/test_soft_deprecation.py +221 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_solve_trace.py +5 -2
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_strip_layout.py +69 -5
- draftwright-0.4.1/tests/test_suppression_ledger.py +380 -0
- draftwright-0.4.1/tests/test_suppression_marks.py +553 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_tolerances.py +64 -40
- draftwright-0.3.9/src/draftwright/_geometry.py +0 -142
- draftwright-0.3.9/src/draftwright/linting/coverage.py +0 -581
- draftwright-0.3.9/src/draftwright/model/planner.py +0 -320
- draftwright-0.3.9/src/draftwright/recognition/levels.py +0 -175
- 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.1}/.gitignore +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/LICENSE +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/annotations/__init__.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/export.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/fits.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/fonts/IBMPlexMono-Regular.ttf +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/fonts/IBMPlexSansCondensed-Regular.ttf +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/fonts/LICENSE-IBMPlexMono-OFL.txt +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/fonts/LICENSE-IBMPlexSansCondensed-OFL.txt +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/fonts/__init__.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/intents.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/linting/structural.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/linting/suggest.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/pmi.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/_record.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/chamfers.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/countersinks.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/fillets.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/grooves.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/src/draftwright/recognition/turned.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/_kernel.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/_layout_sig.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/grm03_thumbwheel_drive_screw.step +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/nist_ctc_01_asme1_ap203.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/nist_ctc_02_asme1_ap203.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/nist_ctc_02_asme1_ap242.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/nist_ctc_03_asme1_ap203.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/nist_ctc_03_asme1_ap242.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/nist_ctc_04_asme1_ap203.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/nist_ctc_04_asme1_ap242.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/nist_ctc_05_asme1_ap203.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/nist_ctc_05_asme1_ap242.stp +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/fixtures/tuner_jig_blind_obround_pockets.step +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/bracket_section.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/centered_rebate.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/chamfered.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/filleted.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/flange_dense.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/grid_plate.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/grooved_shaft.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/hex_bar.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/holed_slot.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/prismatic_ladder.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/scattered_plate.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/side_drilled.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/refactor_golden/turned_stepped.json +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_architecture_docs.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_carve_free_position_callers.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_dense_sheet_canary.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_export_dxf_zoom.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_fillets_adjacency.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_gdt_placement.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_layout_cleanliness.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_layout_hypothesis.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_layout_property.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_lint_box_cache.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_lint_structural.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_linting.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_note_verb.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_occupancy_boxes.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_pitch_dim_footprint.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_private_test_imports.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_recognition.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_refactor_golden.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_score.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_slot_pattern_recognition.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_turned_steps.py +0 -0
- {draftwright-0.3.9 → draftwright-0.4.1}/tests/test_witness_label_reconciliation.py +0 -0
|
@@ -1,5 +1,252 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## v0.4.1 — 2026-08-07
|
|
6
|
+
|
|
7
|
+
**The recognition trust release.** Automatic drawings now fail closed on unsupported inner
|
|
8
|
+
profiles, prove semantic coverage for flats, slots and patterns, and retain the measurement
|
|
9
|
+
identity needed to explain placed, suppressed, dropped and missing definitions. Several real
|
|
10
|
+
STEP case studies also move from clean-looking but incomplete output to complete drawings or
|
|
11
|
+
actionable lint.
|
|
12
|
+
|
|
13
|
+
### Discouraged (supported)
|
|
14
|
+
|
|
15
|
+
- **`Sheet.auto_dimensions()` and `Sheet.add_dimension()` now emit
|
|
16
|
+
`SoftDeprecationWarning`** (#1043). They remain supported with no removal planned; the
|
|
17
|
+
warning steers declared scripts toward `authored_dimensions()` plus explicit
|
|
18
|
+
`dimension(feature, parameter_id)` lines, where omission can mean suppression. Automatic
|
|
19
|
+
`build_drawing(part)` and the `Sheet.from_part(part)` on-ramp remain silent. See
|
|
20
|
+
`docs/deprecations.md` for filtering and migration guidance.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **Finished drawings expose why measurements were omitted and, on covered placement paths,
|
|
25
|
+
what an annotation measures** (#996/#1002). `Drawing.suppressions()` returns the compiler's
|
|
26
|
+
omission ledger, `Drawing.measurement_keys(name)` exposes recorded measurement provenance, and
|
|
27
|
+
`draftwright.audit.diff_builds(before, after)` reports losses, substitutions and candidate
|
|
28
|
+
suppression explanations. The differential is deliberately a triage aid, not a proof where
|
|
29
|
+
renderer identity remains incomplete.
|
|
30
|
+
|
|
31
|
+
- **Physical-completeness lint now follows semantic correspondence for flats, lone slots and
|
|
32
|
+
slot patterns** (#1018). Coverage is joined through recognition, IR and compiler identities
|
|
33
|
+
rather than inferred from label text or page geometry, and distinguishes authored
|
|
34
|
+
suppression, placement drops, missing definitions and unverifiable provenance.
|
|
35
|
+
|
|
36
|
+
- **Full-span floored open channels are recognised and dimensioned as first-class features**
|
|
37
|
+
(#917). Automatic and declared drawings state the independent overall extent, one wall and
|
|
38
|
+
channel width, suppress the derived opposite wall, and report any missing member of that
|
|
39
|
+
defining chain.
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
43
|
+
- **Square and near-square parts retain both independent planar extents** (#997). A plain
|
|
44
|
+
square plate could previously lose both plan dimensions, while parts up to five percent off
|
|
45
|
+
square could lose one and be silently represented as square. The unsafe suppression rule is
|
|
46
|
+
removed; explicit square notation remains tracked separately in #918.
|
|
47
|
+
|
|
48
|
+
- **Machined flats retain their physical stock identity from recognition through placement
|
|
49
|
+
and completeness lint** (#1013/#1015/#1034/#1036). Flats on separate parallel, coaxial or
|
|
50
|
+
slanted stock no longer collapse into one definition or borrow an opposite face from another
|
|
51
|
+
stock region. Independent callouts receive clear-margin candidates, while double-D faces on
|
|
52
|
+
one stock still form one A/F requirement.
|
|
53
|
+
|
|
54
|
+
- **Dense callout and step-detail cases keep their complete defining set** (#915). Hole
|
|
55
|
+
callout batches are reconciled as a queue, detail views fit their actual aspect, step levels
|
|
56
|
+
retain the supporting-face correspondence needed for truthful crops, and a detail redraws
|
|
57
|
+
only rungs omitted from its parent view.
|
|
58
|
+
|
|
59
|
+
- **Pocket leaders start on the physical opening rim** (#916), removing the spurious inner
|
|
60
|
+
silhouette crossing while preserving the solved label corridor and approved dimensions on
|
|
61
|
+
X-, Y- and Z-depth pockets.
|
|
62
|
+
|
|
63
|
+
- **Wedge-mounted raised pads survive recognition** (#909). Lower ledges that touch only in
|
|
64
|
+
plan no longer make the recogniser discard a valid upper pad; true staircase tiers remain
|
|
65
|
+
excluded.
|
|
66
|
+
|
|
67
|
+
- **Annotation-dense detail placement no longer stalls the build** (#1065). Detail views
|
|
68
|
+
avoid every decomposed annotation shaft, witness, label and item footprint; CTC-02
|
|
69
|
+
supplies 571 such boxes. The free-rectangle search previously treated that set as tiny
|
|
70
|
+
and admitted roughly 34 billion candidate rectangles, exhausting the slow tier's
|
|
71
|
+
ten-minute test budget before export. A compressed-coordinate sweep preserves the same
|
|
72
|
+
deterministic winning rectangle while completing the real search in seconds.
|
|
73
|
+
|
|
74
|
+
- **Through double-D bores are recognised and called out as first-class hole profiles**
|
|
75
|
+
(#1061). Automatic and declared builds preserve the parent-circle diameter, A/F size,
|
|
76
|
+
orientation and depth, and render one compound `DOUBLE-D ... A/F` bore callout. Physical
|
|
77
|
+
critique now accepts that supported inner profile while retaining a separate warning for
|
|
78
|
+
13 evenly spaced common-circle arcs on the unresolved outer boundary; it does not infer a
|
|
79
|
+
repeating full profile or a gear standard.
|
|
80
|
+
|
|
81
|
+
- **Unsupported internal profiles no longer pass physical-completeness lint silently**
|
|
82
|
+
(#1058). Inner loops on principal boundary faces are checked against the current
|
|
83
|
+
circular-hole, rectangular-opening, true-obround, and proven through-double-D vocabulary.
|
|
84
|
+
Profiles outside it now produce
|
|
85
|
+
`unrecognised_defining_geometry` and reduce the lint score instead of allowing an
|
|
86
|
+
envelope-only drawing to score 1.0.
|
|
87
|
+
|
|
88
|
+
### Changed
|
|
89
|
+
|
|
90
|
+
- **Crowded prismatic step dimensions recover into an enlarged detail view by default**
|
|
91
|
+
(#909). The automatic `build_drawing` / `make_drawing` / CLI paths and generated
|
|
92
|
+
`Sheet` scripts now preserve the omitted dimensions instead of returning
|
|
93
|
+
`step_dim_dropped` unless the caller remembered `detail_view=True`. Pass
|
|
94
|
+
`detail_view=False` to retain the parent-view-only behavior and its lint warning.
|
|
95
|
+
|
|
96
|
+
## v0.4.0 — 2026-08-02
|
|
97
|
+
|
|
98
|
+
**The compat-exit release.** Every surface whose documented removal target was 0.4.0 is gone,
|
|
99
|
+
and every deprecation that remains now says when it goes — in the message the caller sees, not
|
|
100
|
+
only in a release note. ADR 0005 §4's rule is that an alias carries a tracking issue *and* a
|
|
101
|
+
removal date, because "a facade with no exit date is a failure mode"; this release is that rule
|
|
102
|
+
being kept rather than restated. `docs/deprecations.md` is the new index, and
|
|
103
|
+
`tests/test_deprecation_dates.py` fails any deprecation that names no removal.
|
|
104
|
+
|
|
105
|
+
Also lands ADR 0016's declared-dimensioning work (#867): a `dimension(feature, role)` is
|
|
106
|
+
referential — it names a measurement and carries no number — and an authored set means omission
|
|
107
|
+
is suppression, enforced at the compiled-plan boundary rather than by a flag renderers check.
|
|
108
|
+
|
|
109
|
+
**Read this before upgrading:** two removals break *without a release that warned you*, because
|
|
110
|
+
their deprecation never appeared in a shipped version. See *Removed (breaking)* below and
|
|
111
|
+
`docs/deprecations.md`.
|
|
112
|
+
|
|
113
|
+
### Removed (breaking)
|
|
114
|
+
|
|
115
|
+
Compat surfaces whose documented removal target was 0.4.0 (#720, ADR 0005 §4 — every alias
|
|
116
|
+
carries a tracking issue *and* a removal date, or the facade is permanent by accident):
|
|
117
|
+
|
|
118
|
+
- **The seven `Drawing` compat aliases** — `_named` / `_anno_view` / `_pinned` /
|
|
119
|
+
`_build_issues`, and `_pattern_callouts` / `_patterned_holes` / `_dropped_callout_diams`.
|
|
120
|
+
These were private, and the public reads have existed since #699: use `dwg.registry`
|
|
121
|
+
(`in reg`, `names()`, `issues`, `pinned_names()`) and `dwg.coverage`, or the `Drawing` verbs
|
|
122
|
+
`annotations()` / `iter_annotations()` / `get_annotation()` / `view_of()`.
|
|
123
|
+
**Note the asymmetry.** A *read* — `dwg._named` — now raises `AttributeError`. A *write* —
|
|
124
|
+
`dwg._pinned = {...}` — does **not**: these were properties with setters, and `Drawing` has
|
|
125
|
+
no `__slots__`, so assignment now quietly creates an unrelated instance attribute that no
|
|
126
|
+
longer reaches the registry or coverage owner. Writes therefore fail silently rather than
|
|
127
|
+
loudly. Grep for `\._(named|anno_view|pinned|build_issues|pattern_callouts|patterned_holes|dropped_callout_diams)\b`
|
|
128
|
+
before upgrading; mutate through `registry.add()` / `pin()` / `record_issue()` /
|
|
129
|
+
`restore_issues()` and the `CoverageState` methods instead.
|
|
130
|
+
- **The `draftwright.sheet_dsl` module** — an import alias for `draftwright.sheet` since the
|
|
131
|
+
#640 rename. Import `Sheet` from `draftwright` or `draftwright.sheet`.
|
|
132
|
+
- **`generate_script`**, including its `draftwright.__all__` entry. It has raised since #940
|
|
133
|
+
retired the imperative emitter; it is now simply absent, so the failure is an `ImportError`
|
|
134
|
+
at the top of a script rather than a `RuntimeError` part-way through one. Use
|
|
135
|
+
`--script` / `emit_sheet_script`.
|
|
136
|
+
- **The bespoke `--style imperative` error message.** `--style` itself is unchanged and still
|
|
137
|
+
accepts its sole value `sheet`; `imperative` is now an unrecognised value like any typo,
|
|
138
|
+
rather than one carrying its own explanation of the #940 retirement.
|
|
139
|
+
|
|
140
|
+
- **Bare dimension-role spellings** — `sheet.dimension(f, "width")`. Use the parameter id,
|
|
141
|
+
`"width.length"`; `dimension_ids()` on a handle lists the valid ones. The bare role is the
|
|
142
|
+
*family* spelling: it selects every parameter carrying it, which is how
|
|
143
|
+
`dimension(step, "step")` quietly declared two measurements. In an authored set, where
|
|
144
|
+
omission means suppression, silently declaring an extra one is the mirror image of the rule
|
|
145
|
+
— so it now raises rather than resolving. (A *discriminated* bare role, used with `axis=`,
|
|
146
|
+
is unaffected: that is how variants like `grid_pitch.length.row` are addressed, and it never
|
|
147
|
+
warned.)
|
|
148
|
+
- **The `Sheet.dimension(kind=…, value=…)` call shape** — use `Sheet.measured_dimension(...)`.
|
|
149
|
+
`dimension` is now solely the ADR 0016 referential verb: it names a feature and a parameter
|
|
150
|
+
id and reads the value off the geometry.
|
|
151
|
+
|
|
152
|
+
Those last two break **without a release that warns you**. They were deprecated after v0.3.9
|
|
153
|
+
and removed in 0.4.0, so the `DeprecationWarning` never appeared in a released version —
|
|
154
|
+
upgrading from v0.3.9 or earlier goes straight from working to a raise. That is deliberate
|
|
155
|
+
(ADR 0016); this entry and `docs/deprecations.md` are the only notice you get, so both
|
|
156
|
+
failures name their replacement rather than raising about argument counts.
|
|
157
|
+
|
|
158
|
+
### Deprecated
|
|
159
|
+
|
|
160
|
+
- **The legacy `Drawing.export` shapes now emit `DeprecationWarning`** (#987) — they were
|
|
161
|
+
announced as deprecated in v0.3.1 and then said nothing at runtime for four minor releases,
|
|
162
|
+
which would have made their 0.5.0 removal a silent break. Three cases warn:
|
|
163
|
+
- `export()` with `formats=` **omitted or `None`** — the legacy default, which writes
|
|
164
|
+
SVG + DXF and returns an `(svg, dxf)` **tuple** rather than the `{format: path}` dict.
|
|
165
|
+
- the **`svg=` / `dxf=` booleans**. The suggested replacement names the formats *that call*
|
|
166
|
+
selected, so following it cannot change what gets written.
|
|
167
|
+
- passing a boolean **alongside** `formats=`, where it is silently ignored — `formats` wins,
|
|
168
|
+
and now says so.
|
|
169
|
+
|
|
170
|
+
**If you promote `DeprecationWarning` to an error, previously-passing exports will now
|
|
171
|
+
raise.** Migration: `export(out, formats=("svg", "dxf"))` and read the dict. `make_drawing`
|
|
172
|
+
is unaffected — it returns the same tuple and does not warn.
|
|
173
|
+
|
|
174
|
+
### Added
|
|
175
|
+
|
|
176
|
+
- **`sheet.add_dimension(feature, role)` — ask the planner to carry one more
|
|
177
|
+
measurement** (ADR 0016 / #872). Referential: it names a feature and a role and
|
|
178
|
+
carries **no number**, so the value still comes from the geometry and a size lives in
|
|
179
|
+
exactly one place. It changes *selection*, not derivation — a request can never
|
|
180
|
+
introduce a number the part does not have. Requesting something the planner already
|
|
181
|
+
emits is a deliberate no-op, so a script can ask without first knowing the rule set's
|
|
182
|
+
mind. `sheet.auto_dimensions()` states the source explicitly (optional in this
|
|
183
|
+
release; #874 makes it mandatory).
|
|
184
|
+
- **Suppressing a dimension marks it; it no longer leaks into the callout** (ADR 0016 /
|
|
185
|
+
#875). `PlannedDimension.suppressed` was honoured at thirteen render sites but not by
|
|
186
|
+
the compound hole-callout path, so a suppressed counterbore still printed. The group
|
|
187
|
+
keeps its engineering data either way — what changes is whether a value reaches the
|
|
188
|
+
page. Suppressing the bore ⌀ while a counterbore, spotface or countersink segment
|
|
189
|
+
remains now **raises** and names the orphan: `⌀20 THRU ⌴ ⌀32 ↓ 1.5` has no reading with
|
|
190
|
+
its leading term removed, and silently dropping the segments would discard authored
|
|
191
|
+
intent while silently restoring the head would make the drawing say something the
|
|
192
|
+
script does not.
|
|
193
|
+
- **Addressable dimension identity** (#869/#870/#871): every planned measurement now has
|
|
194
|
+
a stable `DimensionId(feature, parameter)`, and correlated measurements that must be
|
|
195
|
+
named as one — a grid pattern's row and column pitch, a step ladder — group into an
|
|
196
|
+
`AddressableDimension`. This is what a `dimension(...)` line will name, and what
|
|
197
|
+
suppression and provenance key on.
|
|
198
|
+
|
|
199
|
+
### Changed
|
|
200
|
+
|
|
201
|
+
- **`Sheet.dimension(kind=…, value=…)` is now `Sheet.measured_dimension(...)`**
|
|
202
|
+
(ADR 0016 / #873), and `model.declare.authored_dimension` is
|
|
203
|
+
`model.declare.measured_dimension` to match. This **reserves** the name `dimension` for
|
|
204
|
+
the referential verb ADR 0016 defines — name a feature and a role, carry no number, let
|
|
205
|
+
the engine read the value off the geometry — which `Drawing.dimension` already is and
|
|
206
|
+
`Sheet.dimension` will become. The verb that carries an explicit number needed a name
|
|
207
|
+
saying so first. The old spelling was a transitional overload during development and is
|
|
208
|
+
**removed in this same release** (#720) rather than shipping — `Sheet.dimension` is solely
|
|
209
|
+
the referential verb, and the old keyword call raises with `measured_dimension` named. See
|
|
210
|
+
*Removed (breaking)* above. Generated AP242 scripts emit `measured_dimension` and so arrive
|
|
211
|
+
un-deprecated.
|
|
212
|
+
- **`Sheet` handles address features by identity, not position** (#908/#910/#912). A
|
|
213
|
+
handle, tolerance, GD&T origin, section request or dimension intent now follows *its*
|
|
214
|
+
feature through a `features` reorder instead of naming whatever took the slot.
|
|
215
|
+
Reordering with `reverse()`/`sort()` preserves every reference; deleting or replacing
|
|
216
|
+
a referenced feature raises rather than silently retargeting a neighbour. `of()` now
|
|
217
|
+
accepts a handle, and negative indices resolve uniformly across `of()`,
|
|
218
|
+
`add_dimension()` and the GD&T verbs.
|
|
219
|
+
|
|
220
|
+
### Fixed
|
|
221
|
+
|
|
222
|
+
- **`sheet.envelope()` measured the file, not the part** (#977). An AP242 STEP import is a
|
|
223
|
+
compound of the solid *plus its PMI presentation geometry* — annotation planes, leader
|
|
224
|
+
curves — and the declared verb measured all of it. On the NIST CTC-01 fixture it declared
|
|
225
|
+
1170 × 650 where the part is 800 × 450: an envelope 370 mm too wide, silently, in anything
|
|
226
|
+
declared by hand. `step_level()` had the same exposure, offsetting every step position by
|
|
227
|
+
the annotation overhang. Both now measure the solid body, sharing the helper the engine
|
|
228
|
+
already used for exactly this (`_analyse` and `Sheet.model`).
|
|
229
|
+
- **A declared envelope's frame origin sat a half-height below a detected one** (#977). It
|
|
230
|
+
used `bbox_min.Z` where the detector uses the bbox centre. **Dimension output is unchanged** —
|
|
231
|
+
envelope sizes derive from `bbox_min`/`bbox_max`, and the overall height is compiled from the
|
|
232
|
+
model bbox — but `frame.origin` is the generic feature *site*, so **a GD&T control frame,
|
|
233
|
+
surface finish or note targeting a hand-declared `sheet.envelope()` was anchored at the
|
|
234
|
+
bottom face rather than the centre, and its leader now moves to the centre**. That is a
|
|
235
|
+
visible change on drawings carrying such an annotation; drawings without one are unaffected.
|
|
236
|
+
Scripts generated by `--script` were never affected either way: they bake the detected frame
|
|
237
|
+
explicitly rather than calling the verb.
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
- **Front-view dimensions join the placement solve instead of committing to the strip**
|
|
241
|
+
(#894): they previously took strip space before the global solve ran, so a
|
|
242
|
+
higher-ranked dimension could find its space already gone. Priority only ranks
|
|
243
|
+
candidates that are *in* the solve.
|
|
244
|
+
- **A hole callout reads the feature's own `through` fact** (#868) rather than inferring
|
|
245
|
+
it from whether a depth parameter happens to be present — so a suppressed depth can no
|
|
246
|
+
longer make a blind hole print `THRU`.
|
|
247
|
+
- **The balloon ring clears the view it annotates after a hole-table escalation**
|
|
248
|
+
(#901/#903).
|
|
249
|
+
|
|
3
250
|
## v0.3.9 — 2026-07-26
|
|
4
251
|
|
|
5
252
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: draftwright
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
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
|
|
@@ -771,9 +771,12 @@ from draftwright import build_drawing
|
|
|
771
771
|
|
|
772
772
|
dwg = build_drawing(part, title="Mounting Plate")
|
|
773
773
|
issues = dwg.lint() # list[LintIssue] — coverage, page bounds, ISO
|
|
774
|
-
|
|
774
|
+
paths = dwg.export("my_part", formats=("svg", "dxf")) # {"svg": ..., "dxf": ...}
|
|
775
775
|
```
|
|
776
776
|
|
|
777
|
+
`export()` with no `formats=` returns the old `(svg, dxf)` tuple; that shape is deprecated
|
|
778
|
+
and removed in 0.5.0 (see [docs/deprecations.md](docs/deprecations.md)).
|
|
779
|
+
|
|
777
780
|
### Declarative drawings — reference features, declare intent
|
|
778
781
|
|
|
779
782
|
Instead of relying on detection, **reference the build123d objects you built** and declare
|
|
@@ -789,10 +792,16 @@ plate = Box(120, 80, 20)
|
|
|
789
792
|
bore = Pos(0, 0, 0) * Cylinder(4, 20)
|
|
790
793
|
|
|
791
794
|
sheet = Sheet(plate - bore, title="Plate", number="DWG-002")
|
|
792
|
-
sheet.envelope()
|
|
795
|
+
env = sheet.envelope()
|
|
793
796
|
sheet.datum("A", plate.faces().sort_by()[-1]) # datum A on the top face
|
|
794
797
|
hole = sheet.hole(bore).finish("1.6").note("M3x0.5 TAP") # ⌀8 bore, Ra 1.6, tapped
|
|
795
798
|
sheet.control(hole).position(0.1, to="A", diameter=True) # ⌀0.1 position wrt A
|
|
799
|
+
|
|
800
|
+
sheet.authored_dimensions() # THIS is the complete set
|
|
801
|
+
sheet.dimension(env, "width.length") # (ADR 0016: a build says where
|
|
802
|
+
sheet.dimension(env, "height.length") # its dimensions come from, and
|
|
803
|
+
sheet.dimension(hole, "bore.diameter") # omitting one means suppress it)
|
|
804
|
+
|
|
796
805
|
sheet.export("plate") # writes plate.pdf
|
|
797
806
|
```
|
|
798
807
|
|
|
@@ -834,6 +843,20 @@ sheet.hole(features.m3_bore).thread("M3x0.5").finish("1.6") # tapped + Ra on t
|
|
|
834
843
|
An object-sourced script carries an inline tip pointing at exactly this edit; a STEP-sourced
|
|
835
844
|
script keeps the detected numbers (there's no object to reference).
|
|
836
845
|
|
|
846
|
+
Every generated script ends by naming the drawing it built, so you can critique or inspect it
|
|
847
|
+
before (or instead of) exporting — one build, not two:
|
|
848
|
+
|
|
849
|
+
```python
|
|
850
|
+
drawing = sheet.build()
|
|
851
|
+
|
|
852
|
+
for issue in drawing.lint(): # ISO/coverage critique of THIS drawing
|
|
853
|
+
print(issue.severity, issue.code, issue.message)
|
|
854
|
+
|
|
855
|
+
drawing.export("part", formats=("pdf",))
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
`sheet.export(...)` remains the one-liner for handwritten scripts that just want the file.
|
|
859
|
+
|
|
837
860
|
See [`docs/multi-feature-object-reference-workflow.md`](docs/multi-feature-object-reference-workflow.md)
|
|
838
861
|
for a complete, runnable walkthrough of this pattern on a multi-feature turned part —
|
|
839
862
|
including the backward-compatible refactor, external threads (no `.thread()` on a step —
|
|
@@ -75,9 +75,12 @@ from draftwright import build_drawing
|
|
|
75
75
|
|
|
76
76
|
dwg = build_drawing(part, title="Mounting Plate")
|
|
77
77
|
issues = dwg.lint() # list[LintIssue] — coverage, page bounds, ISO
|
|
78
|
-
|
|
78
|
+
paths = dwg.export("my_part", formats=("svg", "dxf")) # {"svg": ..., "dxf": ...}
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
`export()` with no `formats=` returns the old `(svg, dxf)` tuple; that shape is deprecated
|
|
82
|
+
and removed in 0.5.0 (see [docs/deprecations.md](docs/deprecations.md)).
|
|
83
|
+
|
|
81
84
|
### Declarative drawings — reference features, declare intent
|
|
82
85
|
|
|
83
86
|
Instead of relying on detection, **reference the build123d objects you built** and declare
|
|
@@ -93,10 +96,16 @@ plate = Box(120, 80, 20)
|
|
|
93
96
|
bore = Pos(0, 0, 0) * Cylinder(4, 20)
|
|
94
97
|
|
|
95
98
|
sheet = Sheet(plate - bore, title="Plate", number="DWG-002")
|
|
96
|
-
sheet.envelope()
|
|
99
|
+
env = sheet.envelope()
|
|
97
100
|
sheet.datum("A", plate.faces().sort_by()[-1]) # datum A on the top face
|
|
98
101
|
hole = sheet.hole(bore).finish("1.6").note("M3x0.5 TAP") # ⌀8 bore, Ra 1.6, tapped
|
|
99
102
|
sheet.control(hole).position(0.1, to="A", diameter=True) # ⌀0.1 position wrt A
|
|
103
|
+
|
|
104
|
+
sheet.authored_dimensions() # THIS is the complete set
|
|
105
|
+
sheet.dimension(env, "width.length") # (ADR 0016: a build says where
|
|
106
|
+
sheet.dimension(env, "height.length") # its dimensions come from, and
|
|
107
|
+
sheet.dimension(hole, "bore.diameter") # omitting one means suppress it)
|
|
108
|
+
|
|
100
109
|
sheet.export("plate") # writes plate.pdf
|
|
101
110
|
```
|
|
102
111
|
|
|
@@ -138,6 +147,20 @@ sheet.hole(features.m3_bore).thread("M3x0.5").finish("1.6") # tapped + Ra on t
|
|
|
138
147
|
An object-sourced script carries an inline tip pointing at exactly this edit; a STEP-sourced
|
|
139
148
|
script keeps the detected numbers (there's no object to reference).
|
|
140
149
|
|
|
150
|
+
Every generated script ends by naming the drawing it built, so you can critique or inspect it
|
|
151
|
+
before (or instead of) exporting — one build, not two:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
drawing = sheet.build()
|
|
155
|
+
|
|
156
|
+
for issue in drawing.lint(): # ISO/coverage critique of THIS drawing
|
|
157
|
+
print(issue.severity, issue.code, issue.message)
|
|
158
|
+
|
|
159
|
+
drawing.export("part", formats=("pdf",))
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`sheet.export(...)` remains the one-liner for handwritten scripts that just want the file.
|
|
163
|
+
|
|
141
164
|
See [`docs/multi-feature-object-reference-workflow.md`](docs/multi-feature-object-reference-workflow.md)
|
|
142
165
|
for a complete, runnable walkthrough of this pattern on a multi-feature turned part —
|
|
143
166
|
including the backward-compatible refactor, external threads (no `.thread()` on a step —
|
|
@@ -32,6 +32,8 @@ 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` |
|
|
36
|
+
| [0017](0017-recognition-inventory-correspondence-and-measurement-provenance.md) | One recognition result per run; correspondence is evidence-gated | Produce one explicit recognition result owned by `BuildState`; require vertical-slice evidence before generalising correspondence, identity, requirements, outcomes, or reconciliation. | Accepted; ownership phase landed, extensions gated by #1018 | `test_recognition_manifest.py`, `test_recognition_result.py`, `test_declared_recognition_gate.py` |
|
|
35
37
|
|
|
36
38
|
## Historical records
|
|
37
39
|
|
|
@@ -46,6 +48,8 @@ architecture** table; open retired or superseded records only for design history
|
|
|
46
48
|
- Compiler and state ownership: 0001 → 0005 → 0015.
|
|
47
49
|
- Recognition and public declaration: 0007 → 0013 → 0011 → 0015.
|
|
48
50
|
- Layout and placement: 0004 → 0014 → 0012.
|
|
51
|
+
- Declared intent and the editable surface: 0001 → 0011 → 0012 → 0016.
|
|
49
52
|
- Quality and correction: 0002, with provenance from 0010.
|
|
53
|
+
- Recognition correspondence and completeness: 0007 → 0013 → 0015 → 0017.
|
|
50
54
|
|
|
51
55
|
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.1"
|
|
8
8
|
description = "Automated technical-drawing generation for build123d"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -80,6 +80,18 @@ markers = [
|
|
|
80
80
|
"slow: heavy end-to-end CTC fixture builds (deselected by default)",
|
|
81
81
|
"smoke: curated build-light subset for a fast local check (~30 s)",
|
|
82
82
|
]
|
|
83
|
+
# `SoftDeprecationWarning` marks a surface that is discouraged but SUPPORTED and not going
|
|
84
|
+
# away (#1043). The suite exercises `Sheet.auto_dimensions()` in ~170 places, deliberately —
|
|
85
|
+
# it is still a supported path and its behaviour must keep being tested. Migrating those to
|
|
86
|
+
# authored dimensions would be churn that tests less, so the category is silenced here rather
|
|
87
|
+
# than at ~170 call sites.
|
|
88
|
+
#
|
|
89
|
+
# This does NOT weaken the guard: `tests/test_soft_deprecation.py` asserts the warning with
|
|
90
|
+
# `pytest.warns`, which fires regardless of this filter. Real `DeprecationWarning`s are
|
|
91
|
+
# untouched and still carry removal dates (`tests/test_deprecation_dates.py`).
|
|
92
|
+
filterwarnings = [
|
|
93
|
+
"ignore::draftwright.SoftDeprecationWarning",
|
|
94
|
+
]
|
|
83
95
|
# Coverage is a CI concern (it adds ~13% locally and instruments every line); the
|
|
84
96
|
# CI workflow passes the --cov flags explicitly. Keep the local default lean.
|
|
85
97
|
addopts = "--tb=short -m 'not slow'"
|
|
@@ -87,6 +99,9 @@ addopts = "--tb=short -m 'not slow'"
|
|
|
87
99
|
[tool.coverage.run]
|
|
88
100
|
source = ["src/draftwright"]
|
|
89
101
|
omit = ["src/draftwright/__init__.py"]
|
|
102
|
+
# Keep XML paths anchored at the repository root so local diff coverage and Codecov
|
|
103
|
+
# measure the same changed source lines rather than relying on runner-specific paths.
|
|
104
|
+
relative_files = true
|
|
90
105
|
# Branch coverage makes the regression gate sensitive to untested decision paths,
|
|
91
106
|
# which matter more than raw statement execution in the recognition/layout code.
|
|
92
107
|
branch = true
|
|
@@ -94,13 +109,16 @@ branch = true
|
|
|
94
109
|
[tool.coverage.report]
|
|
95
110
|
# Baseline measured on the full fast tier on Linux/Python 3.13 (#825):
|
|
96
111
|
# 92.05% combined line+branch coverage (93.90% statements, 86.89% branches).
|
|
97
|
-
# Keep two points of
|
|
98
|
-
#
|
|
112
|
+
# Keep two points of headroom; ratchet upward only after the canonical coverage job
|
|
113
|
+
# has stayed above the proposed floor.
|
|
99
114
|
fail_under = 90
|
|
100
115
|
precision = 1
|
|
101
116
|
exclude_lines = [
|
|
102
117
|
"pragma: no cover",
|
|
103
118
|
"if TYPE_CHECKING:",
|
|
119
|
+
# `@overload` stubs are typing declarations: Python discards the bodies, so they can
|
|
120
|
+
# never execute and counting them as missed coverage measures nothing (#963).
|
|
121
|
+
"@overload",
|
|
104
122
|
]
|
|
105
123
|
|
|
106
124
|
[tool.mypy]
|