Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/draftwright/annotations/_gdt.py
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,7 @@ def render_gdt(
# Prefer the one nearest this strip's anchor; the farther datum retains
# the ordinary side/sheet fallback if its first corridor becomes full.
datum_stem_rank = 0
if item.kind == "datum_ref":
if item.kind == "datum_ref" and strip is not None:
perp, stack = (px, py) if horizontal else (py, px)
distance = abs(stack - strip.anchor)
for other in items:
Expand Down
22 changes: 9 additions & 13 deletions tests/test_adr0018_view_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -597,26 +597,22 @@ def _plate():
return part

@pytest.mark.slow
def test_the_smaller_view_set_reaches_a2_and_what_it_costs(self):
def test_automatic_view_set_matches_manual_reduction_on_a2(self):
part = self._plate()
full = build_drawing(part)
reduced = build_drawing(part, _views=("front", "side"))

# The ADR's failure: the fixed four-view topology drives A1 at 1:1.
assert (full.page_w, full.page_h) == (841.0, 594.0)
# Automatic view selection now removes the redundant plan view.
assert (full.page_w, full.page_h) == (594.0, 420.0)
assert full.scale == 1.0
assert set(full.views) == {"front", "side", "iso"}

# Dropping the redundant plan reaches the ADR's target sheet at the same scale.
assert (reduced.page_w, reduced.page_h) == (594.0, 420.0)
# The explicit two-principal view set reaches the same finished drawing.
assert (reduced.page_w, reduced.page_h) == (full.page_w, full.page_h)
assert reduced.scale == full.scale

# The omitted plan centerline and ISO caption are furniture, not requirements.
# Independent lint confirms that the smaller view set keeps supported meaning.
assert len(reduced.annotations()) < len(full.annotations())
assert set(full.annotations()) - set(reduced.annotations()) == {
"centerline_plan",
"note_iso_nts",
}
assert set(reduced.views) == set(full.views)
assert set(reduced.annotations()) == set(full.annotations())
assert _lint(full) == set()
assert _lint(reduced) == set()

@pytest.mark.slow
Expand Down
36 changes: 36 additions & 0 deletions tests/test_gdt_placement.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,42 @@ def forbidden_sheet_route(*_args, **_kwargs):
assert [attempt["side"] for attempt in events[0]["items"][0]["attempts"]] == ["left"]


def test_imported_datum_on_absent_side_strip_drops_without_aborting_issue_2182(tmp_path):
datum = DatumRef(
frame=Frame((0.0, -25.0, 0.0), "y"),
letter="A",
view="side",
side="left",
source_id="datum:missing-side-strip",
reference_surface_kind="plane",
)
surviving_frame = ControlFrame(
frame=Frame((0.0, 0.0, 10.0), "z"),
characteristic="flatness",
tolerance="0.05",
view="plan",
side="above",
source_id="geometric_tolerance:survivor",
)
trace_path = tmp_path / "missing-side-strip.json"

dwg = _build(datum, surviving_frame, pmi="annotate", trace=trace_path)

assert "m_gdt0" not in dwg.annotations()
assert "m_gdt1" in dwg.annotations()
assert any(
issue.code == "pmi_dropped" and "m_gdt0" in issue.message for issue in dwg.registry.issues
)
solves = json.loads(trace_path.read_text())["solves"]
assert any(
solve["corridor"] == ["side", "left"]
and solve["strip"] is None
and {item["name"] for item in solve["candidates"]} == {"m_gdt0"}
and solve["outcomes"] == [{"name": "m_gdt0", "outcome": "dropped", "reason": "no_strip"}]
for solve in solves
)


def test_projected_datum_stem_keeps_both_near_and_far_datums_issue_2128():
part = Box(80, 50, 20)
near = DatumRef(frame=Frame((0, 0, -10), "z"), letter="A", view="front", side="below")
Expand Down
13 changes: 5 additions & 8 deletions tests/test_issue_1298_manufacturing_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -1781,13 +1781,9 @@ def test_exact_grm03_renders_complete_source_owned_manufacturing_drawing_once():
assert hashlib.sha256(GRM03.read_bytes()).hexdigest() == GRM03_SHA256
drawing = build_drawing(GRM03, pmi="annotate")

assert (drawing.page_w, drawing.page_h, drawing.scale) == (297.0, 210.0, 2.0)
assert {"front", "side", "detail_a"} <= set(drawing.views)
assert drawing.get_annotation("detail_caption_A").label == (
"DETAIL A — PARTIAL PROFILE — SCALE 10:1"
)
assert drawing.detail_decisions[0]["status"] == "placed"
assert drawing.detail_decisions[0]["fit"]["within_reservation"] is True
assert (drawing.page_w, drawing.page_h, drawing.scale) == (297.0, 210.0, 5.0)
assert {"front", "side"} <= set(drawing.views)
assert drawing.detail_decisions == []
assert drawing.scale_decision["status"] != "invalid"

expected_manufacturing = {
Expand Down Expand Up @@ -1951,8 +1947,9 @@ def test_exact_grm03_renders_complete_source_owned_manufacturing_drawing_once():
if isinstance(feature, ChamferFeature)
] == chamfers
replayed = namespace["sheet"].build()
# The declared replay still composes the optional detail at its own chosen scale.
assert (replayed.page_w, replayed.page_h, replayed.scale) == (297.0, 210.0, 2.0)
assert replayed.detail_decisions[0]["status"] == "placed"
assert replayed.detail_decisions[0]["extent"] == drawing.detail_decisions[0]["extent"]
assert replayed.detail_decisions[0]["fit"]["within_reservation"] is True
replayed_model = replayed.model()
assert sum(isinstance(feature, GeneralTolerance) for feature in replayed_model.features) == 1
Expand Down
Loading