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 diff --git a/fatamorgana/basic.py b/fatamorgana/basic.py index fee40dc..70da126 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) @@ -1211,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' @@ -1595,7 +1601,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 +1624,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)) diff --git a/fatamorgana/records.py b/fatamorgana/records.py index 88863a7..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 @@ -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. @@ -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: @@ -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. """ @@ -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 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"]