Compare commits
No commits in common. "main" and "feature/pyproject-toml" have entirely different histories.
main
...
feature/py
10 changed files with 60 additions and 127 deletions
6
.github/workflows/main.yml
vendored
6
.github/workflows/main.yml
vendored
|
|
@ -1,10 +1,6 @@
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on:
|
on: [push, pull_request, workflow_dispatch]
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
workflow_dispatch:
|
|
||||||
workflow_call:
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
|
||||||
6
.github/workflows/python-publish.yml
vendored
6
.github/workflows/python-publish.yml
vendored
|
|
@ -8,14 +8,16 @@ jobs:
|
||||||
create_wheel_and_sdist:
|
create_wheel_and_sdist:
|
||||||
name: create_wheel_and_sdist
|
name: create_wheel_and_sdist
|
||||||
uses: ./.github/workflows/main.yml
|
uses: ./.github/workflows/main.yml
|
||||||
|
with:
|
||||||
|
attest-package: "true"
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
needs: [ create_wheel_and_sdist ]
|
depends-on: create_wheel_and_sdist
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
environment: pypi
|
environment: pypi
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write # IMPORTANT: this permission is mandatory for Trusted Publishing
|
id-token: write. # IMPORTANT: this permission is mandatory for Trusted Publishing
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -129,6 +129,3 @@ dmypy.json
|
||||||
example_737
|
example_737
|
||||||
example_888
|
example_888
|
||||||
example_ksy.ksy
|
example_ksy.ksy
|
||||||
|
|
||||||
# Test stuff
|
|
||||||
devtest/
|
|
||||||
|
|
@ -1,12 +1,3 @@
|
||||||
## Modified version of "construct-typing" module used in my projects.
|
|
||||||
This modification features:
|
|
||||||
- **[EnhancedDataclassMixin](https://github.com/waszil/construct-typing/commit/479b51344bfd95149596a75ee574ac2e63c032df) with additional features**
|
|
||||||
- **ConstantOrContextLambda2 type**
|
|
||||||
- **Typing for Subconstruct**
|
|
||||||
- **Type hint for Computed**
|
|
||||||
- **Switch typing fixes**
|
|
||||||
|
|
||||||
The original README.md file was described down below:
|
|
||||||
# construct-typing
|
# construct-typing
|
||||||
[](https://pypi.org/project/construct-typing/)
|
[](https://pypi.org/project/construct-typing/)
|
||||||

|

|
||||||
|
|
|
||||||
|
|
@ -622,7 +622,7 @@ class Check(Construct[None, None]):
|
||||||
func: ConstantOrContextLambda[bool],
|
func: ConstantOrContextLambda[bool],
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
|
|
||||||
Error: Construct[t.NoReturn, t.NoReturn]
|
Error: Construct[None, None]
|
||||||
|
|
||||||
class FocusedSeq(Construct[t.Any, t.Any]):
|
class FocusedSeq(Construct[t.Any, t.Any]):
|
||||||
subcons: t.List[Construct[t.Any, t.Any]]
|
subcons: t.List[Construct[t.Any, t.Any]]
|
||||||
|
|
@ -800,10 +800,6 @@ def If(
|
||||||
) -> IfThenElse[t.Optional[ThenParsedType], t.Optional[ThenBuildTypes]]: ...
|
) -> IfThenElse[t.Optional[ThenParsedType], t.Optional[ThenBuildTypes]]: ...
|
||||||
|
|
||||||
SwitchType = t.TypeVar("SwitchType")
|
SwitchType = t.TypeVar("SwitchType")
|
||||||
SwitchParsedType = t.TypeVar("SwitchParsedType")
|
|
||||||
SwitchBuildTypes = t.TypeVar("SwitchBuildTypes")
|
|
||||||
SwitchDefaultParsedType = t.TypeVar("SwitchDefaultParsedType")
|
|
||||||
SwitchDefaultBuildTypes = t.TypeVar("SwitchDefaultBuildTypes")
|
|
||||||
|
|
||||||
class Switch(Construct[ParsedType, BuildTypes]):
|
class Switch(Construct[ParsedType, BuildTypes]):
|
||||||
keyfunc: ConstantOrContextLambda[t.Any]
|
keyfunc: ConstantOrContextLambda[t.Any]
|
||||||
|
|
@ -811,31 +807,17 @@ class Switch(Construct[ParsedType, BuildTypes]):
|
||||||
default: Construct[t.Any, t.Any]
|
default: Construct[t.Any, t.Any]
|
||||||
@t.overload
|
@t.overload
|
||||||
def __new__(
|
def __new__(
|
||||||
cls: "type[Switch[SwitchParsedType | None, SwitchBuildTypes | None]]",
|
cls: "type[Switch[int, t.Optional[int]]]",
|
||||||
keyfunc: ConstantOrContextLambda[SwitchType],
|
keyfunc: ConstantOrContextLambda[SwitchType],
|
||||||
cases: dict[t.Any, Construct[SwitchParsedType, SwitchBuildTypes]],
|
cases: t.Dict[SwitchType, Construct[int, int]],
|
||||||
default: None = ...,
|
default: t.Optional[Construct[int, int]] = ...,
|
||||||
) -> Switch[SwitchParsedType | None, SwitchBuildTypes | None]: ...
|
) -> Switch[int, t.Optional[int]]: ...
|
||||||
@t.overload
|
|
||||||
def __new__(
|
|
||||||
cls: "type[Switch[SwitchParsedType, SwitchBuildTypes]]",
|
|
||||||
keyfunc: ConstantOrContextLambda[SwitchType],
|
|
||||||
cases: dict[t.Any, Construct[SwitchParsedType, SwitchBuildTypes]],
|
|
||||||
default: Construct[t.NoReturn, t.NoReturn],
|
|
||||||
) -> Switch[SwitchParsedType, SwitchBuildTypes]: ...
|
|
||||||
@t.overload
|
|
||||||
def __new__(
|
|
||||||
cls: "type[Switch[SwitchParsedType | SwitchDefaultParsedType, SwitchBuildTypes | SwitchDefaultBuildTypes]]",
|
|
||||||
keyfunc: ConstantOrContextLambda[SwitchType],
|
|
||||||
cases: dict[t.Any, Construct[SwitchParsedType, SwitchBuildTypes]],
|
|
||||||
default: Construct[SwitchDefaultParsedType, SwitchDefaultBuildTypes],
|
|
||||||
) -> Switch[SwitchParsedType | SwitchDefaultParsedType, SwitchBuildTypes | SwitchDefaultBuildTypes]: ...
|
|
||||||
@t.overload
|
@t.overload
|
||||||
def __new__(
|
def __new__(
|
||||||
cls: "type[Switch[t.Any, t.Any]]",
|
cls: "type[Switch[t.Any, t.Any]]",
|
||||||
keyfunc: ConstantOrContextLambda[SwitchType],
|
keyfunc: ConstantOrContextLambda[t.Any],
|
||||||
cases: dict[t.Any, Construct[t.Any, t.Any]],
|
cases: t.Dict[t.Any, Construct[t.Any, t.Any]],
|
||||||
default: Construct[t.Any, t.Any] | None = ...,
|
default: t.Optional[Construct[t.Any, t.Any]] = ...,
|
||||||
) -> Switch[t.Any, t.Any]: ...
|
) -> Switch[t.Any, t.Any]: ...
|
||||||
|
|
||||||
class StopIf(Construct[None, None]):
|
class StopIf(Construct[None, None]):
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,15 @@ from .dataclass_struct import (
|
||||||
TStructField,
|
TStructField,
|
||||||
csfield,
|
csfield,
|
||||||
sfield,
|
sfield,
|
||||||
EnhancedDataclassMixin
|
|
||||||
)
|
)
|
||||||
from .generic_wrapper import (
|
from .generic_wrapper import (
|
||||||
Adapter,
|
Adapter,
|
||||||
ConstantOrContextLambda,
|
ConstantOrContextLambda,
|
||||||
ConstantOrContextLambda2,
|
|
||||||
Construct,
|
Construct,
|
||||||
Context,
|
Context,
|
||||||
ListContainer,
|
ListContainer,
|
||||||
PathType,
|
PathType,
|
||||||
Array,
|
Array
|
||||||
Subconstruct,
|
|
||||||
Computed,
|
|
||||||
)
|
)
|
||||||
from .tenum import EnumBase, EnumValue, FlagsEnumBase, TEnum, TFlagsEnum
|
from .tenum import EnumBase, EnumValue, FlagsEnumBase, TEnum, TFlagsEnum
|
||||||
|
|
||||||
|
|
@ -36,7 +32,6 @@ __all__ = [
|
||||||
"TStructField",
|
"TStructField",
|
||||||
"csfield",
|
"csfield",
|
||||||
"sfield",
|
"sfield",
|
||||||
"EnhancedDataclassMixin",
|
|
||||||
"EnumBase",
|
"EnumBase",
|
||||||
"EnumValue",
|
"EnumValue",
|
||||||
"FlagsEnumBase",
|
"FlagsEnumBase",
|
||||||
|
|
@ -44,12 +39,9 @@ __all__ = [
|
||||||
"TFlagsEnum",
|
"TFlagsEnum",
|
||||||
"Adapter",
|
"Adapter",
|
||||||
"ConstantOrContextLambda",
|
"ConstantOrContextLambda",
|
||||||
"ConstantOrContextLambda2",
|
|
||||||
"Construct",
|
"Construct",
|
||||||
"Context",
|
"Context",
|
||||||
"ListContainer",
|
"ListContainer",
|
||||||
"PathType",
|
"PathType",
|
||||||
"Array",
|
"Array"
|
||||||
"Subconstruct",
|
|
||||||
"Computed"
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# pyright: strict
|
# pyright: strict
|
||||||
# pyright: reportIncompatibleVariableOverride=false, reportAny=false
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import textwrap
|
import textwrap
|
||||||
import typing as t
|
import typing as t
|
||||||
|
|
@ -12,7 +11,6 @@ from construct.lib.containers import (
|
||||||
recursion_lock,
|
recursion_lock,
|
||||||
)
|
)
|
||||||
from construct.lib.py3compat import bytestringtype, reprstring, unicodestringtype
|
from construct.lib.py3compat import bytestringtype, reprstring, unicodestringtype
|
||||||
from typing_extensions import override
|
|
||||||
|
|
||||||
from .generic_wrapper import Adapter, Construct, Context, ParsedType, PathType
|
from .generic_wrapper import Adapter, Construct, Context, ParsedType, PathType
|
||||||
|
|
||||||
|
|
@ -29,7 +27,7 @@ class DataclassMixin:
|
||||||
methods exists and every name can be used.
|
methods exists and every name can be used.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__dataclass_fields__: "t.ClassVar[dict[str, dataclasses.Field[t.Any]]]"
|
__dataclass_fields__: "t.ClassVar[t.Dict[str, dataclasses.Field[t.Any]]]"
|
||||||
|
|
||||||
def __getitem__(self, key: str) -> t.Any:
|
def __getitem__(self, key: str) -> t.Any:
|
||||||
return getattr(self, key)
|
return getattr(self, key)
|
||||||
|
|
@ -79,8 +77,8 @@ class DataclassMixin:
|
||||||
|
|
||||||
def csfield(
|
def csfield(
|
||||||
subcon: Construct[ParsedType, t.Any],
|
subcon: Construct[ParsedType, t.Any],
|
||||||
doc: str | None = None,
|
doc: t.Optional[str] = None,
|
||||||
parsed: t.Callable[[t.Any, Context], None] | None = None,
|
parsed: t.Optional[t.Callable[[t.Any, Context], None]] = None,
|
||||||
) -> ParsedType:
|
) -> ParsedType:
|
||||||
"""
|
"""
|
||||||
Helper method for "DataclassStruct" and "DataclassBitStruct" to create the dataclass fields.
|
Helper method for "DataclassStruct" and "DataclassBitStruct" to create the dataclass fields.
|
||||||
|
|
@ -157,11 +155,15 @@ class DataclassStruct(Adapter[t.Any, t.Any, DataclassType, DataclassType]):
|
||||||
subcon: "cs.Struct" # type: ignore
|
subcon: "cs.Struct" # type: ignore
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
dc_type: type[DataclassType],
|
dc_type: t.Type[DataclassType],
|
||||||
reverse: bool = False,
|
reverse: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.dc_type: type[DataclassType] = dc_type
|
if not issubclass(dc_type, DataclassMixin): # type: ignore
|
||||||
self.reverse: bool = reverse
|
raise TypeError(f"'{repr(dc_type)}' has to be a '{repr(DataclassMixin)}'")
|
||||||
|
if not dataclasses.is_dataclass(dc_type):
|
||||||
|
raise TypeError(f"'{repr(dc_type)}' has to be a 'dataclasses.dataclass'")
|
||||||
|
self.dc_type = dc_type
|
||||||
|
self.reverse = reverse
|
||||||
|
|
||||||
# get all fields from the dataclass
|
# get all fields from the dataclass
|
||||||
fields = dataclasses.fields(self.dc_type)
|
fields = dataclasses.fields(self.dc_type)
|
||||||
|
|
@ -169,7 +171,7 @@ class DataclassStruct(Adapter[t.Any, t.Any, DataclassType, DataclassType]):
|
||||||
fields = tuple(reversed(fields))
|
fields = tuple(reversed(fields))
|
||||||
|
|
||||||
# extract the construct formats from the struct_type
|
# extract the construct formats from the struct_type
|
||||||
subcon_fields: dict[str, t.Any] = {}
|
subcon_fields = {}
|
||||||
for field in fields:
|
for field in fields:
|
||||||
subcon_fields[field.name] = field.metadata["subcon"]
|
subcon_fields[field.name] = field.metadata["subcon"]
|
||||||
|
|
||||||
|
|
@ -179,7 +181,6 @@ class DataclassStruct(Adapter[t.Any, t.Any, DataclassType, DataclassType]):
|
||||||
def __getattr__(self, name: str) -> t.Any:
|
def __getattr__(self, name: str) -> t.Any:
|
||||||
return getattr(self.subcon, name)
|
return getattr(self.subcon, name)
|
||||||
|
|
||||||
@override
|
|
||||||
def _decode(
|
def _decode(
|
||||||
self, obj: "cs.Container[t.Any]", context: Context, path: PathType
|
self, obj: "cs.Container[t.Any]", context: Context, path: PathType
|
||||||
) -> DataclassType:
|
) -> DataclassType:
|
||||||
|
|
@ -204,10 +205,9 @@ class DataclassStruct(Adapter[t.Any, t.Any, DataclassType, DataclassType]):
|
||||||
|
|
||||||
return dc # type: ignore
|
return dc # type: ignore
|
||||||
|
|
||||||
@override
|
|
||||||
def _encode(
|
def _encode(
|
||||||
self, obj: DataclassType, context: Context, path: PathType
|
self, obj: DataclassType, context: Context, path: PathType
|
||||||
) -> dict[str, t.Any]:
|
) -> t.Dict[str, t.Any]:
|
||||||
if not isinstance(obj, self.dc_type):
|
if not isinstance(obj, self.dc_type):
|
||||||
raise TypeError(f"'{repr(obj)}' has to be of type {repr(self.dc_type)}")
|
raise TypeError(f"'{repr(obj)}' has to be of type {repr(self.dc_type)}")
|
||||||
|
|
||||||
|
|
@ -215,16 +215,20 @@ class DataclassStruct(Adapter[t.Any, t.Any, DataclassType, DataclassType]):
|
||||||
fields = dataclasses.fields(self.dc_type)
|
fields = dataclasses.fields(self.dc_type)
|
||||||
|
|
||||||
# extract all fields from the container, that are used for create the dataclass object
|
# extract all fields from the container, that are used for create the dataclass object
|
||||||
ret_dict: dict[str, t.Any] = {}
|
ret_dict: t.Dict[str, t.Any] = {}
|
||||||
for field in fields:
|
for field in fields:
|
||||||
value = getattr(obj, field.name)
|
value = getattr(obj, field.name)
|
||||||
ret_dict[field.name] = value
|
ret_dict[field.name] = value
|
||||||
|
|
||||||
return ret_dict
|
return ret_dict
|
||||||
|
|
||||||
|
|
||||||
def DataclassBitStruct(
|
def DataclassBitStruct(
|
||||||
dc_type: type[DataclassType], reverse: bool = False
|
dc_type: t.Type[DataclassType], reverse: bool = False
|
||||||
) -> "cs.Transformed[DataclassType, DataclassType] | cs.Restreamed[DataclassType, DataclassType]":
|
) -> t.Union[
|
||||||
|
"cs.Transformed[DataclassType, DataclassType]",
|
||||||
|
"cs.Restreamed[DataclassType, DataclassType]",
|
||||||
|
]:
|
||||||
r"""
|
r"""
|
||||||
Makes a DataclassStruct inside a Bitwise.
|
Makes a DataclassStruct inside a Bitwise.
|
||||||
|
|
||||||
|
|
@ -251,29 +255,6 @@ def DataclassBitStruct(
|
||||||
"""
|
"""
|
||||||
return cs.Bitwise(DataclassStruct(dc_type, reverse))
|
return cs.Bitwise(DataclassStruct(dc_type, reverse))
|
||||||
|
|
||||||
class EnhancedDataclassMixin(DataclassMixin):
|
|
||||||
@classmethod
|
|
||||||
def format(cls):
|
|
||||||
return DataclassStruct(cls)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def build(cls, obj: t.Self, **kw: dict[str, t.Any]):
|
|
||||||
return cls.format().build(obj, **kw)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def parse(cls, data: bytes | bytearray, **kw: dict[str, t.Any]):
|
|
||||||
return cls.format().parse(data, **kw)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def parse_file(cls, file: str, **kw: dict[str, t.Any]):
|
|
||||||
return cls.format().parse_file(file, **kw)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def parse_stream(cls, stream: t.IO[bytes], **kw: dict[str, t.Any]):
|
|
||||||
return cls.format().parse_stream(stream, **kw)
|
|
||||||
|
|
||||||
def build_self(self) -> bytes:
|
|
||||||
return self.build(self)
|
|
||||||
|
|
||||||
# support legacy names
|
# support legacy names
|
||||||
TStruct = DataclassStruct
|
TStruct = DataclassStruct
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,12 @@ if t.TYPE_CHECKING:
|
||||||
# while type checking, the original classes are already generics, because they are defined like this in the stubs.
|
# while type checking, the original classes are already generics, because they are defined like this in the stubs.
|
||||||
from construct import Adapter as Adapter
|
from construct import Adapter as Adapter
|
||||||
from construct import ConstantOrContextLambda as ConstantOrContextLambda
|
from construct import ConstantOrContextLambda as ConstantOrContextLambda
|
||||||
from construct import ConstantOrContextLambda2 as ConstantOrContextLambda2
|
|
||||||
from construct import Construct as Construct
|
from construct import Construct as Construct
|
||||||
from construct import Context as Context
|
from construct import Context as Context
|
||||||
from construct import ListContainer as ListContainer
|
from construct import ListContainer as ListContainer
|
||||||
from construct import PathType as PathType
|
from construct import PathType as PathType
|
||||||
from construct import Array as Array
|
from construct import Array as Array
|
||||||
from construct import Subconstruct as Subconstruct
|
|
||||||
from construct import Computed as Computed
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
import construct as cs
|
import construct as cs
|
||||||
|
|
@ -46,12 +44,5 @@ else:
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Subconstruct(t.Generic[SubconParsedType, SubconBuildTypes, ParsedType, BuildTypes], cs.Subconstruct):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Computed(t.Generic[ParsedType], cs.Computed):
|
|
||||||
pass
|
|
||||||
|
|
||||||
ConstantOrContextLambda = t.Union[ValueType, t.Callable[[Context], t.Any]]
|
ConstantOrContextLambda = t.Union[ValueType, t.Callable[[Context], t.Any]]
|
||||||
ConstantOrContextLambda2 = t.Union[ValueType, t.Callable[[Context], ValueType]]
|
|
||||||
PathType = str
|
PathType = str
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
# pyright: reportAny=false
|
|
||||||
import enum
|
import enum
|
||||||
import typing as t
|
import typing as t
|
||||||
|
|
||||||
from typing_extensions import Self, override
|
from typing_extensions import Self
|
||||||
|
|
||||||
from .generic_wrapper import Construct, Adapter, Context, PathType
|
from .generic_wrapper import *
|
||||||
|
|
||||||
|
|
||||||
# ## TEnum ############################################################################################################
|
# ## TEnum ############################################################################################################
|
||||||
|
|
@ -13,8 +12,8 @@ class EnumValue:
|
||||||
This is a helper class for adding documentation to an enum value.
|
This is a helper class for adding documentation to an enum value.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, value: int, doc: str | None = None) -> None:
|
def __init__(self, value: int, doc: t.Optional[str] = None) -> None:
|
||||||
self.value: int = value
|
self.value = value
|
||||||
self.__doc__ = doc if doc else ""
|
self.__doc__ = doc if doc else ""
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -48,7 +47,7 @@ class EnumBase(enum.IntEnum):
|
||||||
'This is the running state.'
|
'This is the running state.'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __new__(cls, val: EnumValue | int) -> "Self":
|
def __new__(cls, val: t.Union[EnumValue, int]) -> "Self":
|
||||||
if isinstance(val, EnumValue):
|
if isinstance(val, EnumValue):
|
||||||
obj = int.__new__(cls, val.value)
|
obj = int.__new__(cls, val.value)
|
||||||
obj._value_ = val.value
|
obj._value_ = val.value
|
||||||
|
|
@ -63,8 +62,7 @@ class EnumBase(enum.IntEnum):
|
||||||
# not found in the enum, a new pseudo member is created.
|
# not found in the enum, a new pseudo member is created.
|
||||||
# The idea is taken from: https://stackoverflow.com/a/57179436
|
# The idea is taken from: https://stackoverflow.com/a/57179436
|
||||||
@classmethod
|
@classmethod
|
||||||
@override
|
def _missing_(cls, value: t.Any) -> t.Optional[enum.Enum]:
|
||||||
def _missing_(cls, value: t.Any) -> enum.Enum | None:
|
|
||||||
if isinstance(value, int):
|
if isinstance(value, int):
|
||||||
pseudo_member = cls._value2member_map_.get(value, None)
|
pseudo_member = cls._value2member_map_.get(value, None)
|
||||||
if pseudo_member is None:
|
if pseudo_member is None:
|
||||||
|
|
@ -78,8 +76,7 @@ class EnumBase(enum.IntEnum):
|
||||||
return pseudo_member
|
return pseudo_member
|
||||||
return None # will raise the ValueError in Enum.__new__
|
return None # will raise the ValueError in Enum.__new__
|
||||||
|
|
||||||
@override
|
def __reduce_ex__(self, proto: t.Any) -> t.Tuple[t.Any, ...]:
|
||||||
def __reduce_ex__(self, proto: t.Any) -> tuple[t.Any, ...]:
|
|
||||||
"""
|
"""
|
||||||
Pickle enums by value instead of name (restores pre-3.11 behavior).
|
Pickle enums by value instead of name (restores pre-3.11 behavior).
|
||||||
See https://github.com/python/cpython/pull/26658 for why this exists.
|
See https://github.com/python/cpython/pull/26658 for why this exists.
|
||||||
|
|
@ -94,18 +91,21 @@ class TEnum(Adapter[int, int, EnumType, EnumType]):
|
||||||
"""
|
"""
|
||||||
Typed enum.
|
Typed enum.
|
||||||
"""
|
"""
|
||||||
def __init__(self, subcon: Construct[int, int], enum_type: type[EnumType]):
|
def __init__(self, subcon: Construct[int, int], enum_type: t.Type[EnumType]):
|
||||||
|
if not issubclass(enum_type, EnumBase):
|
||||||
|
raise TypeError(
|
||||||
|
"'{}' has to be a '{}'".format(repr(enum_type), repr(EnumBase))
|
||||||
|
)
|
||||||
|
|
||||||
# save enum type
|
# save enum type
|
||||||
self.enum_type: type[EnumType] = enum_type
|
self.enum_type = t.cast(t.Type[EnumType], enum_type) # type: ignore
|
||||||
|
|
||||||
# init adatper
|
# init adatper
|
||||||
super(TEnum, self).__init__(subcon) # type: ignore
|
super(TEnum, self).__init__(subcon) # type: ignore
|
||||||
|
|
||||||
@override
|
|
||||||
def _decode(self, obj: int, context: Context, path: PathType) -> EnumType:
|
def _decode(self, obj: int, context: Context, path: PathType) -> EnumType:
|
||||||
return self.enum_type(obj)
|
return self.enum_type(obj)
|
||||||
|
|
||||||
@override
|
|
||||||
def _encode(
|
def _encode(
|
||||||
self,
|
self,
|
||||||
obj: EnumType,
|
obj: EnumType,
|
||||||
|
|
@ -152,7 +152,7 @@ class FlagsEnumBase(enum.IntFlag):
|
||||||
'This is option two.'
|
'This is option two.'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __new__(cls, val: EnumValue | int) -> "Self":
|
def __new__(cls, val: t.Union[EnumValue, int]) -> "Self":
|
||||||
if isinstance(val, EnumValue):
|
if isinstance(val, EnumValue):
|
||||||
obj = int.__new__(cls, val.value)
|
obj = int.__new__(cls, val.value)
|
||||||
obj._value_ = val.value
|
obj._value_ = val.value
|
||||||
|
|
@ -164,7 +164,6 @@ class FlagsEnumBase(enum.IntFlag):
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@override
|
|
||||||
def _missing_(cls, value: t.Any) -> t.Any:
|
def _missing_(cls, value: t.Any) -> t.Any:
|
||||||
"""
|
"""
|
||||||
Returns member (possibly creating it) if one can be found for value.
|
Returns member (possibly creating it) if one can be found for value.
|
||||||
|
|
@ -173,8 +172,7 @@ class FlagsEnumBase(enum.IntFlag):
|
||||||
new_member.__doc__ = "missing value"
|
new_member.__doc__ = "missing value"
|
||||||
return new_member
|
return new_member
|
||||||
|
|
||||||
@override
|
def __reduce_ex__(self, proto: t.Any) -> t.Tuple[t.Any, ...]:
|
||||||
def __reduce_ex__(self, proto: t.Any) -> tuple[t.Any, ...]:
|
|
||||||
"""
|
"""
|
||||||
Pickle enums by value instead of name (restores pre-3.11 behavior).
|
Pickle enums by value instead of name (restores pre-3.11 behavior).
|
||||||
See https://github.com/python/cpython/pull/26658 for why this exists.
|
See https://github.com/python/cpython/pull/26658 for why this exists.
|
||||||
|
|
@ -189,18 +187,21 @@ class TFlagsEnum(Adapter[int, int, FlagsEnumType, FlagsEnumType]):
|
||||||
"""
|
"""
|
||||||
Typed enum.
|
Typed enum.
|
||||||
"""
|
"""
|
||||||
def __init__(self, subcon: Construct[int, int], enum_type: type[FlagsEnumType]):
|
def __init__(self, subcon: Construct[int, int], enum_type: t.Type[FlagsEnumType]):
|
||||||
|
if not issubclass(enum_type, FlagsEnumBase):
|
||||||
|
raise TypeError(
|
||||||
|
"'{}' has to be a '{}'".format(repr(enum_type), repr(FlagsEnumBase))
|
||||||
|
)
|
||||||
|
|
||||||
# save enum type
|
# save enum type
|
||||||
self.enum_type: type[FlagsEnumType] = enum_type
|
self.enum_type = t.cast(t.Type[FlagsEnumType], enum_type) # type: ignore
|
||||||
|
|
||||||
# init adatper
|
# init adatper
|
||||||
super(TFlagsEnum, self).__init__(subcon) # type: ignore
|
super(TFlagsEnum, self).__init__(subcon) # type: ignore
|
||||||
|
|
||||||
@override
|
|
||||||
def _decode(self, obj: int, context: Context, path: PathType) -> FlagsEnumType:
|
def _decode(self, obj: int, context: Context, path: PathType) -> FlagsEnumType:
|
||||||
return self.enum_type(obj)
|
return self.enum_type(obj)
|
||||||
|
|
||||||
@override
|
|
||||||
def _encode(
|
def _encode(
|
||||||
self,
|
self,
|
||||||
obj: FlagsEnumType,
|
obj: FlagsEnumType,
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
version = (0, 7, 0)
|
version = (0, 6, 2)
|
||||||
version_string = "0.7.0+wrapper"
|
version_string = "0.6.2"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue