Compare commits
8 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 93e4075d89 | |||
| cceabe46ee | |||
| c869da03bf | |||
| 5b42cdf609 | |||
| 7f7431f018 | |||
| a82c555cda | |||
| 0503ceb725 | |||
| 12debf0b02 |
4 changed files with 20 additions and 20 deletions
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
**Homepage:** https://mpxd.net/code/jan/fatamorgana
|
**Homepage:** https://mpxd.net/code/jan/fatamorgana
|
||||||
* [PyPI](https://pypi.org/project/fatamorgana)
|
* [PyPI](https://pypi.org/project/fatamorgana)
|
||||||
* [Github mirror](https://github.com/anewusername/fatamorgana)
|
|
||||||
|
|
||||||
**Capabilities:**
|
**Capabilities:**
|
||||||
* This package is a work-in-progress and is largely untested -- it works for
|
* This package is a work-in-progress and is largely untested -- it works for
|
||||||
|
|
@ -28,12 +27,7 @@
|
||||||
|
|
||||||
Install with pip from PyPi (preferred):
|
Install with pip from PyPi (preferred):
|
||||||
```bash
|
```bash
|
||||||
pip3 install fatamorgana
|
pip install fatamorgana
|
||||||
```
|
|
||||||
|
|
||||||
Install directly from git repository:
|
|
||||||
```bash
|
|
||||||
pip3 install git+https://mpxd.net/code/jan/fatamorgana.git@release
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
@ -44,7 +38,6 @@ To read the inline help,
|
||||||
import fatamorgana
|
import fatamorgana
|
||||||
help(fatamorgana.OasisLayout)
|
help(fatamorgana.OasisLayout)
|
||||||
```
|
```
|
||||||
The documentation is currently very sparse and I expect to improve it whenever possible!
|
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
This module contains all datatypes and parsing/writing functions for
|
This module contains all datatypes and parsing/writing functions for
|
||||||
all abstractions below the 'record' or 'block' level.
|
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 collections.abc import Sequence
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
@ -250,6 +250,7 @@ def write_uint(stream: IO[bytes], n: int) -> int:
|
||||||
Raises:
|
Raises:
|
||||||
SignedError: if `n` is negative.
|
SignedError: if `n` is negative.
|
||||||
"""
|
"""
|
||||||
|
n = int(n)
|
||||||
if n < 0:
|
if n < 0:
|
||||||
raise SignedError(f'uint must be positive: {n}')
|
raise SignedError(f'uint must be positive: {n}')
|
||||||
|
|
||||||
|
|
@ -295,6 +296,7 @@ def encode_sint(sint: int) -> int:
|
||||||
Returns:
|
Returns:
|
||||||
Unsigned integer encoding for the input.
|
Unsigned integer encoding for the input.
|
||||||
"""
|
"""
|
||||||
|
sint = int(sint)
|
||||||
return (abs(sint) << 1) | (sint < 0)
|
return (abs(sint) << 1) | (sint < 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1211,6 +1213,10 @@ class GridRepetition:
|
||||||
InvalidDataError: if `b_count` and `b_vector` inputs conflict
|
InvalidDataError: if `b_count` and `b_vector` inputs conflict
|
||||||
with each other or if `a_count < 1`.
|
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 None or b_count is None:
|
||||||
if b_vector is not None or b_count is not None:
|
if b_vector is not None or b_count is not None:
|
||||||
raise InvalidDataError('Repetition has only one of'
|
raise InvalidDataError('Repetition has only one of'
|
||||||
|
|
@ -1595,7 +1601,7 @@ def read_point_list(
|
||||||
|
|
||||||
def write_point_list(
|
def write_point_list(
|
||||||
stream: IO[bytes],
|
stream: IO[bytes],
|
||||||
points: list[Sequence[int]],
|
points: 'list[Sequence[int]] | NDArray',
|
||||||
fast: bool = False,
|
fast: bool = False,
|
||||||
implicit_closed: bool = True
|
implicit_closed: bool = True
|
||||||
) -> int:
|
) -> int:
|
||||||
|
|
@ -1618,6 +1624,8 @@ def write_point_list(
|
||||||
Number of bytes written.
|
Number of bytes written.
|
||||||
"""
|
"""
|
||||||
# If we're in a hurry, just write the points as arbitrary Deltas
|
# If we're in a hurry, just write the points as arbitrary Deltas
|
||||||
|
if _USE_NUMPY:
|
||||||
|
points = numpy.asarray(points, dtype=int)
|
||||||
if fast:
|
if fast:
|
||||||
size = write_uint(stream, 4)
|
size = write_uint(stream, 4)
|
||||||
size += write_uint(stream, len(points))
|
size += write_uint(stream, len(points))
|
||||||
|
|
|
||||||
|
|
@ -1434,7 +1434,7 @@ class Placement(Record):
|
||||||
size += self.name.write(stream) # type: ignore
|
size += self.name.write(stream) # type: ignore
|
||||||
if mm:
|
if mm:
|
||||||
size += write_real(stream, self.magnification) # type: ignore
|
size += write_real(stream, self.magnification) # type: ignore
|
||||||
if aa:
|
if aq:
|
||||||
size += write_real(stream, self.angle) # type: ignore
|
size += write_real(stream, self.angle) # type: ignore
|
||||||
if xx:
|
if xx:
|
||||||
size += write_sint(stream, self.x) # type: ignore
|
size += write_sint(stream, self.x) # type: ignore
|
||||||
|
|
@ -1717,8 +1717,8 @@ class Polygon(Record, GeometryMixin):
|
||||||
repetition: repetition_t | None
|
repetition: repetition_t | None
|
||||||
point_list: point_list_t | None
|
point_list: point_list_t | None
|
||||||
"""
|
"""
|
||||||
List of offsets from the initial vertex (x, y) to the remaining
|
List of offsets between consecutive vertices, starting from the initial
|
||||||
vertices, `[[dx0, dy0], [dx1, dy1], ...]`.
|
vertex (x, y): `[[dx0, dy0], [dx1, dy1], ...]`.
|
||||||
The list is an implicitly closed path, vertices are [int, int].
|
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`.
|
The initial vertex is located at (x, y) and is not represented in `point_list`.
|
||||||
`None` means reuse modal.
|
`None` means reuse modal.
|
||||||
|
|
@ -1744,7 +1744,7 @@ class Polygon(Record, GeometryMixin):
|
||||||
self.point_list = point_list
|
self.point_list = point_list
|
||||||
self.properties = [] if properties is None else properties
|
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)
|
warn('Polygon with < 3 points', stacklevel=2)
|
||||||
|
|
||||||
def get_point_list(self) -> point_list_t:
|
def get_point_list(self) -> point_list_t:
|
||||||
|
|
@ -1827,8 +1827,8 @@ class Path(Record, GeometryMixin):
|
||||||
repetition: repetition_t | None = None
|
repetition: repetition_t | None = None
|
||||||
point_list: point_list_t | None = None
|
point_list: point_list_t | None = None
|
||||||
"""
|
"""
|
||||||
List of offsets from the initial vertex (x, y) to the remaining vertices,
|
List of offsets between consecutive vertices, starting from the initial
|
||||||
`[[dx0, dy0], [dx1, dy1], ...]`.
|
vertex (x, y): `[[dx0, dy0], [dx1, dy1], ...]`.
|
||||||
The initial vertex is located at (x, y) and is not represented in `point_list`.
|
The initial vertex is located at (x, y) and is not represented in `point_list`.
|
||||||
Offsets are [int, int]; `None` means reuse modal.
|
Offsets are [int, int]; `None` means reuse modal.
|
||||||
"""
|
"""
|
||||||
|
|
@ -1960,7 +1960,7 @@ class Path(Record, GeometryMixin):
|
||||||
dd = self.datatype is not None
|
dd = self.datatype is not None
|
||||||
ll = self.layer 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))
|
size += write_bool_byte(stream, (ee, ww, pp, xx, yy, rr, dd, ll))
|
||||||
if ll:
|
if ll:
|
||||||
size += write_uint(stream, self.layer) # type: ignore
|
size += write_uint(stream, self.layer) # type: ignore
|
||||||
|
|
|
||||||
|
|
@ -34,15 +34,14 @@ keywords = [
|
||||||
]
|
]
|
||||||
classifiers = [
|
classifiers = [
|
||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Development Status :: 3 - Alpha",
|
"Development Status :: 4 - Beta",
|
||||||
"Environment :: Other Environment",
|
|
||||||
"Intended Audience :: Developers",
|
"Intended Audience :: Developers",
|
||||||
"Intended Audience :: Information Technology",
|
"Intended Audience :: Information Technology",
|
||||||
"Intended Audience :: Manufacturing",
|
"Intended Audience :: Manufacturing",
|
||||||
"Intended Audience :: Science/Research",
|
"Intended Audience :: Science/Research",
|
||||||
"License :: OSI Approved :: GNU Affero General Public License v3",
|
"License :: OSI Approved :: GNU Affero General Public License v3",
|
||||||
"Topic :: Scientific/Engineering",
|
|
||||||
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
|
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
|
||||||
|
"Topic :: File Formats",
|
||||||
]
|
]
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue