From fddd438ac8f6fcc724f1c06d2f007ee5a4a20c53 Mon Sep 17 00:00:00 2001 From: timrid <6593626+timrid@users.noreply.github.com> Date: Mon, 27 Oct 2025 20:05:12 +0100 Subject: [PATCH 1/7] fix publish workflow --- .github/workflows/main.yml | 6 +++++- .github/workflows/python-publish.yml | 6 ++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 44dc00c..e09f947 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,10 @@ name: CI -on: [push, pull_request, workflow_dispatch] +on: + push: + pull_request: + workflow_dispatch: + workflow_call: jobs: build: diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 6cdb1dd..ea14263 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -8,16 +8,14 @@ jobs: create_wheel_and_sdist: name: create_wheel_and_sdist uses: ./.github/workflows/main.yml - with: - attest-package: "true" deploy: - depends-on: create_wheel_and_sdist + needs: [ create_wheel_and_sdist ] runs-on: ubuntu-latest environment: pypi permissions: - id-token: write. # IMPORTANT: this permission is mandatory for Trusted Publishing + id-token: write # IMPORTANT: this permission is mandatory for Trusted Publishing steps: - uses: actions/checkout@v3 From f3b7bc342ee6ecc1aee4d072972cdfd626666a81 Mon Sep 17 00:00:00 2001 From: timrid <6593626+timrid@users.noreply.github.com> Date: Mon, 27 Oct 2025 20:18:53 +0100 Subject: [PATCH 2/7] incremented version to 0.7.0 --- construct_typed/version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/construct_typed/version.py b/construct_typed/version.py index b1bde74..04fbf4c 100644 --- a/construct_typed/version.py +++ b/construct_typed/version.py @@ -1,2 +1,2 @@ -version = (0, 6, 2) -version_string = "0.6.2" +version = (0, 7, 0) +version_string = "0.7.0" From 0c93e4d551079227d560dc71515998d8653711c0 Mon Sep 17 00:00:00 2001 From: wrapper Date: Tue, 7 Apr 2026 18:48:27 +0700 Subject: [PATCH 3/7] mod --- .gitignore | 3 ++ README.md | 8 ++++ construct-stubs/core.pyi | 27 +++++++++----- construct_typed/__init__.py | 12 +++++- construct_typed/dataclass_struct.py | 57 +++++++++++++++++++---------- construct_typed/generic_wrapper.py | 11 +++++- construct_typed/tenum.py | 45 +++++++++++------------ construct_typed/version.py | 2 +- 8 files changed, 110 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index b3d4398..1d9e0fe 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,6 @@ dmypy.json example_737 example_888 example_ksy.ksy + +# Test stuff +devtest/ \ No newline at end of file diff --git a/README.md b/README.md index b11989c..d95463b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ +## Modified version of "construct-typing" module used in my projects. +This modification features: +- **[EnhancedDataclassMixin](https://github.com/waszil/construct-typing/commit/479b51344bfd95149596a75ee574ac2e63c032df)** +- **ConstantOrContextLambda2 type** +- **Typing for Subconstruct** +- **Type hint for Computed** + +The original README.md file was described down below: # construct-typing [![PyPI](https://img.shields.io/pypi/v/construct-typing)](https://pypi.org/project/construct-typing/) ![PyPI - Implementation](https://img.shields.io/pypi/implementation/construct-typing) diff --git a/construct-stubs/core.pyi b/construct-stubs/core.pyi index 456ab4a..59f482e 100644 --- a/construct-stubs/core.pyi +++ b/construct-stubs/core.pyi @@ -800,6 +800,8 @@ def If( ) -> IfThenElse[t.Optional[ThenParsedType], t.Optional[ThenBuildTypes]]: ... SwitchType = t.TypeVar("SwitchType") +SwitchParsedType = t.TypeVar("SwitchParsedType") +SwitchBuildTypes = t.TypeVar("SwitchBuildTypes") class Switch(Construct[ParsedType, BuildTypes]): keyfunc: ConstantOrContextLambda[t.Any] @@ -807,18 +809,25 @@ class Switch(Construct[ParsedType, BuildTypes]): default: Construct[t.Any, t.Any] @t.overload def __new__( - cls: "type[Switch[int, t.Optional[int]]]", + cls: "type[Switch[SwitchParsedType | None, SwitchBuildTypes | None]]", keyfunc: ConstantOrContextLambda[SwitchType], - cases: t.Dict[SwitchType, Construct[int, int]], - default: t.Optional[Construct[int, int]] = ..., - ) -> Switch[int, t.Optional[int]]: ... + cases: dict[t.Any, Construct[SwitchParsedType, SwitchBuildTypes]], + default: None = ..., + ) -> Switch[SwitchParsedType | None, SwitchBuildTypes | None]: ... @t.overload def __new__( - cls: "type[Switch[t.Any, t.Any]]", - keyfunc: ConstantOrContextLambda[t.Any], - cases: t.Dict[t.Any, Construct[t.Any, t.Any]], - default: t.Optional[Construct[t.Any, t.Any]] = ..., - ) -> Switch[t.Any, t.Any]: ... + cls: "type[Switch[SwitchParsedType, SwitchBuildTypes]]", + keyfunc: ConstantOrContextLambda[SwitchType], + cases: dict[t.Any, Construct[SwitchParsedType, SwitchBuildTypes]], + default: Construct[SwitchParsedType, SwitchBuildTypes], + ) -> Switch[SwitchParsedType, SwitchBuildTypes]: ... + # @t.overload + # def __new__( + # cls: "type[Switch[t.Any, t.Any]]", + # keyfunc: ConstantOrContextLambda[t.Any], + # cases: t.Dict[t.Any, Construct[t.Any, t.Any]], + # default: t.Optional[Construct[t.Any, t.Any]] = ..., + # ) -> Switch[t.Any, t.Any]: ... class StopIf(Construct[None, None]): condfunc: ConstantOrContextLambda[bool] diff --git a/construct_typed/__init__.py b/construct_typed/__init__.py index 9ea0ccf..f594f2b 100644 --- a/construct_typed/__init__.py +++ b/construct_typed/__init__.py @@ -9,15 +9,19 @@ from .dataclass_struct import ( TStructField, csfield, sfield, + EnhancedDataclassMixin ) from .generic_wrapper import ( Adapter, ConstantOrContextLambda, + ConstantOrContextLambda2, Construct, Context, ListContainer, PathType, - Array + Array, + Subconstruct, + Computed, ) from .tenum import EnumBase, EnumValue, FlagsEnumBase, TEnum, TFlagsEnum @@ -32,6 +36,7 @@ __all__ = [ "TStructField", "csfield", "sfield", + "EnhancedDataclassMixin", "EnumBase", "EnumValue", "FlagsEnumBase", @@ -39,9 +44,12 @@ __all__ = [ "TFlagsEnum", "Adapter", "ConstantOrContextLambda", + "ConstantOrContextLambda2", "Construct", "Context", "ListContainer", "PathType", - "Array" + "Array", + "Subconstruct", + "Computed" ] diff --git a/construct_typed/dataclass_struct.py b/construct_typed/dataclass_struct.py index e6ca2e8..e626085 100644 --- a/construct_typed/dataclass_struct.py +++ b/construct_typed/dataclass_struct.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # pyright: strict +# pyright: reportIncompatibleVariableOverride=false, reportAny=false import dataclasses import textwrap import typing as t @@ -11,6 +12,7 @@ from construct.lib.containers import ( recursion_lock, ) from construct.lib.py3compat import bytestringtype, reprstring, unicodestringtype +from typing_extensions import override from .generic_wrapper import Adapter, Construct, Context, ParsedType, PathType @@ -27,7 +29,7 @@ class DataclassMixin: methods exists and every name can be used. """ - __dataclass_fields__: "t.ClassVar[t.Dict[str, dataclasses.Field[t.Any]]]" + __dataclass_fields__: "t.ClassVar[dict[str, dataclasses.Field[t.Any]]]" def __getitem__(self, key: str) -> t.Any: return getattr(self, key) @@ -77,8 +79,8 @@ class DataclassMixin: def csfield( subcon: Construct[ParsedType, t.Any], - doc: t.Optional[str] = None, - parsed: t.Optional[t.Callable[[t.Any, Context], None]] = None, + doc: str | None = None, + parsed: t.Callable[[t.Any, Context], None] | None = None, ) -> ParsedType: """ Helper method for "DataclassStruct" and "DataclassBitStruct" to create the dataclass fields. @@ -155,15 +157,11 @@ class DataclassStruct(Adapter[t.Any, t.Any, DataclassType, DataclassType]): subcon: "cs.Struct" # type: ignore def __init__( self, - dc_type: t.Type[DataclassType], + dc_type: type[DataclassType], reverse: bool = False, ) -> None: - if not issubclass(dc_type, DataclassMixin): # type: ignore - 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 + self.dc_type: type[DataclassType] = dc_type + self.reverse: bool = reverse # get all fields from the dataclass fields = dataclasses.fields(self.dc_type) @@ -171,7 +169,7 @@ class DataclassStruct(Adapter[t.Any, t.Any, DataclassType, DataclassType]): fields = tuple(reversed(fields)) # extract the construct formats from the struct_type - subcon_fields = {} + subcon_fields: dict[str, t.Any] = {} for field in fields: subcon_fields[field.name] = field.metadata["subcon"] @@ -181,6 +179,7 @@ class DataclassStruct(Adapter[t.Any, t.Any, DataclassType, DataclassType]): def __getattr__(self, name: str) -> t.Any: return getattr(self.subcon, name) + @override def _decode( self, obj: "cs.Container[t.Any]", context: Context, path: PathType ) -> DataclassType: @@ -205,9 +204,10 @@ class DataclassStruct(Adapter[t.Any, t.Any, DataclassType, DataclassType]): return dc # type: ignore + @override def _encode( self, obj: DataclassType, context: Context, path: PathType - ) -> t.Dict[str, t.Any]: + ) -> dict[str, t.Any]: if not isinstance(obj, self.dc_type): raise TypeError(f"'{repr(obj)}' has to be of type {repr(self.dc_type)}") @@ -215,20 +215,16 @@ class DataclassStruct(Adapter[t.Any, t.Any, DataclassType, DataclassType]): fields = dataclasses.fields(self.dc_type) # extract all fields from the container, that are used for create the dataclass object - ret_dict: t.Dict[str, t.Any] = {} + ret_dict: dict[str, t.Any] = {} for field in fields: value = getattr(obj, field.name) ret_dict[field.name] = value return ret_dict - def DataclassBitStruct( - dc_type: t.Type[DataclassType], reverse: bool = False -) -> t.Union[ - "cs.Transformed[DataclassType, DataclassType]", - "cs.Restreamed[DataclassType, DataclassType]", -]: + dc_type: type[DataclassType], reverse: bool = False +) -> "cs.Transformed[DataclassType, DataclassType] | cs.Restreamed[DataclassType, DataclassType]": r""" Makes a DataclassStruct inside a Bitwise. @@ -255,6 +251,29 @@ def DataclassBitStruct( """ 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 TStruct = DataclassStruct diff --git a/construct_typed/generic_wrapper.py b/construct_typed/generic_wrapper.py index 742c267..cd4788b 100644 --- a/construct_typed/generic_wrapper.py +++ b/construct_typed/generic_wrapper.py @@ -12,12 +12,14 @@ if t.TYPE_CHECKING: # 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 ConstantOrContextLambda as ConstantOrContextLambda + from construct import ConstantOrContextLambda2 as ConstantOrContextLambda2 from construct import Construct as Construct from construct import Context as Context from construct import ListContainer as ListContainer from construct import PathType as PathType from construct import Array as Array - + from construct import Subconstruct as Subconstruct + from construct import Computed as Computed else: import construct as cs @@ -44,5 +46,12 @@ else: ): 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]] + ConstantOrContextLambda2 = t.Union[ValueType, t.Callable[[Context], ValueType]] PathType = str diff --git a/construct_typed/tenum.py b/construct_typed/tenum.py index 4ae6c03..4417c6b 100644 --- a/construct_typed/tenum.py +++ b/construct_typed/tenum.py @@ -1,9 +1,10 @@ +# pyright: reportAny=false import enum import typing as t -from typing_extensions import Self +from typing_extensions import Self, override -from .generic_wrapper import * +from .generic_wrapper import Construct, Adapter, Context, PathType # ## TEnum ############################################################################################################ @@ -12,8 +13,8 @@ class EnumValue: This is a helper class for adding documentation to an enum value. """ - def __init__(self, value: int, doc: t.Optional[str] = None) -> None: - self.value = value + def __init__(self, value: int, doc: str | None = None) -> None: + self.value: int = value self.__doc__ = doc if doc else "" @@ -47,7 +48,7 @@ class EnumBase(enum.IntEnum): 'This is the running state.' """ - def __new__(cls, val: t.Union[EnumValue, int]) -> "Self": + def __new__(cls, val: EnumValue | int) -> "Self": if isinstance(val, EnumValue): obj = int.__new__(cls, val.value) obj._value_ = val.value @@ -62,7 +63,8 @@ class EnumBase(enum.IntEnum): # not found in the enum, a new pseudo member is created. # The idea is taken from: https://stackoverflow.com/a/57179436 @classmethod - def _missing_(cls, value: t.Any) -> t.Optional[enum.Enum]: + @override + def _missing_(cls, value: t.Any) -> enum.Enum | None: if isinstance(value, int): pseudo_member = cls._value2member_map_.get(value, None) if pseudo_member is None: @@ -76,7 +78,8 @@ class EnumBase(enum.IntEnum): return pseudo_member return None # will raise the ValueError in Enum.__new__ - def __reduce_ex__(self, proto: t.Any) -> t.Tuple[t.Any, ...]: + @override + def __reduce_ex__(self, proto: t.Any) -> tuple[t.Any, ...]: """ Pickle enums by value instead of name (restores pre-3.11 behavior). See https://github.com/python/cpython/pull/26658 for why this exists. @@ -91,21 +94,18 @@ class TEnum(Adapter[int, int, EnumType, EnumType]): """ Typed enum. """ - 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)) - ) - + def __init__(self, subcon: Construct[int, int], enum_type: type[EnumType]): # save enum type - self.enum_type = t.cast(t.Type[EnumType], enum_type) # type: ignore + self.enum_type: type[EnumType] = enum_type # init adatper super(TEnum, self).__init__(subcon) # type: ignore + @override def _decode(self, obj: int, context: Context, path: PathType) -> EnumType: return self.enum_type(obj) + @override def _encode( self, obj: EnumType, @@ -152,7 +152,7 @@ class FlagsEnumBase(enum.IntFlag): 'This is option two.' """ - def __new__(cls, val: t.Union[EnumValue, int]) -> "Self": + def __new__(cls, val: EnumValue | int) -> "Self": if isinstance(val, EnumValue): obj = int.__new__(cls, val.value) obj._value_ = val.value @@ -164,6 +164,7 @@ class FlagsEnumBase(enum.IntFlag): return obj @classmethod + @override def _missing_(cls, value: t.Any) -> t.Any: """ Returns member (possibly creating it) if one can be found for value. @@ -172,7 +173,8 @@ class FlagsEnumBase(enum.IntFlag): new_member.__doc__ = "missing value" return new_member - def __reduce_ex__(self, proto: t.Any) -> t.Tuple[t.Any, ...]: + @override + def __reduce_ex__(self, proto: t.Any) -> tuple[t.Any, ...]: """ Pickle enums by value instead of name (restores pre-3.11 behavior). See https://github.com/python/cpython/pull/26658 for why this exists. @@ -187,21 +189,18 @@ class TFlagsEnum(Adapter[int, int, FlagsEnumType, FlagsEnumType]): """ Typed enum. """ - 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)) - ) - + def __init__(self, subcon: Construct[int, int], enum_type: type[FlagsEnumType]): # save enum type - self.enum_type = t.cast(t.Type[FlagsEnumType], enum_type) # type: ignore + self.enum_type: type[FlagsEnumType] = enum_type # init adatper super(TFlagsEnum, self).__init__(subcon) # type: ignore + @override def _decode(self, obj: int, context: Context, path: PathType) -> FlagsEnumType: return self.enum_type(obj) + @override def _encode( self, obj: FlagsEnumType, diff --git a/construct_typed/version.py b/construct_typed/version.py index 04fbf4c..38a2845 100644 --- a/construct_typed/version.py +++ b/construct_typed/version.py @@ -1,2 +1,2 @@ version = (0, 7, 0) -version_string = "0.7.0" +version_string = "0.7.0+wrapper" From 2f078b340bbb510d647ce69bec5b5ce13e181df8 Mon Sep 17 00:00:00 2001 From: wrapper Date: Tue, 7 Apr 2026 19:02:24 +0700 Subject: [PATCH 4/7] more switch fixes --- README.md | 1 + construct-stubs/core.pyi | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d95463b..73d2f1d 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ This modification features: - **ConstantOrContextLambda2 type** - **Typing for Subconstruct** - **Type hint for Computed** +- **Switch typing fixes** The original README.md file was described down below: # construct-typing diff --git a/construct-stubs/core.pyi b/construct-stubs/core.pyi index 59f482e..3792b96 100644 --- a/construct-stubs/core.pyi +++ b/construct-stubs/core.pyi @@ -802,6 +802,8 @@ def If( 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]): keyfunc: ConstantOrContextLambda[t.Any] @@ -816,11 +818,11 @@ class Switch(Construct[ParsedType, BuildTypes]): ) -> Switch[SwitchParsedType | None, SwitchBuildTypes | None]: ... @t.overload def __new__( - cls: "type[Switch[SwitchParsedType, SwitchBuildTypes]]", + cls: "type[Switch[SwitchParsedType | SwitchDefaultParsedType, SwitchBuildTypes | SwitchDefaultBuildTypes]]", keyfunc: ConstantOrContextLambda[SwitchType], cases: dict[t.Any, Construct[SwitchParsedType, SwitchBuildTypes]], - default: Construct[SwitchParsedType, SwitchBuildTypes], - ) -> Switch[SwitchParsedType, SwitchBuildTypes]: ... + default: Construct[SwitchDefaultParsedType, SwitchDefaultBuildTypes], + ) -> Switch[SwitchParsedType | SwitchDefaultParsedType, SwitchBuildTypes | SwitchDefaultBuildTypes]: ... # @t.overload # def __new__( # cls: "type[Switch[t.Any, t.Any]]", From c1896ab8dcb96bab8900269a8b706ed0e94591b2 Mon Sep 17 00:00:00 2001 From: wrapper Date: Tue, 7 Apr 2026 19:25:45 +0700 Subject: [PATCH 5/7] Construct Error class does not return --- construct-stubs/core.pyi | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/construct-stubs/core.pyi b/construct-stubs/core.pyi index 3792b96..4bee6b5 100644 --- a/construct-stubs/core.pyi +++ b/construct-stubs/core.pyi @@ -622,7 +622,7 @@ class Check(Construct[None, None]): func: ConstantOrContextLambda[bool], ) -> None: ... -Error: Construct[None, None] +Error: Construct[t.NoReturn, t.NoReturn] class FocusedSeq(Construct[t.Any, t.Any]): subcons: t.List[Construct[t.Any, t.Any]] @@ -817,6 +817,13 @@ class Switch(Construct[ParsedType, BuildTypes]): default: None = ..., ) -> Switch[SwitchParsedType | None, SwitchBuildTypes | None]: ... @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], From 0a4628935b6d279649114cfc1c632a90a785907a Mon Sep 17 00:00:00 2001 From: wrapper Date: Tue, 7 Apr 2026 20:19:38 +0700 Subject: [PATCH 6/7] add --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 73d2f1d..c4bac18 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Modified version of "construct-typing" module used in my projects. This modification features: -- **[EnhancedDataclassMixin](https://github.com/waszil/construct-typing/commit/479b51344bfd95149596a75ee574ac2e63c032df)** +- **[EnhancedDataclassMixin](https://github.com/waszil/construct-typing/commit/479b51344bfd95149596a75ee574ac2e63c032df) with additional features** - **ConstantOrContextLambda2 type** - **Typing for Subconstruct** - **Type hint for Computed** From 486c553d6576ee38200f4b32df387c00e9d05db7 Mon Sep 17 00:00:00 2001 From: wrapper Date: Tue, 7 Apr 2026 23:28:33 +0700 Subject: [PATCH 7/7] fallback switch --- construct-stubs/core.pyi | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/construct-stubs/core.pyi b/construct-stubs/core.pyi index 4bee6b5..7ed1af6 100644 --- a/construct-stubs/core.pyi +++ b/construct-stubs/core.pyi @@ -830,13 +830,13 @@ class Switch(Construct[ParsedType, BuildTypes]): cases: dict[t.Any, Construct[SwitchParsedType, SwitchBuildTypes]], default: Construct[SwitchDefaultParsedType, SwitchDefaultBuildTypes], ) -> Switch[SwitchParsedType | SwitchDefaultParsedType, SwitchBuildTypes | SwitchDefaultBuildTypes]: ... - # @t.overload - # def __new__( - # cls: "type[Switch[t.Any, t.Any]]", - # keyfunc: ConstantOrContextLambda[t.Any], - # cases: t.Dict[t.Any, Construct[t.Any, t.Any]], - # default: t.Optional[Construct[t.Any, t.Any]] = ..., - # ) -> Switch[t.Any, t.Any]: ... + @t.overload + def __new__( + cls: "type[Switch[t.Any, t.Any]]", + keyfunc: ConstantOrContextLambda[SwitchType], + cases: dict[t.Any, Construct[t.Any, t.Any]], + default: Construct[t.Any, t.Any] | None = ..., + ) -> Switch[t.Any, t.Any]: ... class StopIf(Construct[None, None]): condfunc: ConstantOrContextLambda[bool]