From 12debf0b02beb985e6223c15d0980e22ac55f100 Mon Sep 17 00:00:00 2001 From: jan Date: Tue, 30 Dec 2025 02:54:45 -0800 Subject: [PATCH 1/8] update tags --- pyproject.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c91c0d1..9c149ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,15 +34,14 @@ keywords = [ ] classifiers = [ "Programming Language :: Python :: 3", - "Development Status :: 3 - Alpha", - "Environment :: Other Environment", + "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: Manufacturing", "Intended Audience :: Science/Research", "License :: OSI Approved :: GNU Affero General Public License v3", - "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", + "Topic :: File Formats", ] requires-python = ">=3.11" dynamic = ["version"] From 0503ceb7255a1b4b596acf54932ca9dfe5b191e7 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sun, 15 Feb 2026 15:11:25 -0800 Subject: [PATCH 2/8] [Path] fix Path writing the wrong record type --- fatamorgana/records.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fatamorgana/records.py b/fatamorgana/records.py index 88863a7..c7bacc1 100644 --- a/fatamorgana/records.py +++ b/fatamorgana/records.py @@ -1960,7 +1960,7 @@ class Path(Record, GeometryMixin): dd = self.datatype is not None ll = self.layer is not None - size = write_uint(stream, 21) + size = write_uint(stream, 22) size += write_bool_byte(stream, (ee, ww, pp, xx, yy, rr, dd, ll)) if ll: size += write_uint(stream, self.layer) # type: ignore From a82c555cda52d095096029a1376dff15a01bfd73 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sun, 15 Feb 2026 15:45:20 -0800 Subject: [PATCH 3/8] [Polygon] fix overeager warning --- fatamorgana/records.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fatamorgana/records.py b/fatamorgana/records.py index c7bacc1..e298ca9 100644 --- a/fatamorgana/records.py +++ b/fatamorgana/records.py @@ -1744,7 +1744,7 @@ class Polygon(Record, GeometryMixin): self.point_list = point_list self.properties = [] if properties is None else properties - if point_list is not None and len(point_list) < 3: + if point_list is not None and len(point_list) < 2: warn('Polygon with < 3 points', stacklevel=2) def get_point_list(self) -> point_list_t: From 7f7431f018f3e16440f77f6d7c5f5dc4dcb66526 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sun, 15 Feb 2026 15:46:45 -0800 Subject: [PATCH 4/8] [Polygon / Path] clarify docs --- fatamorgana/records.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fatamorgana/records.py b/fatamorgana/records.py index e298ca9..f4d898c 100644 --- a/fatamorgana/records.py +++ b/fatamorgana/records.py @@ -1717,8 +1717,8 @@ class Polygon(Record, GeometryMixin): repetition: repetition_t | None point_list: point_list_t | None """ - List of offsets from the initial vertex (x, y) to the remaining - vertices, `[[dx0, dy0], [dx1, dy1], ...]`. + List of offsets between consecutive vertices, starting from the initial + vertex (x, y): `[[dx0, dy0], [dx1, dy1], ...]`. The list is an implicitly closed path, vertices are [int, int]. The initial vertex is located at (x, y) and is not represented in `point_list`. `None` means reuse modal. @@ -1827,8 +1827,8 @@ class Path(Record, GeometryMixin): repetition: repetition_t | None = None point_list: point_list_t | None = None """ - List of offsets from the initial vertex (x, y) to the remaining vertices, - `[[dx0, dy0], [dx1, dy1], ...]`. + List of offsets between consecutive vertices, starting from the initial + vertex (x, y): `[[dx0, dy0], [dx1, dy1], ...]`. The initial vertex is located at (x, y) and is not represented in `point_list`. Offsets are [int, int]; `None` means reuse modal. """ From 5b42cdf609cc78e3dafd27de6575481404daef39 Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sun, 15 Feb 2026 16:25:21 -0800 Subject: [PATCH 5/8] [basic] cast to the expected types before conversion --- fatamorgana/basic.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fatamorgana/basic.py b/fatamorgana/basic.py index fee40dc..3c35d5e 100644 --- a/fatamorgana/basic.py +++ b/fatamorgana/basic.py @@ -2,7 +2,7 @@ This module contains all datatypes and parsing/writing functions for all abstractions below the 'record' or 'block' level. """ -from typing import Any, IO, Union +from typing import Any, IO, Union, TYPE_CHECKING from collections.abc import Sequence from fractions import Fraction from enum import Enum @@ -250,6 +250,7 @@ def write_uint(stream: IO[bytes], n: int) -> int: Raises: SignedError: if `n` is negative. """ + n = int(n) if n < 0: raise SignedError(f'uint must be positive: {n}') @@ -295,6 +296,7 @@ def encode_sint(sint: int) -> int: Returns: Unsigned integer encoding for the input. """ + sint = int(sint) return (abs(sint) << 1) | (sint < 0) @@ -1595,7 +1597,7 @@ def read_point_list( def write_point_list( stream: IO[bytes], - points: list[Sequence[int]], + points: 'list[Sequence[int]] | NDArray', fast: bool = False, implicit_closed: bool = True ) -> int: @@ -1618,6 +1620,8 @@ def write_point_list( Number of bytes written. """ # If we're in a hurry, just write the points as arbitrary Deltas + if _USE_NUMPY: + points = numpy.asarray(points, dtype=int) if fast: size = write_uint(stream, 4) size += write_uint(stream, len(points)) From c869da03bf5a3d322fa1f5aee3ef2dcfadd1df0a Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Sun, 15 Feb 2026 19:21:28 -0800 Subject: [PATCH 6/8] [GridRepetition] convert to expected types --- fatamorgana/basic.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fatamorgana/basic.py b/fatamorgana/basic.py index 3c35d5e..70da126 100644 --- a/fatamorgana/basic.py +++ b/fatamorgana/basic.py @@ -1213,6 +1213,10 @@ class GridRepetition: InvalidDataError: if `b_count` and `b_vector` inputs conflict with each other or if `a_count < 1`. """ + a_count = int(a_count) + if b_count is not None: + b_count = int(b_count) + if b_vector is None or b_count is None: if b_vector is not None or b_count is not None: raise InvalidDataError('Repetition has only one of' From cceabe46ee92ad9c866e18cf1ba839869c529cde Mon Sep 17 00:00:00 2001 From: jan Date: Mon, 16 Feb 2026 21:50:29 -0800 Subject: [PATCH 7/8] README update: drop github mirror --- README.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/README.md b/README.md index 350a0d0..d4df9bb 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ **Homepage:** https://mpxd.net/code/jan/fatamorgana * [PyPI](https://pypi.org/project/fatamorgana) -* [Github mirror](https://github.com/anewusername/fatamorgana) **Capabilities:** * This package is a work-in-progress and is largely untested -- it works for @@ -28,12 +27,7 @@ Install with pip from PyPi (preferred): ```bash -pip3 install fatamorgana -``` - -Install directly from git repository: -```bash -pip3 install git+https://mpxd.net/code/jan/fatamorgana.git@release +pip install fatamorgana ``` ## Documentation @@ -44,7 +38,6 @@ To read the inline help, import fatamorgana help(fatamorgana.OasisLayout) ``` -The documentation is currently very sparse and I expect to improve it whenever possible! ## Examples From 93e4075d8902863e2c40380f833e3d9904023338 Mon Sep 17 00:00:00 2001 From: jan Date: Tue, 17 Feb 2026 00:44:56 -0800 Subject: [PATCH 8/8] [Placement] fix writing placement --- fatamorgana/records.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fatamorgana/records.py b/fatamorgana/records.py index f4d898c..a137b42 100644 --- a/fatamorgana/records.py +++ b/fatamorgana/records.py @@ -1434,7 +1434,7 @@ class Placement(Record): size += self.name.write(stream) # type: ignore if mm: size += write_real(stream, self.magnification) # type: ignore - if aa: + if aq: size += write_real(stream, self.angle) # type: ignore if xx: size += write_sint(stream, self.x) # type: ignore