diff --git a/CHANGELOG.md b/CHANGELOG.md index a497f4b..6fd5379 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [2.9.1] - Typing fixes + +- `Prefixed` now supports struct types directly +- `StructDefMixin` now includes direct to-bytes conversion with `bytes(...)` +- Fixed a bug in `@bitfield` where parsed bit-width fields are not populated to the current context +- Corrected some type hints in `FieldMixin` and `_ContextLike` + ## [2.9.0] - Python 3.14 Compatibility and Generic Templates ### Added diff --git a/docs/sphinx/source/development/changelog.rst b/docs/sphinx/source/development/changelog.rst index ee6a617..1c9c0de 100644 --- a/docs/sphinx/source/development/changelog.rst +++ b/docs/sphinx/source/development/changelog.rst @@ -6,6 +6,16 @@ Changelog *More entries will be added in the future.* +.. _changelog_2.9.1: + +[2.9.1] - Bitfield and Prefixed update +====================================== + +- ``Prefixed`` now supports struct types directly +- ``StructDefMixin`` now includes direct to-bytes conversion with ``bytes(...)`` +- Fixed a bug in ``@bitfield`` where parsed bit-width fields are not populated to the current context +- Corrected some type hints in ``FieldMixin`` and ``_ContextLike`` + .. _changelog_2.9.0: [2.9.0] - Python 3.14 Compatibility and Generic Templates diff --git a/pypi/pyproject.toml b/pypi/pyproject.toml index 3f50269..5e4772c 100644 --- a/pypi/pyproject.toml +++ b/pypi/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "caterpillar-py" -version = "2.9.0" +version = "2.9.1" requires-python = ">=3.10" description="Library to pack and unpack structurized binary data." authors = [{ name = "MatrixEditor" }] diff --git a/pyproject.toml b/pyproject.toml index b0af367..5a4d31a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ cmake.source-dir = "." [project] name = "caterpillar" -version = "2.9.0" +version = "2.9.1" requires-python = ">=3.10" description = "Library to pack and unpack structurized binary data." authors = [{ name = "MatrixEditor" }] diff --git a/src/caterpillar/__init__.py b/src/caterpillar/__init__.py index 7a5c4ae..ae5b85d 100644 --- a/src/caterpillar/__init__.py +++ b/src/caterpillar/__init__.py @@ -14,8 +14,8 @@ # along with this program. If not, see . import warnings -__version__ = "2.9.0" -__release__ = "2.8" +__version__ = "2.9.1" +__release__ = "2.9" __author__ = "MatrixEditor" diff --git a/src/caterpillar/abc.py b/src/caterpillar/abc.py index 3ff0cba..632c6ee 100755 --- a/src/caterpillar/abc.py +++ b/src/caterpillar/abc.py @@ -143,6 +143,8 @@ def __getitem__(self, key: Literal["_arch"], /) -> "_ArchLike": ... @overload def __getitem__(self, key: Literal["_parent"], /) -> "_ContextLike": ... @overload + def __getitem__(self, key: Literal["_obj"], /) -> "_ContextLike": ... + @overload def __getitem__(self, key: Literal["_root"], /) -> "_ContextLike": ... @overload def __getitem__(self, key: Literal["_io"], /) -> _StreamType: ... @@ -570,7 +572,6 @@ def __call__(self, **kwargs: Any) -> _ContextLike: _AnnotationT = str | bytes | type | _ActionLike | _StructLike | Any - __all__ = [ "_ContextLike", "_ContextLambda", diff --git a/src/caterpillar/fields/_mixin.py b/src/caterpillar/fields/_mixin.py index b76605e..7d64752 100755 --- a/src/caterpillar/fields/_mixin.py +++ b/src/caterpillar/fields/_mixin.py @@ -33,7 +33,7 @@ _OT, _OptionLike, _EndianLike, - _SwitchLambda, + _SwitchOptionsT, _ArgType, ) from ._base import Field @@ -53,7 +53,7 @@ def __or__(self, flag: _OptionLike) -> Field[_IT, _OT]: # fmt: off return Field(self, byteorder(self)) | flag # pyright: ignore[reportArgumentType] - def __xor__(self, flag: Flag) -> Field[_IT, _OT]: + def __xor__(self, flag: _OptionLike) -> Field[_IT, _OT]: """Creates a field *without* the given flag.""" # fmt: off return Field(self, byteorder(self)) ^ flag # pyright: ignore[reportArgumentType] @@ -69,7 +69,7 @@ def __getitem__(self, dim: _LengthT) -> Field[Collection[_IT], Collection[_OT]]: return Field(self, byteorder(self))[dim] # pyright: ignore[reportArgumentType] def __rshift__( - self, switch: _SwitchLambda | dict[str, _StructLike] + self, switch: _SwitchOptionsT ) -> Field[_IT, _OT]: """Inserts switch options into the new field""" # fmt: off @@ -90,11 +90,15 @@ def __and__( self, other: "_StructLike[_OT, _ChainTailT]" ) -> "Chain[_IT, _ChainTailT]": ... @overload + def __and__( + self, other: "type[_ChainTailT]" + ) -> "Chain[_IT, _ChainTailT]": ... + @overload def __and__( self, other: "Chain[_OT, _ChainTailT]" ) -> "Chain[_IT, _ChainTailT]": ... def __and__( - self, other: "Chain[_OT, _ChainTailT] | _StructLike[_OT, _ChainTailT]" + self, other: "Chain[_OT, _ChainTailT] | _StructLike[_OT, _ChainTailT] | type[_OT]" ) -> "Chain": """Returns a chain joining this structure before the next element or chain.""" # fmt: off diff --git a/src/caterpillar/fields/common.py b/src/caterpillar/fields/common.py index 0e661ad..ea25ecc 100755 --- a/src/caterpillar/fields/common.py +++ b/src/caterpillar/fields/common.py @@ -1642,11 +1642,11 @@ class Prefixed(Generic[_PrefixIOT], FieldStruct[_PrefixIOT, _PrefixIOT]): def __init__( self, prefix: _StructLike[int, int], - struct: _StructLike[_PrefixIOT, _PrefixIOT] | None = None, + struct: _StructLike[_PrefixIOT, _PrefixIOT] | type[_PrefixIOT] | None = None, encoding: str | None = None, ): self.prefix: _StructLike[int, int] = prefix - self.struct: _StructLike[_PrefixIOT, _PrefixIOT] | None = struct + self.struct: _StructLike[_PrefixIOT, _PrefixIOT] | None = getstruct(struct, struct) self.encoding: str | None = encoding # Support str as second argument if isinstance(struct, str): diff --git a/src/caterpillar/model/_bitfield.py b/src/caterpillar/model/_bitfield.py index f729b5e..c97a82b 100755 --- a/src/caterpillar/model/_bitfield.py +++ b/src/caterpillar/model/_bitfield.py @@ -1077,6 +1077,7 @@ def unpack_one(self, context: _ContextLike) -> _VT: if entry.signed and value >= 1 << (entry.width - 1): value -= 1 << entry.width init_data[entry.name] = value + context[CTX_OBJECT][entry.name] = value return self.model(**init_data) # pyright: ignore[reportCallIssue] diff --git a/src/caterpillar/model/_struct.py b/src/caterpillar/model/_struct.py index fbcab81..6ea758e 100755 --- a/src/caterpillar/model/_struct.py +++ b/src/caterpillar/model/_struct.py @@ -322,6 +322,7 @@ class StructDefMixin: - ``cls.from_bytes(...)`` for constructing instances from raw binary data. - ``cls.from_file(...)`` for constructing instances from files. - ``obj.to_bytes(...)`` for serializing instances back into binary form. + - ``__bytes__()`` for direct to-bytes conversion with ``bytes(...)`` The primary purpose of this mixin is to improve ergonomics and satisfy static type checkers by exposing these behaviors directly on the model @@ -464,6 +465,10 @@ def to_bytes( **kwargs, ) + def __bytes__(self) -> bytes: + """Helper for direct bytes(...) conversion""" + return self.to_bytes() + class struct_factory: """Factory responsible for converting plain classes into ``@struct`` models. diff --git a/src/ccaterpillar/pyproject.toml b/src/ccaterpillar/pyproject.toml index d94c441..2e1ccdc 100644 --- a/src/ccaterpillar/pyproject.toml +++ b/src/ccaterpillar/pyproject.toml @@ -17,7 +17,7 @@ CP_ENABLE_NATIVE = "1" [project] name = "caterpillar" -version = "2.9.0" +version = "2.9.1" requires-python = ">=3.12" description = "Library to pack and unpack structurized binary data." readme = "../../README.md"