renamed "TContainerBase" to "TContainerMixin"
This commit is contained in:
parent
7f88357562
commit
b336087493
6 changed files with 40 additions and 34 deletions
15
README.md
15
README.md
|
|
@ -54,7 +54,7 @@ Note: The stubs are based on *construct* in Version 2.10.
|
|||
To include autocompletion and further enhance the type hints for these complex constructs the **construct_typed** package is used as an extension to the original *construct* package. It is mainly a bunch of Adapters for the original constructs with the focus on type hints.
|
||||
|
||||
It implements the following new constructs:
|
||||
- `TStruct`, `TBitStruct`: similar to `construct.Struct` but strictly tied to `TContainerBase` and `@dataclasses.dataclass`
|
||||
- `TStruct`, `TBitStruct`: similar to `construct.Struct` but strictly tied to `TContainerMixin` and `@dataclasses.dataclass`
|
||||
- `TEnum`: similar to `construct.Enum` but strictly tied to a `TEnumBase` class
|
||||
- `TFlagsEnum`: similar to `construct.FlagsEnum` but strictly tied to a `TFlagsEnumBase` class
|
||||
|
||||
|
|
@ -67,18 +67,19 @@ A short example:
|
|||
import dataclasses
|
||||
import construct as cs
|
||||
import construct_typed as cst
|
||||
import typing as t
|
||||
|
||||
class Orientation(cst.EnumBase):
|
||||
HORIZONTAL = 0
|
||||
VERTICAL = 1
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Image(cst.TContainerBase):
|
||||
signature: cst.Opt[bytes] = cst.sfield(cs.Const(b"BMP"))
|
||||
orientation: Orientation = cst.sfield(cst.TEnum(cs.Int8ub, Orientation))
|
||||
width: int = cst.sfield(cs.Int8ub)
|
||||
height: int = cst.sfield(cs.Int8ub)
|
||||
pixels: cst.List[int] = cst.sfield(cs.Array(cs.this.width * cs.this.height, cs.Byte))
|
||||
class Image(cst.TContainerMixin):
|
||||
signature: t.Optional[bytes] = cst.TStructField(cs.Const(b"BMP"))
|
||||
orientation: Orientation = cst.TStructField(cst.TEnum(cs.Int8ub, Orientation))
|
||||
width: int = cst.TStructField(cs.Int8ub)
|
||||
height: int = cst.TStructField(cs.Int8ub)
|
||||
pixels: t.List[int] = cst.TStructField(cs.Array(cs.this.width * cs.this.height, cs.Byte))
|
||||
|
||||
format = cst.TStruct(Image)
|
||||
obj = Image(orientation=Orientation.VERTICAL, width=3, height=2, pixels=[7, 8, 9, 11, 12, 13])
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from .generic_wrapper import (
|
|||
PathType,
|
||||
)
|
||||
from .tenum import EnumBase, FlagsEnumBase, TEnum, TFlagsEnum
|
||||
from .tstruct import TBitStruct, TStruct, sfield, TStructField, TContainerBase
|
||||
from .tstruct import TBitStruct, TStruct, sfield, TStructField, TContainerMixin, TContainerBase
|
||||
from .tunion import TUnion, ufield, TUnionField
|
||||
|
||||
__all__ = [
|
||||
|
|
@ -24,6 +24,7 @@ __all__ = [
|
|||
"Adapter",
|
||||
"ListContainer",
|
||||
"TContainerBase",
|
||||
"TContainerMixin",
|
||||
"Context",
|
||||
"ConstantOrContextLambda",
|
||||
"PathType",
|
||||
|
|
|
|||
|
|
@ -15,17 +15,17 @@ from .generic_wrapper import (
|
|||
|
||||
if t.TYPE_CHECKING:
|
||||
|
||||
class _TContainerBase(cs.Container[t.Any]):
|
||||
class _TContainerMixin(cs.Container[t.Any]):
|
||||
...
|
||||
|
||||
|
||||
else:
|
||||
|
||||
class _TContainerBase(cs.Container):
|
||||
class _TContainerMixin(cs.Container):
|
||||
pass
|
||||
|
||||
|
||||
class TContainerBase(_TContainerBase):
|
||||
class TContainerMixin(_TContainerMixin):
|
||||
"""
|
||||
Base class for a Container of a TStruct and a TBitStruct.
|
||||
|
||||
|
|
@ -50,6 +50,9 @@ class TContainerBase(_TContainerBase):
|
|||
self.move_to_end(field.name)
|
||||
|
||||
|
||||
TContainerBase = TContainerMixin # also support legacy name
|
||||
|
||||
|
||||
def sfield(
|
||||
subcon: Construct[ParsedType, t.Any],
|
||||
doc: t.Optional[str] = None,
|
||||
|
|
@ -76,9 +79,10 @@ def sfield(
|
|||
|
||||
return field # type: ignore
|
||||
|
||||
|
||||
TStructField = sfield # also support legacy name
|
||||
|
||||
ContainerType = t.TypeVar("ContainerType", bound=TContainerBase)
|
||||
ContainerType = t.TypeVar("ContainerType", bound=TContainerMixin)
|
||||
|
||||
|
||||
class _TStruct(Adapter[t.Any, t.Any, ContainerType, BuildTypes]):
|
||||
|
|
@ -92,10 +96,10 @@ class _TStruct(Adapter[t.Any, t.Any, ContainerType, BuildTypes]):
|
|||
swapped: bool = False,
|
||||
add_offsets: bool = False,
|
||||
) -> None:
|
||||
if not issubclass(container_type, TContainerBase):
|
||||
if not issubclass(container_type, TContainerMixin):
|
||||
raise TypeError(
|
||||
"'{}' has to be a '{}'".format(
|
||||
repr(container_type), repr(TContainerBase)
|
||||
repr(container_type), repr(TContainerMixin)
|
||||
)
|
||||
)
|
||||
if not dataclasses.is_dataclass(container_type):
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import construct_typed as cst
|
|||
Buffer = t.Union[bytes, memoryview, bytearray]
|
||||
ParsedType = t.TypeVar("ParsedType")
|
||||
BuildTypes = t.TypeVar("BuildTypes")
|
||||
ContainerType = t.TypeVar("ContainerType", bound=cst.TContainerBase)
|
||||
ContainerType = t.TypeVar("ContainerType", bound=cst.TContainerMixin)
|
||||
T = t.TypeVar("T")
|
||||
|
||||
IdentType = t.TypeVar("IdentType")
|
||||
|
|
|
|||
|
|
@ -1705,7 +1705,7 @@ def test_from_issue_324() -> None:
|
|||
)),
|
||||
"checksum" / Checksum(
|
||||
Byte,
|
||||
lambda data: sum(iterateints(data)) & 0xFF,
|
||||
lambda data: sum(data) & 0xFF,
|
||||
this.vals.data
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ def test_tcontainer_compare_with_dataclass() -> None:
|
|||
b: int = cst.sfield(cs.Int8ub)
|
||||
|
||||
@dataclasses.dataclass
|
||||
class TestTContainer(cst.TContainerBase):
|
||||
class TestTContainer(cst.TContainerMixin):
|
||||
a: t.Optional[int] = cst.sfield(cs.Const(1, cs.Byte))
|
||||
b: int = cst.sfield(cs.Int8ub)
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ def test_tcontainer_compare_with_dataclass() -> None:
|
|||
|
||||
def test_tcontainer_order() -> None:
|
||||
@dataclasses.dataclass
|
||||
class Image(cst.TContainerBase):
|
||||
class Image(cst.TContainerMixin):
|
||||
signature: t.Optional[bytes] = cst.sfield(cs.Const(b"BMP"))
|
||||
width: int = cst.sfield(cs.Int8ub)
|
||||
height: int = cst.sfield(cs.Int8ub)
|
||||
|
|
@ -85,7 +85,7 @@ def test_tcontainer_order() -> None:
|
|||
|
||||
def test_tstruct() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
a: int = cst.sfield(cs.Int16ub)
|
||||
b: int = cst.sfield(cs.Int8ub)
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ def test_tstruct() -> None:
|
|||
|
||||
def test_tstruct_swapped() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
a: int = cst.sfield(cs.Int16ub)
|
||||
b: int = cst.sfield(cs.Int8ub)
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ def test_tstruct_swapped() -> None:
|
|||
|
||||
def test_tstruct_add_offsets() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
a: int = cst.sfield(cs.Int16ub)
|
||||
b: int = cst.sfield(cs.Int8ub)
|
||||
|
||||
|
|
@ -138,9 +138,9 @@ def test_tstruct_add_offsets() -> None:
|
|||
|
||||
def test_tstruct_nested() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
@dataclasses.dataclass
|
||||
class InnerDataclass(cst.TContainerBase):
|
||||
class InnerDataclass(cst.TContainerMixin):
|
||||
b: int = cst.sfield(cs.Byte)
|
||||
|
||||
a: InnerDataclass = cst.sfield(cst.TStruct(InnerDataclass))
|
||||
|
|
@ -155,7 +155,7 @@ def test_tstruct_nested() -> None:
|
|||
|
||||
def test_tstruct_default_field() -> None:
|
||||
@dataclasses.dataclass
|
||||
class Image(cst.TContainerBase):
|
||||
class Image(cst.TContainerMixin):
|
||||
width: int = cst.sfield(cs.Int8ub)
|
||||
height: int = cst.sfield(cs.Int8ub)
|
||||
pixels: t.Optional[bytes] = cst.sfield(
|
||||
|
|
@ -175,7 +175,7 @@ def test_tstruct_default_field() -> None:
|
|||
|
||||
def test_tstruct_const_field() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
const_field: t.Optional[bytes] = cst.sfield(cs.Const(b"\x00"))
|
||||
|
||||
common(
|
||||
|
|
@ -195,7 +195,7 @@ def test_tstruct_const_field() -> None:
|
|||
|
||||
def test_tstruct_array_field() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
array_field: t.List[int] = cst.sfield(cs.Array(5, cs.Int8ub))
|
||||
|
||||
common(
|
||||
|
|
@ -208,7 +208,7 @@ def test_tstruct_array_field() -> None:
|
|||
|
||||
def test_tstruct_anonymus_fields_1() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
_1: t.Optional[bytes] = cst.sfield(cs.Const(b"\x00"))
|
||||
_2: None = cst.sfield(cs.Padding(1))
|
||||
_3: None = cst.sfield(cs.Pass)
|
||||
|
|
@ -224,7 +224,7 @@ def test_tstruct_anonymus_fields_1() -> None:
|
|||
|
||||
def test_tstruct_anonymus_fields_2() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
_1: int = cst.sfield(cs.Computed(7))
|
||||
_2: t.Optional[bytes] = cst.sfield(cs.Const(b"JPEG"))
|
||||
_3: None = cst.sfield(cs.Pass)
|
||||
|
|
@ -235,14 +235,14 @@ def test_tstruct_anonymus_fields_2() -> None:
|
|||
|
||||
|
||||
def test_tstruct_no_dataclass() -> None:
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
a: int = cst.sfield(cs.Int16ub)
|
||||
b: int = cst.sfield(cs.Int8ub)
|
||||
|
||||
assert raises(lambda: cst.TStruct(TestContainer)) == TypeError
|
||||
|
||||
|
||||
def test_tstruct_no_tcontainerbase() -> None:
|
||||
def test_tstruct_no_TContainerMixin() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer:
|
||||
a: int = cst.sfield(cs.Int16ub)
|
||||
|
|
@ -253,12 +253,12 @@ def test_tstruct_no_tcontainerbase() -> None:
|
|||
|
||||
def test_tstruct_wrong_container() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer1(cst.TContainerBase):
|
||||
class TestContainer1(cst.TContainerMixin):
|
||||
a: int = cst.sfield(cs.Int16ub)
|
||||
b: int = cst.sfield(cs.Int8ub)
|
||||
|
||||
@dataclasses.dataclass
|
||||
class TestContainer2(cst.TContainerBase):
|
||||
class TestContainer2(cst.TContainerMixin):
|
||||
a: int = cst.sfield(cs.Int16ub)
|
||||
b: int = cst.sfield(cs.Int8ub)
|
||||
|
||||
|
|
@ -269,7 +269,7 @@ def test_tstruct_wrong_container() -> None:
|
|||
|
||||
def test_tstruct_doc() -> None:
|
||||
@dataclasses.dataclass
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
a: int = cst.sfield(cs.Int16ub, "This is the documentation of a")
|
||||
b: int = cst.sfield(
|
||||
cs.Int8ub, doc="This is the documentation of b\nwhich is multiline"
|
||||
|
|
@ -344,7 +344,7 @@ def test_tenum_in_tstruct() -> None:
|
|||
b = 2
|
||||
|
||||
@dataclasses.dataclass
|
||||
class TestContainer(cst.TContainerBase):
|
||||
class TestContainer(cst.TContainerMixin):
|
||||
a: TestEnum = cst.sfield(cst.TEnum(cs.Int8ub, TestEnum))
|
||||
b: int = cst.sfield(cs.Int8ub)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue