"""Tests for DSN shape parsing.""" from __future__ import annotations from freeroute.dsn.sexp import parse from freeroute.dsn.shapes import ( Circle, Path, Polygon, Rectangle, read_area, read_shape, ) def shape_of(text: str): return read_shape(parse(text)) def test_rectangle(): rect = shape_of("(rect Top -400 -100 400 100)") assert isinstance(rect, Rectangle) assert rect.layer == "Top" assert rect.coords == [-400.0, -100.0, 400.0, 100.0] def test_circle_with_center(): circ = shape_of("(circle Bottom 600 10 20)") assert isinstance(circ, Circle) assert circ.diameter == 600.0 assert (circ.center_x, circ.center_y) == (10.0, 20.0) def test_circle_without_center_defaults_to_origin(): circ = shape_of("(circle Top 600)") assert isinstance(circ, Circle) assert (circ.center_x, circ.center_y) == (0.0, 0.0) def test_polygon(): poly = shape_of("(polygon signal 0 0 0 100 0 100 100 0 100)") assert isinstance(poly, Polygon) assert poly.aperture_width == 0.0 assert poly.coords == [0.0, 0.0, 100.0, 0.0, 100.0, 100.0, 0.0, 100.0] def test_path_is_width_plus_points(): path = shape_of("(path pcb 0 0 0 150000 0 150000 -90000)") assert isinstance(path, Path) assert path.width == 0.0 assert path.coords == [0.0, 0.0, 150000.0, 0.0, 150000.0, -90000.0] def test_unknown_shape_returns_none(): assert shape_of("(mystery Top 1 2)") is None def test_area_border_name_and_clearance(): area = read_area(parse('(keepout "kz" (rect Top 0 0 10 10) (clearance_class special))')) assert area is not None assert area.name == "kz" assert isinstance(area.border, Rectangle) assert area.clearance_class == "special" assert area.holes == [] def test_area_with_window_hole(): area = read_area( parse("(keepout (polygon Top 0 0 0 0 100 100 100 100 0) (window (rect Top 10 10 20 20)))") ) assert area is not None assert isinstance(area.border, Polygon) assert len(area.holes) == 1 assert isinstance(area.holes[0], Rectangle)