Compare commits

..

2 Commits

Author SHA1 Message Date
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
3 changed files with 11 additions and 21 deletions

View File

@ -17,11 +17,6 @@ logger = logging.getLogger(__name__)
class KlamathError(Exception): class KlamathError(Exception):
pass pass
try:
from klamath_rs_ext import pack_int2, pack_int4
_USE_RS_EXT = True
except ImportError:
_USE_RS_EXT = False
# #
# Parse functions # Parse functions
@ -98,14 +93,14 @@ def pack_bitarray(data: int) -> bytes:
return struct.pack('>H', data) 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) arr = numpy.asarray(data)
if (arr > 32767).any() or (arr < -32768).any(): if (arr > 32767).any() or (arr < -32768).any():
raise KlamathError(f'int2 data out of range: {arr}') raise KlamathError(f'int2 data out of range: {arr}')
return arr.astype('>i2').tobytes() 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) arr = numpy.asarray(data)
if (arr > 2147483647).any() or (arr < -2147483648).any(): if (arr > 2147483647).any() or (arr < -2147483648).any():
raise KlamathError(f'int4 data out of range: {arr}') raise KlamathError(f'int4 data out of range: {arr}')
@ -194,9 +189,3 @@ def read(stream: IO[bytes], size: int) -> bytes:
if len(data) != size: if len(data) != size:
raise EOFError raise EOFError
return data 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. structure references) and associated properties.
""" """
from typing import IO, TypeVar from typing import IO, TypeVar
from collections.abc import Mapping
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from dataclasses import dataclass from dataclasses import dataclass
@ -56,7 +57,7 @@ def read_properties(stream: IO[bytes]) -> dict[int, bytes]:
return properties 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. Write element properties.
@ -147,7 +148,7 @@ class Reference(Element):
colrow: tuple[int, int] | NDArray[numpy.int16] | None colrow: tuple[int, int] | NDArray[numpy.int16] | None
""" Number of columns and rows (AREF) or None (SREF) """ """ Number of columns and rows (AREF) or None (SREF) """
properties: dict[int, bytes] properties: Mapping[int, bytes]
""" Properties associated with this reference. """ """ Properties associated with this reference. """
@classmethod @classmethod
@ -229,7 +230,7 @@ class Boundary(Element):
xy: NDArray[numpy.int32] xy: NDArray[numpy.int32]
""" Ordered vertices of the shape. First and last points should be identical. """ """ Ordered vertices of the shape. First and last points should be identical. """
properties: dict[int, bytes] properties: Mapping[int, bytes]
""" Properties for the element. """ """ Properties for the element. """
@classmethod @classmethod
@ -275,7 +276,7 @@ class Path(Element):
xy: NDArray[numpy.int32] xy: NDArray[numpy.int32]
""" Path centerline coordinates """ """ Path centerline coordinates """
properties: dict[int, bytes] properties: Mapping[int, bytes]
""" Properties for the element. """ """ Properties for the element. """
@classmethod @classmethod
@ -340,7 +341,7 @@ class Box(Element):
xy: NDArray[numpy.int32] xy: NDArray[numpy.int32]
""" Box coordinates (5 pairs) """ """ Box coordinates (5 pairs) """
properties: dict[int, bytes] properties: Mapping[int, bytes]
""" Properties for the element. """ """ Properties for the element. """
@classmethod @classmethod
@ -374,7 +375,7 @@ class Node(Element):
xy: NDArray[numpy.int32] xy: NDArray[numpy.int32]
""" 1-50 pairs of coordinates. """ """ 1-50 pairs of coordinates. """
properties: dict[int, bytes] properties: Mapping[int, bytes]
""" Properties for the element. """ """ Properties for the element. """
@classmethod @classmethod
@ -434,7 +435,7 @@ class Text(Element):
string: bytes string: bytes
""" Text content """ """ Text content """
properties: dict[int, bytes] properties: Mapping[int, bytes]
""" Properties for the element. """ """ Properties for the element. """
@classmethod @classmethod

View File

@ -120,7 +120,7 @@ def test_pack_ascii() -> None:
assert pack_ascii(b'321') == b'321\0' 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)] 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, 0, 0, 0, 0, 0))) == default
assert parse_datetime(pack_int2((0, 1, 32, 0, 0, 0))) == default assert parse_datetime(pack_int2((0, 1, 32, 0, 0, 0))) == default