Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
10 changes: 10 additions & 0 deletions docs/sphinx/source/development/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pypi/pyproject.toml
Original file line number Diff line number Diff line change
@@ -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" }]
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }]
Expand Down
4 changes: 2 additions & 2 deletions src/caterpillar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import warnings

__version__ = "2.9.0"
__release__ = "2.8"
__version__ = "2.9.1"
__release__ = "2.9"
__author__ = "MatrixEditor"


Expand Down
3 changes: 2 additions & 1 deletion src/caterpillar/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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: ...
Expand Down Expand Up @@ -570,7 +572,6 @@ def __call__(self, **kwargs: Any) -> _ContextLike:

_AnnotationT = str | bytes | type | _ActionLike | _StructLike | Any


__all__ = [
"_ContextLike",
"_ContextLambda",
Expand Down
12 changes: 8 additions & 4 deletions src/caterpillar/fields/_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
_OT,
_OptionLike,
_EndianLike,
_SwitchLambda,
_SwitchOptionsT,
_ArgType,
)
from ._base import Field
Expand All @@ -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]
Expand All @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/caterpillar/fields/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
1 change: 1 addition & 0 deletions src/caterpillar/model/_bitfield.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down
5 changes: 5 additions & 0 deletions src/caterpillar/model/_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/ccaterpillar/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading