0.12.0
New Features
Type Checking Compatibility
Type checker-compatible annotations are finally here! The old dataclass annotation way would cause type checkers to report errors when you try assigning an int
to a field marked as UInt8
. You can now get around this by using typing.Annotated
.
The old way:
@binobj.dataclass
class MyStruct(binobj.Struct):
foo: UInt16
bar: StringZ = ""
sub_struct: MyOtherStruct
baz: Timestamp64(signed=False)
To save you headaches with MyPy, the same struct can be declared like so:
@binobj.dataclass
class MyStruct(binobj.Struct):
foo: Annotated[int, UInt16]
bar: Annotated[str, StringZ] = ""
sub_struct: MyOtherStruct # Note no change necessary here
baz: Annotated[datetime, Timestamp64(signed=False)]
Full Mapping-like Behavior
Two new struct wrappers, StructMappingProxy
and MutableStructMappingProxy
, allow you to use a Struct
exactly as you would a Mapping
or MutableMapping
:
ro_proxy = binobj.StructMappingProxy(struct_instance)
assert ro_proxy.struct is struct_instance # Original struct still available
for key, value in ro_proxy.items():
print(f"{k!r} = {v!r}")
cm = collections.ChainMap({}, binobj.MutableStructMappingProxy(struct_instance))
These are typed as Mapping[str, Any]
and MutableMapping[str, Any]
, respectively.
Other New Features
Now testing on Python 3.13-rc1.
Deprecations
- Support for Python 3.9 will be removed in the next backwards-incompatible release.
- Using
Field
instances as bare annotations is deprecated; usetyping.Annotated
instead.
Bugfixes
- On Python ≤ 3.10, using
Field
instances as type annotations completely broke if deferred annotation evaluation was enabled withfrom __future__ import annotations
. This can now be worked around by usingAnnotated
, or with normal field assignment. - When reading fixed data, if
exact
was true the error message would be one byte off when saying how much it expected to read. - Better type annotations for containers.
- Error messages now use
__qualname__
for classes, instead of__name__
. This will only change the output of nested classes.
Breaking Changes
Dropped support for EOL Python 3.7 and 3.8.
Other Changes
- Refactored
Struct
class initialization and pushed it into a factory method onStructMetadata
. The eventual goal is to completely eliminate the need for inheritingStruct
. - Switched from Black to Ruff.
- Minimum version of
typing_extensions
is now 4.4. - Upgraded test dependencies.