From dbd0903d1be34f10657a140405d7e8864000f425 Mon Sep 17 00:00:00 2001 From: Mal Curtis Date: Sun, 4 Aug 2024 04:03:22 +0000 Subject: [PATCH 1/9] Add prefixed enums in addition to pretty ones --- src/betterproto/plugin/models.py | 25 ++++++++++++++++++------- tests/inputs/enum/test_enum.py | 4 ++++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/betterproto/plugin/models.py b/src/betterproto/plugin/models.py index cf14cadb4..91996a13a 100644 --- a/src/betterproto/plugin/models.py +++ b/src/betterproto/plugin/models.py @@ -79,6 +79,7 @@ DirectImportTypingCompiler, TypingCompiler, ) +from ..casing import sanitize_name # Create a unique placeholder to deal with @@ -660,18 +661,28 @@ class EnumEntry: def __post_init__(self) -> None: # Get entries/allowed values for this Enum - self.entries = [ - self.EnumEntry( - name=pythonize_enum_member_name( - entry_proto_value.name, self.proto_obj.name - ), + self.entries: List[self.EnumEntry] = [] + for entry_number, entry_proto_value in enumerate(self.proto_obj.value): + pythonized_name = pythonize_enum_member_name( + entry_proto_value.name, self.proto_obj.name + ) + name = sanitize_name(entry_proto_value.name) + entry = self.EnumEntry( + name=pythonized_name, value=entry_proto_value.number, comment=get_comment( proto_file=self.source_file, path=self.path + [2, entry_number] ), ) - for entry_number, entry_proto_value in enumerate(self.proto_obj.value) - ] + self.entries.append(entry) + if name != pythonized_name: + self.entries.append( + self.EnumEntry( + name=name, + value=entry_proto_value.number, + comment=entry.comment, + ) + ) super().__post_init__() # call MessageCompiler __post_init__ @property diff --git a/tests/inputs/enum/test_enum.py b/tests/inputs/enum/test_enum.py index 21a5ac3b9..682ef68d5 100644 --- a/tests/inputs/enum/test_enum.py +++ b/tests/inputs/enum/test_enum.py @@ -111,4 +111,8 @@ def test_renamed_enum_members(): "PLUS", "MINUS", "_0_PREFIXED", + "ARITHMETIC_OPERATOR_NONE", + "ARITHMETIC_OPERATOR_PLUS", + "ARITHMETIC_OPERATOR_MINUS", + "ARITHMETIC_OPERATOR_0_PREFIXED", } From 8e9b9b2e8499f32394ca638b36c530b3b632f55e Mon Sep 17 00:00:00 2001 From: Mal Curtis Date: Mon, 5 Aug 2024 04:12:56 +0000 Subject: [PATCH 2/9] Use a lookup map for full name --- src/betterproto/plugin/models.py | 30 +++++++++--------------- src/betterproto/templates/template.py.j2 | 8 +++++++ tests/inputs/enum/test_enum.py | 15 ++++-------- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/betterproto/plugin/models.py b/src/betterproto/plugin/models.py index 91996a13a..4c8b8eb7d 100644 --- a/src/betterproto/plugin/models.py +++ b/src/betterproto/plugin/models.py @@ -662,27 +662,19 @@ class EnumEntry: def __post_init__(self) -> None: # Get entries/allowed values for this Enum self.entries: List[self.EnumEntry] = [] - for entry_number, entry_proto_value in enumerate(self.proto_obj.value): - pythonized_name = pythonize_enum_member_name( - entry_proto_value.name, self.proto_obj.name - ) - name = sanitize_name(entry_proto_value.name) - entry = self.EnumEntry( - name=pythonized_name, - value=entry_proto_value.number, + self.entries = [ + self.EnumEntry( + name=pythonize_enum_member_name( + entry.name, self.proto_obj.name), + full_name=sanitize_name(entry.name), + value=entry.number, comment=get_comment( - proto_file=self.source_file, path=self.path + [2, entry_number] - ), - ) - self.entries.append(entry) - if name != pythonized_name: - self.entries.append( - self.EnumEntry( - name=name, - value=entry_proto_value.number, - comment=entry.comment, - ) + proto_file=self.source_file, + path=self.path + [2, i] ) + ) + for i, entry in enumerate(self.proto_obj.value) + ] super().__post_init__() # call MessageCompiler __post_init__ @property diff --git a/src/betterproto/templates/template.py.j2 b/src/betterproto/templates/template.py.j2 index 24c927cfc..371aec458 100644 --- a/src/betterproto/templates/template.py.j2 +++ b/src/betterproto/templates/template.py.j2 @@ -20,6 +20,14 @@ class {{ enum.py_name }}(betterproto.Enum): return core_schema.int_schema(ge=0) {% endif %} + def full_name(self): + return {{ enum.py_name }}_full_name_map[self.value] + +{{ enum.py_name }}_full_name_map = { +{% for entry in enum.entries %} + {{ entry.value }}: "{{ entry.full_name }}", +{% endfor %} +} {% endfor %} {% endif %} {% for message in output_file.messages %} diff --git a/tests/inputs/enum/test_enum.py b/tests/inputs/enum/test_enum.py index 682ef68d5..0441b5d78 100644 --- a/tests/inputs/enum/test_enum.py +++ b/tests/inputs/enum/test_enum.py @@ -105,14 +105,7 @@ def test_enum_mapped_on_parse(): assert Test().choice.name == Choice.ZERO.name -def test_renamed_enum_members(): - assert set(ArithmeticOperator.__members__) == { - "NONE", - "PLUS", - "MINUS", - "_0_PREFIXED", - "ARITHMETIC_OPERATOR_NONE", - "ARITHMETIC_OPERATOR_PLUS", - "ARITHMETIC_OPERATOR_MINUS", - "ARITHMETIC_OPERATOR_0_PREFIXED", - } +def test_enum_full_name(): + assert ArithmeticOperator.NONE.full_name() == "ARITHMETIC_OPERATOR_NONE" + assert ArithmeticOperator.PLUS.full_name() == "ARITHMETIC_OPERATOR_PLUS" + assert ArithmeticOperator._0_PREFIXED.full_name() == "ARITHMETIC_OPERATOR_0_PREFIXED" From 30a52714a4f417e27de62a983264165d18e51366 Mon Sep 17 00:00:00 2001 From: Mal Curtis Date: Mon, 5 Aug 2024 04:14:03 +0000 Subject: [PATCH 3/9] Revert --- src/betterproto/plugin/models.py | 30 +++++++++++++++--------- src/betterproto/templates/template.py.j2 | 8 ------- tests/inputs/enum/test_enum.py | 15 ++++++++---- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/betterproto/plugin/models.py b/src/betterproto/plugin/models.py index 4c8b8eb7d..91996a13a 100644 --- a/src/betterproto/plugin/models.py +++ b/src/betterproto/plugin/models.py @@ -662,19 +662,27 @@ class EnumEntry: def __post_init__(self) -> None: # Get entries/allowed values for this Enum self.entries: List[self.EnumEntry] = [] - self.entries = [ - self.EnumEntry( - name=pythonize_enum_member_name( - entry.name, self.proto_obj.name), - full_name=sanitize_name(entry.name), - value=entry.number, + for entry_number, entry_proto_value in enumerate(self.proto_obj.value): + pythonized_name = pythonize_enum_member_name( + entry_proto_value.name, self.proto_obj.name + ) + name = sanitize_name(entry_proto_value.name) + entry = self.EnumEntry( + name=pythonized_name, + value=entry_proto_value.number, comment=get_comment( - proto_file=self.source_file, - path=self.path + [2, i] - ) + proto_file=self.source_file, path=self.path + [2, entry_number] + ), ) - for i, entry in enumerate(self.proto_obj.value) - ] + self.entries.append(entry) + if name != pythonized_name: + self.entries.append( + self.EnumEntry( + name=name, + value=entry_proto_value.number, + comment=entry.comment, + ) + ) super().__post_init__() # call MessageCompiler __post_init__ @property diff --git a/src/betterproto/templates/template.py.j2 b/src/betterproto/templates/template.py.j2 index 371aec458..24c927cfc 100644 --- a/src/betterproto/templates/template.py.j2 +++ b/src/betterproto/templates/template.py.j2 @@ -20,14 +20,6 @@ class {{ enum.py_name }}(betterproto.Enum): return core_schema.int_schema(ge=0) {% endif %} - def full_name(self): - return {{ enum.py_name }}_full_name_map[self.value] - -{{ enum.py_name }}_full_name_map = { -{% for entry in enum.entries %} - {{ entry.value }}: "{{ entry.full_name }}", -{% endfor %} -} {% endfor %} {% endif %} {% for message in output_file.messages %} diff --git a/tests/inputs/enum/test_enum.py b/tests/inputs/enum/test_enum.py index 0441b5d78..682ef68d5 100644 --- a/tests/inputs/enum/test_enum.py +++ b/tests/inputs/enum/test_enum.py @@ -105,7 +105,14 @@ def test_enum_mapped_on_parse(): assert Test().choice.name == Choice.ZERO.name -def test_enum_full_name(): - assert ArithmeticOperator.NONE.full_name() == "ARITHMETIC_OPERATOR_NONE" - assert ArithmeticOperator.PLUS.full_name() == "ARITHMETIC_OPERATOR_PLUS" - assert ArithmeticOperator._0_PREFIXED.full_name() == "ARITHMETIC_OPERATOR_0_PREFIXED" +def test_renamed_enum_members(): + assert set(ArithmeticOperator.__members__) == { + "NONE", + "PLUS", + "MINUS", + "_0_PREFIXED", + "ARITHMETIC_OPERATOR_NONE", + "ARITHMETIC_OPERATOR_PLUS", + "ARITHMETIC_OPERATOR_MINUS", + "ARITHMETIC_OPERATOR_0_PREFIXED", + } From beaa87397de51e4938e440525522a1ff704bc50f Mon Sep 17 00:00:00 2001 From: Mal Curtis Date: Mon, 5 Aug 2024 04:14:11 +0000 Subject: [PATCH 4/9] Revert --- src/betterproto/plugin/models.py | 25 +++++++------------------ tests/inputs/enum/test_enum.py | 4 ---- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/betterproto/plugin/models.py b/src/betterproto/plugin/models.py index 91996a13a..cf14cadb4 100644 --- a/src/betterproto/plugin/models.py +++ b/src/betterproto/plugin/models.py @@ -79,7 +79,6 @@ DirectImportTypingCompiler, TypingCompiler, ) -from ..casing import sanitize_name # Create a unique placeholder to deal with @@ -661,28 +660,18 @@ class EnumEntry: def __post_init__(self) -> None: # Get entries/allowed values for this Enum - self.entries: List[self.EnumEntry] = [] - for entry_number, entry_proto_value in enumerate(self.proto_obj.value): - pythonized_name = pythonize_enum_member_name( - entry_proto_value.name, self.proto_obj.name - ) - name = sanitize_name(entry_proto_value.name) - entry = self.EnumEntry( - name=pythonized_name, + self.entries = [ + self.EnumEntry( + name=pythonize_enum_member_name( + entry_proto_value.name, self.proto_obj.name + ), value=entry_proto_value.number, comment=get_comment( proto_file=self.source_file, path=self.path + [2, entry_number] ), ) - self.entries.append(entry) - if name != pythonized_name: - self.entries.append( - self.EnumEntry( - name=name, - value=entry_proto_value.number, - comment=entry.comment, - ) - ) + for entry_number, entry_proto_value in enumerate(self.proto_obj.value) + ] super().__post_init__() # call MessageCompiler __post_init__ @property diff --git a/tests/inputs/enum/test_enum.py b/tests/inputs/enum/test_enum.py index 682ef68d5..21a5ac3b9 100644 --- a/tests/inputs/enum/test_enum.py +++ b/tests/inputs/enum/test_enum.py @@ -111,8 +111,4 @@ def test_renamed_enum_members(): "PLUS", "MINUS", "_0_PREFIXED", - "ARITHMETIC_OPERATOR_NONE", - "ARITHMETIC_OPERATOR_PLUS", - "ARITHMETIC_OPERATOR_MINUS", - "ARITHMETIC_OPERATOR_0_PREFIXED", } From c07d5b06e56b9df23392072474612091ef30ad3a Mon Sep 17 00:00:00 2001 From: Mal Curtis Date: Mon, 5 Aug 2024 04:15:17 +0000 Subject: [PATCH 5/9] Use a lookup map for full name --- src/betterproto/templates/template.py.j2 | 8 ++++++++ tests/inputs/enum/test_enum.py | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/betterproto/templates/template.py.j2 b/src/betterproto/templates/template.py.j2 index 24c927cfc..371aec458 100644 --- a/src/betterproto/templates/template.py.j2 +++ b/src/betterproto/templates/template.py.j2 @@ -20,6 +20,14 @@ class {{ enum.py_name }}(betterproto.Enum): return core_schema.int_schema(ge=0) {% endif %} + def full_name(self): + return {{ enum.py_name }}_full_name_map[self.value] + +{{ enum.py_name }}_full_name_map = { +{% for entry in enum.entries %} + {{ entry.value }}: "{{ entry.full_name }}", +{% endfor %} +} {% endfor %} {% endif %} {% for message in output_file.messages %} diff --git a/tests/inputs/enum/test_enum.py b/tests/inputs/enum/test_enum.py index 21a5ac3b9..2a0353a29 100644 --- a/tests/inputs/enum/test_enum.py +++ b/tests/inputs/enum/test_enum.py @@ -112,3 +112,9 @@ def test_renamed_enum_members(): "MINUS", "_0_PREFIXED", } + + +def test_enum_full_name(): + assert ArithmeticOperator.NONE.full_name() == "ARITHMETIC_OPERATOR_NONE" + assert ArithmeticOperator.PLUS.full_name() == "ARITHMETIC_OPERATOR_PLUS" + assert ArithmeticOperator._0_PREFIXED.full_name() == "ARITHMETIC_OPERATOR_0_PREFIXED" From 5a2f64c1b7424a7e32e29b133eb8c53cba501be0 Mon Sep 17 00:00:00 2001 From: Mal Curtis Date: Mon, 5 Aug 2024 04:22:55 +0000 Subject: [PATCH 6/9] Move to property --- src/betterproto/plugin/models.py | 3 +++ src/betterproto/templates/template.py.j2 | 1 + tests/inputs/enum/test_enum.py | 6 +++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/betterproto/plugin/models.py b/src/betterproto/plugin/models.py index cf14cadb4..044032375 100644 --- a/src/betterproto/plugin/models.py +++ b/src/betterproto/plugin/models.py @@ -65,6 +65,7 @@ from betterproto.lib.google.protobuf.compiler import CodeGeneratorRequest from .. import which_one_of +from ..casing import sanitize_name from ..compile.importing import ( get_type_reference, parse_source_type_name, @@ -655,6 +656,7 @@ class EnumEntry: """Representation of an Enum entry.""" name: str + full_name: str value: int comment: str @@ -665,6 +667,7 @@ def __post_init__(self) -> None: name=pythonize_enum_member_name( entry_proto_value.name, self.proto_obj.name ), + full_name=sanitize_name(entry_proto_value.name), value=entry_proto_value.number, comment=get_comment( proto_file=self.source_file, path=self.path + [2, entry_number] diff --git a/src/betterproto/templates/template.py.j2 b/src/betterproto/templates/template.py.j2 index 371aec458..92e389a8b 100644 --- a/src/betterproto/templates/template.py.j2 +++ b/src/betterproto/templates/template.py.j2 @@ -20,6 +20,7 @@ class {{ enum.py_name }}(betterproto.Enum): return core_schema.int_schema(ge=0) {% endif %} + @property def full_name(self): return {{ enum.py_name }}_full_name_map[self.value] diff --git a/tests/inputs/enum/test_enum.py b/tests/inputs/enum/test_enum.py index 2a0353a29..4e0dfac76 100644 --- a/tests/inputs/enum/test_enum.py +++ b/tests/inputs/enum/test_enum.py @@ -115,6 +115,6 @@ def test_renamed_enum_members(): def test_enum_full_name(): - assert ArithmeticOperator.NONE.full_name() == "ARITHMETIC_OPERATOR_NONE" - assert ArithmeticOperator.PLUS.full_name() == "ARITHMETIC_OPERATOR_PLUS" - assert ArithmeticOperator._0_PREFIXED.full_name() == "ARITHMETIC_OPERATOR_0_PREFIXED" + assert ArithmeticOperator.NONE.full_name == "ARITHMETIC_OPERATOR_NONE" + assert ArithmeticOperator.PLUS.full_name == "ARITHMETIC_OPERATOR_PLUS" + assert ArithmeticOperator._0_PREFIXED.full_name == "ARITHMETIC_OPERATOR_0_PREFIXED" From 6b80b2aff707486e8f46976fa001f3388efe3d2b Mon Sep 17 00:00:00 2001 From: Mal Curtis Date: Mon, 5 Aug 2024 04:38:40 +0000 Subject: [PATCH 7/9] Add json output --- src/betterproto/__init__.py | 14 ++++++++++---- tests/inputs/enum/enum.proto | 1 + tests/inputs/enum/test_enum.py | 8 ++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/betterproto/__init__.py b/src/betterproto/__init__.py index 050f41435..6bd8d0a27 100644 --- a/src/betterproto/__init__.py +++ b/src/betterproto/__init__.py @@ -1493,24 +1493,30 @@ def to_dict( else: output[cased_name] = b64encode(value).decode("utf8") elif meta.proto_type == TYPE_ENUM: + def name(enum_class, value): + obj = enum_class(value) + if hasattr(obj.__class__, 'full_name') and isinstance(obj.__class__.full_name, property): + return obj.full_name + return obj.name if field_is_repeated: enum_class = field_types[field_name].__args__[0] if isinstance(value, typing.Iterable) and not isinstance( value, str ): - output[cased_name] = [enum_class(el).name for el in value] + output[cased_name] = [ + name(enum_class, el) for el in value] else: # transparently upgrade single value to repeated - output[cased_name] = [enum_class(value).name] + output[cased_name] = [name(enum_class, 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] = name(enum_class, value) else: enum_class = field_types[field_name] # noqa - output[cased_name] = enum_class(value).name + output[cased_name] = name(enum_class, value) elif meta.proto_type in (TYPE_FLOAT, TYPE_DOUBLE): if field_is_repeated: output[cased_name] = [_dump_float(n) for n in value] diff --git a/tests/inputs/enum/enum.proto b/tests/inputs/enum/enum.proto index 5e2e80c1f..073f2e061 100644 --- a/tests/inputs/enum/enum.proto +++ b/tests/inputs/enum/enum.proto @@ -6,6 +6,7 @@ package enum; message Test { Choice choice = 1; repeated Choice choices = 2; + ArithmeticOperator op = 3; } enum Choice { diff --git a/tests/inputs/enum/test_enum.py b/tests/inputs/enum/test_enum.py index 4e0dfac76..f8e6f3420 100644 --- a/tests/inputs/enum/test_enum.py +++ b/tests/inputs/enum/test_enum.py @@ -118,3 +118,11 @@ def test_enum_full_name(): assert ArithmeticOperator.NONE.full_name == "ARITHMETIC_OPERATOR_NONE" assert ArithmeticOperator.PLUS.full_name == "ARITHMETIC_OPERATOR_PLUS" assert ArithmeticOperator._0_PREFIXED.full_name == "ARITHMETIC_OPERATOR_0_PREFIXED" + + +def test_enum_to_json(): + assert Test(op=ArithmeticOperator.NONE).to_json() == '{}' + assert Test(op=ArithmeticOperator.PLUS).to_json( + ) == '{"op": "ARITHMETIC_OPERATOR_PLUS"}' + assert Test(op=ArithmeticOperator._0_PREFIXED).to_json( + ) == '{"op": "ARITHMETIC_OPERATOR_0_PREFIXED"}' From 675e71b706d64b37b576ea87dc598b7eddfe0ffb Mon Sep 17 00:00:00 2001 From: Mal Curtis Date: Mon, 5 Aug 2024 04:41:52 +0000 Subject: [PATCH 8/9] Add backwards compat test --- tests/inputs/enum/test_enum.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/inputs/enum/test_enum.py b/tests/inputs/enum/test_enum.py index f8e6f3420..6703818a8 100644 --- a/tests/inputs/enum/test_enum.py +++ b/tests/inputs/enum/test_enum.py @@ -1,3 +1,6 @@ +import betterproto +from dataclasses import dataclass + from tests.output_betterproto.enum import ( ArithmeticOperator, Choice, @@ -126,3 +129,22 @@ def test_enum_to_json(): ) == '{"op": "ARITHMETIC_OPERATOR_PLUS"}' assert Test(op=ArithmeticOperator._0_PREFIXED).to_json( ) == '{"op": "ARITHMETIC_OPERATOR_0_PREFIXED"}' + + +class EnumCompat(betterproto.Enum): + NONE = 0 + PLUS = 1 + MINUS = 2 + + +@dataclass(eq=False, repr=False) +class CompatTest(betterproto.Message): + enum: "EnumCompat" = betterproto.enum_field(1) + + +def test_enum_to_json_backwards_compat(): + assert CompatTest(enum=EnumCompat.NONE).to_json() == '{}' + assert CompatTest(enum=EnumCompat.PLUS).to_json( + ) == '{"enum": "PLUS"}' + assert CompatTest(enum=EnumCompat.MINUS).to_json( + ) == '{"enum": "MINUS"}' From 9f928de98d763f9b8db27cf77d6f7896d12ba964 Mon Sep 17 00:00:00 2001 From: Mal Curtis Date: Mon, 5 Aug 2024 04:56:42 +0000 Subject: [PATCH 9/9] Handle from_json --- src/betterproto/__init__.py | 7 +++++-- src/betterproto/templates/template.py.j2 | 11 +++++++++++ tests/inputs/enum/test_enum.py | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/betterproto/__init__.py b/src/betterproto/__init__.py index 6bd8d0a27..816ffe2c7 100644 --- a/src/betterproto/__init__.py +++ b/src/betterproto/__init__.py @@ -1576,10 +1576,13 @@ def _from_dict_init(cls, mapping: Mapping[str, Any]) -> Mapping[str, Any]: ) elif meta.proto_type == TYPE_ENUM: enum_cls = cls._betterproto.cls_by_field[field_name] + + def obj(enum_class, value): + return enum_class.from_full_name(value) if hasattr(enum_class, 'from_full_name') else enum_class.from_string(value) if isinstance(value, list): - value = [enum_cls.from_string(e) for e in value] + value = [obj(enum_cls, e) for e in value] elif isinstance(value, str): - value = enum_cls.from_string(value) + value = obj(enum_cls, value) elif meta.proto_type in (TYPE_FLOAT, TYPE_DOUBLE): value = ( [_parse_float(n) for n in value] diff --git a/src/betterproto/templates/template.py.j2 b/src/betterproto/templates/template.py.j2 index 92e389a8b..f05afd8b5 100644 --- a/src/betterproto/templates/template.py.j2 +++ b/src/betterproto/templates/template.py.j2 @@ -24,11 +24,22 @@ class {{ enum.py_name }}(betterproto.Enum): def full_name(self): return {{ enum.py_name }}_full_name_map[self.value] + @classmethod + def from_full_name(cls, full_name): + return cls.from_string({{ enum.py_name }}_full_name_reverse_map[full_name]) + + {{ enum.py_name }}_full_name_map = { {% for entry in enum.entries %} {{ entry.value }}: "{{ entry.full_name }}", {% endfor %} } + +{{ enum.py_name }}_full_name_reverse_map = { +{% for entry in enum.entries %} + "{{ entry.full_name }}": "{{ entry.name }}", +{% endfor %} +} {% endfor %} {% endif %} {% for message in output_file.messages %} diff --git a/tests/inputs/enum/test_enum.py b/tests/inputs/enum/test_enum.py index 6703818a8..1476d3dc2 100644 --- a/tests/inputs/enum/test_enum.py +++ b/tests/inputs/enum/test_enum.py @@ -131,6 +131,14 @@ def test_enum_to_json(): ) == '{"op": "ARITHMETIC_OPERATOR_0_PREFIXED"}' +def test_enum_from_json(): + assert Test().from_json('{}').op == ArithmeticOperator.NONE + assert Test().from_json( + '{"op": "ARITHMETIC_OPERATOR_PLUS"}').op == ArithmeticOperator.PLUS + assert Test().from_json( + '{"op": "ARITHMETIC_OPERATOR_0_PREFIXED"}').op == ArithmeticOperator._0_PREFIXED + + class EnumCompat(betterproto.Enum): NONE = 0 PLUS = 1 @@ -148,3 +156,9 @@ def test_enum_to_json_backwards_compat(): ) == '{"enum": "PLUS"}' assert CompatTest(enum=EnumCompat.MINUS).to_json( ) == '{"enum": "MINUS"}' + + +def test_enum_from_json_backwards_compat(): + assert CompatTest().from_json('{}').enum == EnumCompat.NONE + assert CompatTest().from_json('{"enum": "PLUS"}').enum == EnumCompat.PLUS + assert CompatTest().from_json('{"enum": "MINUS"}').enum == EnumCompat.MINUS