draftwright 0.4.12__tar.gz → 0.4.13__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. {draftwright-0.4.12 → draftwright-0.4.13}/PKG-INFO +1 -1
  2. {draftwright-0.4.12 → draftwright-0.4.13}/pyproject.toml +1 -1
  3. draftwright-0.4.13/src/draftwright/_build_profile.py +186 -0
  4. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/_geometry.py +9 -0
  5. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/annotations/_common.py +31 -0
  6. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/annotations/from_model.py +133 -469
  7. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/annotations/holes.py +3 -3
  8. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/annotations/leaders.py +74 -16
  9. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_adr0018_view_selection.py +20 -4
  10. draftwright-0.4.13/tests/test_build_profile_harness.py +194 -0
  11. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_e2e_standards.py +8 -3
  12. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_import_boundaries.py +3 -0
  13. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1058_wheel_profile.py +4 -1
  14. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1143_hole_completeness.py +61 -33
  15. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1144_transactional_hole_table.py +15 -8
  16. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1166_cross_pass_feature_leaders.py +83 -11
  17. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1176_quality_fidelity.py +5 -1
  18. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1187_unroutable_leaders.py +0 -1
  19. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1204_multiscale_view_issues.py +4 -3
  20. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1215_no_approved_tolerance_is_dropped.py +65 -54
  21. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1216_callout_reservation_measures_ink.py +15 -5
  22. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1276_turned_leader_targets.py +11 -4
  23. draftwright-0.4.13/tests/test_issue_1308_machined_leader_analytics.py +253 -0
  24. draftwright-0.4.13/tests/test_issue_1312_engine_costs.py +25 -0
  25. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_740_leader_assignment.py +45 -36
  26. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_798_silhouette_lint.py +1 -1
  27. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_885_prismatic_coverage.py +4 -1
  28. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_917_open_channel.py +5 -2
  29. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_layout_property.py +4 -4
  30. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_make_drawing.py +14 -20
  31. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_sheet_emit.py +65 -33
  32. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_slanted_blind_step.py +12 -5
  33. {draftwright-0.4.12 → draftwright-0.4.13}/.gitignore +0 -0
  34. {draftwright-0.4.12 → draftwright-0.4.13}/CHANGELOG.md +0 -0
  35. {draftwright-0.4.12 → draftwright-0.4.13}/LICENSE +0 -0
  36. {draftwright-0.4.12 → draftwright-0.4.13}/README.md +0 -0
  37. {draftwright-0.4.12 → draftwright-0.4.13}/docs/adr/README.md +0 -0
  38. {draftwright-0.4.12 → draftwright-0.4.13}/docs/reference/recogniser-capabilities.md +0 -0
  39. {draftwright-0.4.12 → draftwright-0.4.13}/docs/reference/sheet.md +0 -0
  40. {draftwright-0.4.12 → draftwright-0.4.13}/docs/research/1062-repeating-radial-profile-evidence.md +0 -0
  41. {draftwright-0.4.12 → draftwright-0.4.13}/skills/SKILL.md +0 -0
  42. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/__init__.py +0 -0
  43. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/_core.py +0 -0
  44. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/_pmi_part21.py +0 -0
  45. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/_warnings.py +0 -0
  46. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/analysis.py +0 -0
  47. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/annotate.py +0 -0
  48. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/annotations/__init__.py +0 -0
  49. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/annotations/balloons.py +0 -0
  50. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/annotations/gears.py +0 -0
  51. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/annotations/orchestrator.py +0 -0
  52. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/annotations/sections.py +0 -0
  53. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/audit.py +0 -0
  54. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/builder.py +0 -0
  55. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/cli.py +0 -0
  56. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/compose.py +0 -0
  57. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/drawing.py +0 -0
  58. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/evaluation/__init__.py +0 -0
  59. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/evaluation/step_analysis.py +0 -0
  60. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/export.py +0 -0
  61. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/fits.py +0 -0
  62. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/fonts/IBMPlexMono-Regular.ttf +0 -0
  63. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/fonts/IBMPlexSansCondensed-Regular.ttf +0 -0
  64. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/fonts/LICENSE-IBMPlexMono-OFL.txt +0 -0
  65. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/fonts/LICENSE-IBMPlexSansCondensed-OFL.txt +0 -0
  66. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/fonts/__init__.py +0 -0
  67. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/intents.py +0 -0
  68. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/layout.py +0 -0
  69. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/__init__.py +0 -0
  70. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/channel_coverage.py +0 -0
  71. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/coverage.py +0 -0
  72. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/evidence.py +0 -0
  73. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/flat_coverage.py +0 -0
  74. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/gear_coverage.py +0 -0
  75. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/hole_coverage.py +0 -0
  76. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/issues.py +0 -0
  77. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/pmi_coverage.py +0 -0
  78. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/polygonal_stock_coverage.py +0 -0
  79. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/profiled_bore_coverage.py +0 -0
  80. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/quality.py +0 -0
  81. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/slot_coverage.py +0 -0
  82. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/structural.py +0 -0
  83. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/linting/suggest.py +0 -0
  84. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/make_drawing.py +0 -0
  85. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/model/__init__.py +0 -0
  86. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/model/callout.py +0 -0
  87. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/model/compiled.py +0 -0
  88. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/model/declare.py +0 -0
  89. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/model/detect.py +0 -0
  90. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/model/ir.py +0 -0
  91. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/model/planner.py +0 -0
  92. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/model/pmi_lowering.py +0 -0
  93. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/pmi.py +0 -0
  94. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/projection.py +0 -0
  95. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/py.typed +0 -0
  96. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/recogniser_contract.py +0 -0
  97. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/recognition/__init__.py +0 -0
  98. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/recognition_cache.py +0 -0
  99. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/registry.py +0 -0
  100. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/repair.py +0 -0
  101. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/score.py +0 -0
  102. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/sheet.py +0 -0
  103. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/sheet_emit.py +0 -0
  104. {draftwright-0.4.12 → draftwright-0.4.13}/src/draftwright/view_plan.py +0 -0
  105. {draftwright-0.4.12 → draftwright-0.4.13}/tests/_kernel.py +0 -0
  106. {draftwright-0.4.12 → draftwright-0.4.13}/tests/_layout_sig.py +0 -0
  107. {draftwright-0.4.12 → draftwright-0.4.13}/tests/conftest.py +0 -0
  108. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/ap242_single_cylinder_diameter.step +0 -0
  109. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/evaluation/README.md +0 -0
  110. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/evaluation/ambiguous-open-semicircle.step +0 -0
  111. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/evaluation/blind-hole.step +0 -0
  112. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/evaluation/corpus-v1.json +0 -0
  113. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/evaluation/plain-block.step +0 -0
  114. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/evaluation/topology-a.step +0 -0
  115. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/evaluation/topology-b.step +0 -0
  116. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/grm03_thumbwheel_drive_screw.step +0 -0
  117. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/grm04_drive_plate.step +0 -0
  118. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/if_step_flat_across_cylinder.step +0 -0
  119. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/issue_1058_wheel_rh.step +0 -0
  120. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/issue_909_basic_part_design_017_body.step +0 -0
  121. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/issue_915_case_study_2.step +0 -0
  122. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/nist_ctc_01_asme1_ap203.stp +0 -0
  123. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/nist_ctc_01_asme1_ap242.stp +0 -0
  124. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/nist_ctc_02_asme1_ap203.stp +0 -0
  125. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/nist_ctc_02_asme1_ap242.stp +0 -0
  126. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/nist_ctc_03_asme1_ap203.stp +0 -0
  127. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/nist_ctc_03_asme1_ap242.stp +0 -0
  128. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/nist_ctc_04_asme1_ap203.stp +0 -0
  129. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/nist_ctc_04_asme1_ap242.stp +0 -0
  130. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/nist_ctc_05_asme1_ap203.stp +0 -0
  131. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/nist_ctc_05_asme1_ap242.stp +0 -0
  132. {draftwright-0.4.12 → draftwright-0.4.13}/tests/fixtures/tuner_jig_blind_obround_pockets.step +0 -0
  133. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/bracket_section.json +0 -0
  134. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/centered_rebate.json +0 -0
  135. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/chamfered.json +0 -0
  136. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/filleted.json +0 -0
  137. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/flange_dense.json +0 -0
  138. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/grid_plate.json +0 -0
  139. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/grooved_shaft.json +0 -0
  140. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/hex_bar.json +0 -0
  141. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/holed_slot.json +0 -0
  142. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/pocketed.json +0 -0
  143. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/prismatic_ladder.json +0 -0
  144. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/scattered_plate.json +0 -0
  145. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/side_drilled.json +0 -0
  146. {draftwright-0.4.12 → draftwright-0.4.13}/tests/refactor_golden/turned_stepped.json +0 -0
  147. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_add_dimension.py +0 -0
  148. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_adr0018_arrangement_gate.py +0 -0
  149. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_adr0018_view_routing.py +0 -0
  150. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_agents_guide.py +0 -0
  151. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_api_docs.py +0 -0
  152. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_architecture_docs.py +0 -0
  153. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_audit_differential.py +0 -0
  154. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_balloon_ring_standoff.py +0 -0
  155. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_carve_free_position_callers.py +0 -0
  156. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_compiled_plan_boundary.py +0 -0
  157. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_counting_calls.py +0 -0
  158. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_declare.py +0 -0
  159. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_declared_recognition_gate.py +0 -0
  160. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_dense_sheet_canary.py +0 -0
  161. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_deprecation_dates.py +0 -0
  162. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_detect_once.py +0 -0
  163. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_detect_registry.py +0 -0
  164. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_dimension_role_vocabulary.py +0 -0
  165. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_drawing_encapsulation.py +0 -0
  166. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_e2e_slice.py +0 -0
  167. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_export_dxf_curves.py +0 -0
  168. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_export_dxf_zoom.py +0 -0
  169. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_external_recognition_boundary.py +0 -0
  170. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_fillets_adjacency.py +0 -0
  171. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_fits.py +0 -0
  172. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_flat_completeness.py +0 -0
  173. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_flat_stock_identity.py +0 -0
  174. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_flat_stock_opposition.py +0 -0
  175. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_gdt_placement.py +0 -0
  176. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_grid_lattice_convention.py +0 -0
  177. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_iso_nts_caption_placement.py +0 -0
  178. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1000_envelope_reuse.py +0 -0
  179. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1073_cross_body_patterns.py +0 -0
  180. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1082_polygonal_stock.py +0 -0
  181. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1086_declared_gears.py +0 -0
  182. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1116_ap242_hole_tolerance_lowering.py +0 -0
  183. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1130_view_planning_evidence.py +0 -0
  184. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1142_hole_leader_labels.py +0 -0
  185. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1146_scale_completeness.py +0 -0
  186. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1147_legibility_pair_aggregation.py +0 -0
  187. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1153_contradictory_dimensions.py +0 -0
  188. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1154_one_owner_per_measurement.py +0 -0
  189. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1155_grm04_sheet_use.py +0 -0
  190. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1177_angular_dimensions.py +0 -0
  191. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1188_per_view_assignment.py +0 -0
  192. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1190_section_decision.py +0 -0
  193. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1196_deterministic_view_names.py +0 -0
  194. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1202_observed_drawing_consumer.py +0 -0
  195. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1209_linear_pmi_witnesses.py +0 -0
  196. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1215_envelope_tolerance.py +0 -0
  197. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1216_pairwise_across_scale_groups.py +0 -0
  198. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1217_claimed_representations.py +0 -0
  199. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1217_the_facility_is_shared.py +0 -0
  200. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1219_location_claims_its_own_axis.py +0 -0
  201. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1229_ledger_member_keying.py +0 -0
  202. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1240_iso_above_strip_visibility.py +0 -0
  203. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1254_turned_chamfers.py +0 -0
  204. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1260_view_constraints.py +0 -0
  205. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1281_turned_fillets.py +0 -0
  206. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1296_cylindrical_diameter_pmi.py +0 -0
  207. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1298_manufacturing_requirements.py +0 -0
  208. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_1299_page_escalation.py +0 -0
  209. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_367_leader_ink.py +0 -0
  210. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_443_grm03_axial_coverage.py +0 -0
  211. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_676_polygonal_boss.py +0 -0
  212. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_676_polygonal_boss_declare.py +0 -0
  213. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_798_floor_cardinality.py +0 -0
  214. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_798_material_field.py +0 -0
  215. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_909_sloped_profile.py +0 -0
  216. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_915_dense_case.py +0 -0
  217. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_916_pocket_leader.py +0 -0
  218. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_924_zero_length_shoulders.py +0 -0
  219. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_955_height_contingency.py +0 -0
  220. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_issue_958_cross_solid_recognition.py +0 -0
  221. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_label_provenance.py +0 -0
  222. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_layout.py +0 -0
  223. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_layout_cleanliness.py +0 -0
  224. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_layout_hypothesis.py +0 -0
  225. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_leader_footprint.py +0 -0
  226. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_lint_box_cache.py +0 -0
  227. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_lint_reconciliation.py +0 -0
  228. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_lint_structural.py +0 -0
  229. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_linting.py +0 -0
  230. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_location_vocabulary.py +0 -0
  231. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_note_verb.py +0 -0
  232. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_object_aspects.py +0 -0
  233. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_occupancy_boxes.py +0 -0
  234. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_parameter_id.py +0 -0
  235. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_part_model.py +0 -0
  236. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_pitch_dim_footprint.py +0 -0
  237. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_pmi.py +0 -0
  238. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_pmi_datum_lowering.py +0 -0
  239. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_pmi_gtol_lowering.py +0 -0
  240. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_pmi_part21.py +0 -0
  241. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_pocket_pattern.py +0 -0
  242. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_pocket_pattern_recognition.py +0 -0
  243. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_principal_profile_classifier.py +0 -0
  244. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_private_test_attr_reads.py +0 -0
  245. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_private_test_imports.py +0 -0
  246. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_quality_components.py +0 -0
  247. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_recogniser_adoption.py +0 -0
  248. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_recogniser_capabilities.py +0 -0
  249. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_recogniser_contract.py +0 -0
  250. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_recognition.py +0 -0
  251. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_recognition_manifest.py +0 -0
  252. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_recognition_result.py +0 -0
  253. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_refactor_golden.py +0 -0
  254. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_registry.py +0 -0
  255. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_render_seam.py +0 -0
  256. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_repack_geometry_seam.py +0 -0
  257. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_score.py +0 -0
  258. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_script_detail_parity.py +0 -0
  259. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_shared_box_memo.py +0 -0
  260. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_sheet_gdt.py +0 -0
  261. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_sheet_identity_invariant.py +0 -0
  262. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_sheet_notes.py +0 -0
  263. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_sheet_of.py +0 -0
  264. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_sheet_section.py +0 -0
  265. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_sheet_tables.py +0 -0
  266. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_slot_completeness.py +0 -0
  267. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_slot_pattern.py +0 -0
  268. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_slot_pattern_recognition.py +0 -0
  269. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_soft_deprecation.py +0 -0
  270. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_solve_trace.py +0 -0
  271. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_step_analysis_evaluation.py +0 -0
  272. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_strip_layout.py +0 -0
  273. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_suppression_ledger.py +0 -0
  274. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_suppression_marks.py +0 -0
  275. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_tolerances.py +0 -0
  276. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_turned_steps.py +0 -0
  277. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_view_plan.py +0 -0
  278. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_witness_label_reconciliation.py +0 -0
  279. {draftwright-0.4.12 → draftwright-0.4.13}/tests/test_workflows.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: draftwright
3
- Version: 0.4.12
3
+ Version: 0.4.13
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "draftwright"
7
- version = "0.4.12"
7
+ version = "0.4.13"
8
8
  description = "Automated technical-drawing generation for build123d"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -0,0 +1,186 @@
1
+ """Pytest plugin and runner support for reproducible build-cost profiles (#1307)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import re
7
+ import sys
8
+ from collections import defaultdict
9
+ from collections.abc import Callable
10
+ from dataclasses import dataclass, field
11
+ from functools import wraps
12
+ from pathlib import Path
13
+ from time import perf_counter
14
+ from typing import Any
15
+
16
+ _MIN_REPORT_SECONDS = 0.005
17
+ _STATE: _ProfileState | None = None
18
+ _CURRENT_NODEID = "<collection>"
19
+
20
+
21
+ @dataclass
22
+ class _ProfileState:
23
+ output_dir: Path
24
+ worker_id: str
25
+ collected: int | None = None
26
+ calls: dict[tuple[str, str], list[float]] = field(
27
+ default_factory=lambda: defaultdict(lambda: [0, 0.0])
28
+ )
29
+ phases: list[dict[str, Any]] = field(default_factory=list)
30
+
31
+ def record_call(self, seam: str, seconds: float) -> None:
32
+ aggregate = self.calls[(_CURRENT_NODEID, seam)]
33
+ aggregate[0] += 1
34
+ aggregate[1] += seconds
35
+
36
+ def write(self, exitstatus: int) -> Path:
37
+ self.output_dir.mkdir(parents=True, exist_ok=True)
38
+ safe_worker = re.sub(r"[^A-Za-z0-9_.-]", "_", self.worker_id)
39
+ path = self.output_dir / f"profile-{safe_worker}.json"
40
+ payload = {
41
+ "worker_id": self.worker_id,
42
+ "collected": self.collected,
43
+ "exitstatus": exitstatus,
44
+ "calls": [
45
+ {
46
+ "nodeid": nodeid,
47
+ "seam": seam,
48
+ "count": int(values[0]),
49
+ "seconds": values[1],
50
+ }
51
+ for (nodeid, seam), values in sorted(self.calls.items())
52
+ ],
53
+ "phases": self.phases,
54
+ }
55
+ path.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
56
+ return path
57
+
58
+
59
+ def _timed(seam: str, function: Callable[..., Any]) -> Callable[..., Any]:
60
+ @wraps(function)
61
+ def wrapper(*args, **kwargs):
62
+ started = perf_counter()
63
+ try:
64
+ return function(*args, **kwargs)
65
+ finally:
66
+ assert _STATE is not None
67
+ _STATE.record_call(seam, perf_counter() - started)
68
+
69
+ return wrapper
70
+
71
+
72
+ def pytest_addoption(parser) -> None:
73
+ group = parser.getgroup("draftwright-build-profile")
74
+ group.addoption(
75
+ "--build-profile-dir",
76
+ help="write one Draftwright build profile JSON file per pytest-xdist worker",
77
+ )
78
+
79
+
80
+ def pytest_configure(config) -> None:
81
+ global _STATE
82
+ output = config.getoption("--build-profile-dir")
83
+ if not output:
84
+ return
85
+
86
+ worker_input = getattr(config, "workerinput", None)
87
+ # Under xdist the controller executes no tests; worker processes write the useful files.
88
+ if worker_input is None and getattr(config.option, "numprocesses", None):
89
+ return
90
+
91
+ worker_id = worker_input.get("workerid", "worker") if worker_input else "main"
92
+ _STATE = _ProfileState(Path(output).resolve(), worker_id)
93
+
94
+ import draftwright.builder as builder
95
+ import draftwright.sheet as sheet
96
+
97
+ draftwright = sys.modules["draftwright"]
98
+ builder_public = _timed("builder.build_drawing", builder.build_drawing)
99
+ builder.build_drawing = builder_public
100
+ # The public lazy package attribute and Sheet's import-time binding otherwise bypass a
101
+ # patch installed only on builder.py. That omission made the first #1307 census a lower
102
+ # bound, so all three bindings are explicit here.
103
+ setattr(draftwright, "build_drawing", builder_public)
104
+ sheet.build_drawing = _timed("sheet.build_drawing", sheet.build_drawing)
105
+ builder._build_drawing_once = _timed(
106
+ "builder._build_drawing_once", builder._build_drawing_once
107
+ )
108
+
109
+
110
+ def pytest_collection_finish(session) -> None:
111
+ if _STATE is not None:
112
+ _STATE.collected = len(session.items)
113
+
114
+
115
+ def pytest_runtest_logstart(nodeid, location) -> None:
116
+ del location
117
+ global _CURRENT_NODEID
118
+ _CURRENT_NODEID = nodeid
119
+
120
+
121
+ def pytest_runtest_logfinish(nodeid, location) -> None:
122
+ del nodeid, location
123
+ global _CURRENT_NODEID
124
+ _CURRENT_NODEID = "<between-tests>"
125
+
126
+
127
+ def pytest_runtest_logreport(report) -> None:
128
+ if _STATE is not None and report.duration >= _MIN_REPORT_SECONDS:
129
+ _STATE.phases.append(
130
+ {
131
+ "nodeid": report.nodeid,
132
+ "phase": report.when,
133
+ "seconds": report.duration,
134
+ "outcome": report.outcome,
135
+ }
136
+ )
137
+
138
+
139
+ def pytest_sessionfinish(session, exitstatus) -> None:
140
+ del session
141
+ if _STATE is not None:
142
+ _STATE.write(int(exitstatus))
143
+
144
+
145
+ def build_pytest_command(output_dir: Path, pytest_args: list[str]) -> list[str]:
146
+ """Return argv without joining *pytest_args* into a shell-expanded module string."""
147
+ return [
148
+ "uv",
149
+ "run",
150
+ "pytest",
151
+ "-p",
152
+ "draftwright._build_profile",
153
+ f"--build-profile-dir={output_dir}",
154
+ *pytest_args,
155
+ ]
156
+
157
+
158
+ def summarise_profiles(output_dir: Path, expected_collected: int) -> dict[str, Any]:
159
+ paths = sorted(output_dir.glob("profile-*.json"))
160
+ if not paths:
161
+ raise ValueError(f"no worker profiles were written to {output_dir}")
162
+
163
+ by_seam: dict[str, list[float]] = defaultdict(lambda: [0, 0.0])
164
+ workers = []
165
+ for path in paths:
166
+ payload = json.loads(path.read_text(encoding="utf-8"))
167
+ collected = payload.get("collected")
168
+ if collected != expected_collected:
169
+ raise ValueError(
170
+ f"{path.name} collected {collected!r}, expected {expected_collected}; "
171
+ "refusing to report a successful empty or partial profile"
172
+ )
173
+ workers.append(payload["worker_id"])
174
+ for call in payload["calls"]:
175
+ aggregate = by_seam[call["seam"]]
176
+ aggregate[0] += call["count"]
177
+ aggregate[1] += call["seconds"]
178
+
179
+ return {
180
+ "expected_collected": expected_collected,
181
+ "workers": workers,
182
+ "seams": {
183
+ seam: {"count": int(values[0]), "seconds": values[1]}
184
+ for seam, values in sorted(by_seam.items())
185
+ },
186
+ }
@@ -456,6 +456,15 @@ def _convex_polygons_overlap(left, right) -> bool:
456
456
 
457
457
  if len(left) < 3 or len(right) < 3:
458
458
  return False
459
+ left_x, left_y = zip(*left, strict=True)
460
+ right_x, right_y = zip(*right, strict=True)
461
+ if (
462
+ max(left_x) <= min(right_x)
463
+ or max(right_x) <= min(left_x)
464
+ or max(left_y) <= min(right_y)
465
+ or max(right_y) <= min(left_y)
466
+ ):
467
+ return False
459
468
  axes: list[tuple[float, float]] = []
460
469
  for points in (left, right):
461
470
  axes.extend(
@@ -830,6 +830,37 @@ def leader_callout_geometry(tip, elbow, draft, *, text_side="auto", callout_box=
830
830
  return label_box, segments
831
831
 
832
832
 
833
+ def analytical_leader_lands_clear(
834
+ candidate,
835
+ obstacles,
836
+ silhouette,
837
+ page,
838
+ *,
839
+ label,
840
+ geom_clear=False,
841
+ ) -> bool:
842
+ """Apply the producer's label/full-ink clearance floor to an unbuilt leader."""
843
+ label_box = candidate.label_box
844
+ if not label or label_box is None:
845
+ return False
846
+ check_box = label_box
847
+ if geom_clear:
848
+ xs = [label_box[0], label_box[2]]
849
+ ys = [label_box[1], label_box[3]]
850
+ for polygon in candidate.ink_polygons:
851
+ xs.extend(point[0] for point in polygon)
852
+ ys.extend(point[1] for point in polygon)
853
+ check_box = (min(xs), min(ys), max(xs), max(ys))
854
+ return not (
855
+ _box_hits(check_box, obstacles)
856
+ or _box_hits(label_box, [silhouette])
857
+ or label_box[0] < page[0]
858
+ or label_box[1] < page[1]
859
+ or label_box[2] > page[2]
860
+ or label_box[3] > page[3]
861
+ )
862
+
863
+
833
864
  def leader_footprint(tip, elbow, draft, *, text_side="auto", callout_box=None):
834
865
  """Analytical page-mm AABB ``(x0, y0, x1, y1)`` of the :class:`Leader` that
835
866
  ``Leader(tip, elbow, label="", draft, text_side=…, callout=…)`` would build —