From 112a65409e788c8bd797b3921cb4c353417b93ae Mon Sep 17 00:00:00 2001 From: Maxim Agupov Date: Thu, 21 Jul 2022 11:54:39 +0200 Subject: [PATCH 1/3] type hint fix --- src/betterproto/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/betterproto/__init__.py b/src/betterproto/__init__.py index 5e514d5c1..e49d77c73 100644 --- a/src/betterproto/__init__.py +++ b/src/betterproto/__init__.py @@ -845,8 +845,11 @@ def _type_hint(cls, field_name: str) -> Type: @classmethod def _type_hints(cls) -> Dict[str, Type]: - module = sys.modules[cls.__module__] - return get_type_hints(cls, module.__dict__, {}) + global_vars = {} + for base in inspect.getmro(cls): + module = inspect.getmodule(base) + global_vars.update(vars(module)) + return get_type_hints(cls, global_vars, {}) @classmethod def _cls_for(cls, field: dataclasses.Field, index: int = 0) -> Type: From 1c5d1061e74833c71b5b78443715d9619b3446e1 Mon Sep 17 00:00:00 2001 From: Maxim Agupov Date: Thu, 21 Jul 2022 13:52:38 +0200 Subject: [PATCH 2/3] fix enum deserialization --- src/betterproto/__init__.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/betterproto/__init__.py b/src/betterproto/__init__.py index e49d77c73..abba4815b 100644 --- a/src/betterproto/__init__.py +++ b/src/betterproto/__init__.py @@ -315,6 +315,28 @@ def from_string(cls, name: str) -> "Enum": except KeyError as e: raise ValueError(f"Unknown value {name} for enum {cls.__name__}") from e + @classmethod + def from_value(cls, value: Union[int, str]) -> "Enum": + """Return the value which corresponds to the value. + + Parameters + ----------- + value: :class:`Union[int, str]` + The name or value of the enum member to get + + Raises + ------- + :exc:`ValueError` + The member was not found in the Enum. + """ + try: + if isinstance(value, str): + return cls.from_string(value) + value = int(value) + return cls(value) # type: ignore + except KeyError as e: + raise ValueError(f"Unknown value {name} for enum {cls.__name__}") from e + def _pack_fmt(proto_type: str) -> str: """Returns a little-endian format string for reading/writing binary.""" @@ -1229,9 +1251,9 @@ def from_dict(self: T, value: Dict[str, Any]) -> T: elif meta.proto_type == TYPE_ENUM: enum_cls = self._betterproto.cls_by_field[field_name] if isinstance(v, list): - v = [enum_cls.from_string(e) for e in v] - elif isinstance(v, str): - v = enum_cls.from_string(v) + v = [enum_cls.from_value(e) for e in v] + else: + v = enum_cls.from_value(v) elif meta.proto_type in (TYPE_FLOAT, TYPE_DOUBLE): if isinstance(value[key], list): v = [_parse_float(n) for n in value[key]] From af9de10191ef0d6667f9f8d86e287f627ac45de7 Mon Sep 17 00:00:00 2001 From: Maxim Agupov Date: Thu, 21 Jul 2022 18:41:36 +0200 Subject: [PATCH 3/3] fix enum serialization --- src/betterproto/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/betterproto/__init__.py b/src/betterproto/__init__.py index abba4815b..4a5b25e23 100644 --- a/src/betterproto/__init__.py +++ b/src/betterproto/__init__.py @@ -1158,19 +1158,19 @@ def to_dict( if isinstance(value, typing.Iterable) and not isinstance( value, str ): - output[cased_name] = [enum_class(el).name for el in value] + output[cased_name] = [enum_class(el).value for el in value] else: # transparently upgrade single value to repeated - output[cased_name] = [enum_class(value).name] + output[cased_name] = [enum_class(value).value] elif value is None: if include_default_values: output[cased_name] = value elif meta.optional: enum_class = field_types[field_name].__args__[0] - output[cased_name] = enum_class(value).name + output[cased_name] = enum_class(value).value else: enum_class = field_types[field_name] # noqa - output[cased_name] = enum_class(value).name + output[cased_name] = enum_class(value).value elif meta.proto_type in (TYPE_FLOAT, TYPE_DOUBLE): if field_is_repeated: output[cased_name] = [_dump_float(n) for n in value]