Compare commits

...

5 Commits

Author SHA1 Message Date
jan
45f675ca22 use klamath_rs_ext if available 2025-10-26 18:07:07 -07:00
jan
74b9672b4a bump version to v1.5 2025-10-12 23:37:53 -07:00
jan
0ac4c3b275 fix path extensions not getting written correctly 2025-10-12 23:37:53 -07:00
ae9c2d7b5f add type annotation 2025-04-21 19:39:23 -07:00
428e396b9b Loosen type requirements / guarantees for properties
We will still return a dict, but only require a mapping when writing
2025-04-21 19:39:23 -07:00
4 changed files with 24 additions and 12 deletions

View File

@ -36,5 +36,5 @@ from . import (
)
__author__ = 'Jan Petykiewicz'
__version__ = '1.4'
__version__ = '1.5'

View File

@ -17,6 +17,11 @@ logger = logging.getLogger(__name__)
class KlamathError(Exception):
pass
try:
from klamath_rs_ext import pack_int2, pack_int4
_USE_RS_EXT = True
except ImportError:
_USE_RS_EXT = False
#
# Parse functions
@ -93,14 +98,14 @@ def pack_bitarray(data: int) -> bytes:
return struct.pack('>H', data)
def pack_int2(data: NDArray[numpy.integer] | Sequence[int] | int) -> bytes:
def _pack_int2(data: NDArray[numpy.integer] | Sequence[int] | int) -> bytes:
arr = numpy.asarray(data)
if (arr > 32767).any() or (arr < -32768).any():
raise KlamathError(f'int2 data out of range: {arr}')
return arr.astype('>i2').tobytes()
def pack_int4(data: NDArray[numpy.integer] | Sequence[int] | int) -> bytes:
def _pack_int4(data: NDArray[numpy.integer] | Sequence[int] | int) -> bytes:
arr = numpy.asarray(data)
if (arr > 2147483647).any() or (arr < -2147483648).any():
raise KlamathError(f'int4 data out of range: {arr}')
@ -189,3 +194,9 @@ def read(stream: IO[bytes], size: int) -> bytes:
if len(data) != size:
raise EOFError
return data
if not _USE_RS_EXT:
pack_int2 = _pack_int2
pack_int4 = _pack_int4

View File

@ -3,6 +3,7 @@ Functionality for reading/writing elements (geometry, text labels,
structure references) and associated properties.
"""
from typing import IO, TypeVar
from collections.abc import Mapping
from abc import ABCMeta, abstractmethod
from dataclasses import dataclass
@ -56,7 +57,7 @@ def read_properties(stream: IO[bytes]) -> dict[int, bytes]:
return properties
def write_properties(stream: IO[bytes], properties: dict[int, bytes]) -> int:
def write_properties(stream: IO[bytes], properties: Mapping[int, bytes]) -> int:
"""
Write element properties.
@ -147,7 +148,7 @@ class Reference(Element):
colrow: tuple[int, int] | NDArray[numpy.int16] | None
""" Number of columns and rows (AREF) or None (SREF) """
properties: dict[int, bytes]
properties: Mapping[int, bytes]
""" Properties associated with this reference. """
@classmethod
@ -229,7 +230,7 @@ class Boundary(Element):
xy: NDArray[numpy.int32]
""" Ordered vertices of the shape. First and last points should be identical. """
properties: dict[int, bytes]
properties: Mapping[int, bytes]
""" Properties for the element. """
@classmethod
@ -275,7 +276,7 @@ class Path(Element):
xy: NDArray[numpy.int32]
""" Path centerline coordinates """
properties: dict[int, bytes]
properties: Mapping[int, bytes]
""" Properties for the element. """
@classmethod
@ -315,7 +316,7 @@ class Path(Element):
if self.width != 0:
b += WIDTH.write(stream, self.width)
if self.path_type < 4:
if self.path_type == 4:
bgn_ext, end_ext = self.extension
if bgn_ext != 0:
b += BGNEXTN.write(stream, bgn_ext)
@ -340,7 +341,7 @@ class Box(Element):
xy: NDArray[numpy.int32]
""" Box coordinates (5 pairs) """
properties: dict[int, bytes]
properties: Mapping[int, bytes]
""" Properties for the element. """
@classmethod
@ -374,7 +375,7 @@ class Node(Element):
xy: NDArray[numpy.int32]
""" 1-50 pairs of coordinates. """
properties: dict[int, bytes]
properties: Mapping[int, bytes]
""" Properties for the element. """
@classmethod
@ -434,7 +435,7 @@ class Text(Element):
string: bytes
""" Text content """
properties: dict[int, bytes]
properties: Mapping[int, bytes]
""" Properties for the element. """
@classmethod

View File

@ -120,7 +120,7 @@ def test_pack_ascii() -> None:
assert pack_ascii(b'321') == b'321\0'
def test_invalid_date():
def test_invalid_date() -> None:
default = [datetime(1900, 1, 1, 0, 0, 0)]
assert parse_datetime(pack_int2((0, 0, 0, 0, 0, 0))) == default
assert parse_datetime(pack_int2((0, 1, 32, 0, 0, 0))) == default