[arrow] make sure loaded values are mutable

This commit is contained in:
Jan Petykiewicz 2026-09-14 21:51:50 -07:00
commit 70c4cb3589
4 changed files with 137 additions and 18 deletions

View file

@ -23,6 +23,67 @@ if not gdsii_arrow.is_available():
pytest.skip('klamath_rs_ext shared library is not available', allow_module_level=True)
def test_arrow_materialized_coordinates_are_writable_floats(tmp_path: Path) -> None:
original = _make_arrow_test_library()
for annotations, layer in [(None, (30, 0)), ({'1': ['prop']}, (31, 0))]:
for xx in (0, 10):
original['leaf'].polygon(layer, [(xx, 0), (xx + 4, 0), (xx, 3)], annotations=annotations)
filename = tmp_path / 'mutable.gds'
gdsii.writefile(original, filename, meters_per_unit=1e-9)
lib, _ = gdsii_arrow.readfile(filename)
arrays = []
types = set()
for pattern in lib.values():
for shapes in pattern.shapes.values():
for shape in shapes:
types.add(type(shape))
if isinstance(shape, RectCollection):
coordinates = shape.rects
elif isinstance(shape, PolyCollection):
coordinates = shape.vertex_lists
else:
coordinates = shape.vertices
arrays.append(coordinates)
before = coordinates.copy()
shape.translate((0.25, 0.5)).scale_by(1.5)
shift = (0.25, 0.5, 0.25, 0.5) if isinstance(shape, RectCollection) else (0.25, 0.5)
numpy.testing.assert_allclose(coordinates, (before + shift) * 1.5)
if isinstance(shape, MPath) and shape.cap_extensions is not None:
arrays.append(shape.cap_extensions)
for labels in pattern.labels.values():
arrays.extend(label.offset for label in labels)
for refs in pattern.refs.values():
for ref in refs:
arrays.append(ref.offset)
ref.translate((0.25, 0.5))
if ref.repetition is not None:
arrays.extend((ref.repetition.a_vector, ref.repetition.b_vector))
ref.repetition.scale_by(1.5)
assert {Polygon, PolyCollection, RectCollection, MPath} <= types
for array in arrays:
assert array.dtype == numpy.float64
assert array.flags.writeable
def test_arrow_path_extensions_are_quantized_for_oasis(tmp_path: Path) -> None:
pytest.importorskip('fatamorgana')
from ..file import oasis # noqa: PLC0415
source = Library({'top': Pattern().path((1, 0), [(0, 0), (20, 0)], width=4,
cap=MPath.Cap.SquareCustom, cap_extensions=(1, 5))})
gds_path = tmp_path / 'path.gds'
gdsii.writefile(source, gds_path, meters_per_unit=1e-9)
loaded, _ = gdsii_arrow.readfile(gds_path)
path = loaded['top'].shapes[(1, 0)][0]
path.scale_by(1.25)
exported = oasis.build(loaded, units_per_micron=1000).cells[0].geometry[0]
assert exported.extension_start[1] == 1
assert exported.extension_end[1] == 6
assert isinstance(exported.extension_start[1], int | numpy.integer)
assert isinstance(exported.extension_end[1], int | numpy.integer)
numpy.testing.assert_allclose(path.cap_extensions, (1.25, 6.25))
def _annotations_key(annotations: dict[str, list[object]] | None) -> tuple[tuple[str, tuple[object, ...]], ...] | None:
if not annotations:
return None