From f4f83c0ee087291e3e4dbffe11c8fb0f7d5dd2f4 Mon Sep 17 00:00:00 2001 From: ccp_zeulix Date: Tue, 24 Sep 2024 15:23:38 +0000 Subject: [PATCH 1/3] Version 5.3.0 - Support for Value ### Added - Support for the `google.protobuf.Value` message --- CHANGELOG.md | 8 ++++ neobuilder/__init__.py | 2 +- neobuilder/descwrap/_field.py | 47 +++++++++++++--------- neobuilder/generators/symbols/dataclass.py | 38 ++++++++++++++--- pyproject.toml | 2 +- requirements.txt | 2 +- 6 files changed, 73 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a784173..fc6b6cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [5.3.0] - 2024-09-24 + +### Added + +- Support for the `google.protobuf.Value` message + + ## [5.2.1] - 2024-09-24 ### Changed diff --git a/neobuilder/__init__.py b/neobuilder/__init__.py index 7b84400..38a5c87 100644 --- a/neobuilder/__init__.py +++ b/neobuilder/__init__.py @@ -1,4 +1,4 @@ -__version__ = '5.2.1' +__version__ = '5.3.0' __author__ = 'Thordur Matthiasson ' __license__ = 'MIT License' diff --git a/neobuilder/descwrap/_field.py b/neobuilder/descwrap/_field.py index 862ee34..1241efb 100644 --- a/neobuilder/descwrap/_field.py +++ b/neobuilder/descwrap/_field.py @@ -12,24 +12,27 @@ class FieldKind(enum.IntFlag): - UNKNOWN = 0x0000 - DATA_SCALAR = 0x0001 - DATA_MESSAGE = 0x0002 - DATA_ENUM = 0x0004 - - KIND_SINGLE = 0x0010 - KIND_LIST = 0x0020 - KIND_MAP = 0x0040 - - SPECIAL_TIMESTAMP = 0x0100 - SPECIAL_BYTES = 0x0200 - SPECIAL_LONG = 0x0400 - SPECIAL_DURATION = 0x0800 - SPECIAL_ANY = 0x1000 - SPECIAL_EMPTY = 0x2000 - SPECIAL_STRUCT = 0x4000 - - SPECIAL_KEYWORD = 0x10000000 + UNKNOWN = 0x0000 + DATA_SCALAR = 0x0001 + DATA_MESSAGE = 0x0002 + DATA_ENUM = 0x0004 + + KIND_SINGLE = 0x0010 + KIND_LIST = 0x0020 + KIND_MAP = 0x0040 + + SPECIAL_TIMESTAMP = 0x00100 + SPECIAL_BYTES = 0x00200 + SPECIAL_LONG = 0x00400 + SPECIAL_DURATION = 0x00800 + SPECIAL_ANY = 0x01000 + SPECIAL_EMPTY = 0x02000 + SPECIAL_STRUCT = 0x04000 + SPECIAL_VALUE = 0x08000 + SPECIAL_LIST_VALUE = 0x10000 + SPECIAL_NULL_VALUE = 0x20000 + + SPECIAL_KEYWORD = 0x10000000 # scalar FIELD_SIMPLE = DATA_SCALAR | KIND_SINGLE @@ -52,6 +55,8 @@ class FieldKind(enum.IntFlag): # map FIELD_ENUM_MAP = DATA_ENUM | KIND_MAP + FIELD_STRUCT_VALUES = SPECIAL_STRUCT | SPECIAL_VALUE | SPECIAL_LIST_VALUE | SPECIAL_NULL_VALUE + def __repr__(self) -> str: return self.name or str(self.value) @@ -127,6 +132,12 @@ def _check_field_kind(self): self.kind |= FieldKind.SPECIAL_EMPTY elif self.value_msg.full_name == 'google.protobuf.Struct': self.kind |= FieldKind.SPECIAL_STRUCT + elif self.value_msg.full_name == 'google.protobuf.Value': + self.kind |= FieldKind.SPECIAL_VALUE + elif self.value_msg.full_name == 'google.protobuf.ListValue': + self.kind |= FieldKind.SPECIAL_LIST_VALUE + elif self.value_msg.full_name == 'google.protobuf.NullValue': + self.kind |= FieldKind.SPECIAL_NULL_VALUE else: self.kind |= FieldKind.DATA_MESSAGE elif self.value_field.type == ProtoType.ENUM: # Enum diff --git a/neobuilder/generators/symbols/dataclass.py b/neobuilder/generators/symbols/dataclass.py index 9bd7d1d..48fb757 100644 --- a/neobuilder/generators/symbols/dataclass.py +++ b/neobuilder/generators/symbols/dataclass.py @@ -228,6 +228,12 @@ def render_arg_py(self, used_in_file: json_format.descriptor.FileDescriptor = No def get_field_options(self): if self.is_struct(): return f"default_factory=dict, metadata={{{self.get_metadata()}}}" + elif self.is_value(): + return f"default=..., metadata={{{self.get_metadata()}}}" + elif self.is_list_value(): + return f"default_factory=list, metadata={{{self.get_metadata()}}}" + elif self.is_null_value(): + return f"default=None, metadata={{{self.get_metadata()}}}" elif self.is_map(): return f"default_factory=dict, metadata={{{self.get_metadata()}}}" elif self.is_list(): @@ -280,13 +286,19 @@ def get_py_type_name(self, used_in_file: json_format.descriptor.FileDescriptor = def get_type_hint(self, used_in_file: json_format.descriptor.FileDescriptor = None) -> str: if self.is_struct(): - return f'typing.Dict[str, typing.Any]' + return 'typing.Dict[str, typing.Any]' + elif self.is_value(): + return 'typing.Any' + elif self.is_list_value(): + return 'typing.List[typing.Any]' + elif self.is_null_value(): + return 'None' elif self.is_map(): return f'typing.Dict[{self.field_descriptor.key_py_type.name}, {self.get_py_type_name(used_in_file)}]' elif self.is_list(): return f'typing.List[{self.get_py_type_name(used_in_file)}]' elif self.is_empty(): - return f'None' + return 'None' return self.get_py_type_name(used_in_file) def get_message_container_type(self) -> str: @@ -304,9 +316,7 @@ def get_metadata(self): elif self.is_list(): buf.append("'is_list': True") - if self.is_struct(): - buf.append("'is_struct': True") - elif self.is_message(): + if self.is_message() and not self.is_struct_value(): buf.append("'is_obj': True") elif self.is_enum(): buf.append("'is_enum': True") @@ -333,6 +343,12 @@ def get_dictator_name(self): return 'LongDictator' if self.is_struct(): return 'StructDictator' + if self.is_value(): + return 'ValueDictator' + if self.is_list_value(): + return 'ListValueDictator' + if self.is_null_value(): + return 'NullValueDictator' return 'BaseDictator' def is_long(self): @@ -344,6 +360,18 @@ def is_timestamp(self): def is_struct(self): return bool(self.field_descriptor.kind & FieldKind.SPECIAL_STRUCT) + def is_struct_value(self): + return bool(self.field_descriptor.kind & FieldKind.FIELD_STRUCT_VALUES) + + def is_value(self): + return bool(self.field_descriptor.kind & FieldKind.SPECIAL_VALUE) + + def is_null_value(self): + return bool(self.field_descriptor.kind & FieldKind.SPECIAL_NULL_VALUE) + + def is_list_value(self): + return bool(self.field_descriptor.kind & FieldKind.SPECIAL_LIST_VALUE) + def is_duration(self): return bool(self.field_descriptor.kind & FieldKind.SPECIAL_DURATION) diff --git a/pyproject.toml b/pyproject.toml index bfc7ae1..54612aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ classifiers = [ ] dependencies = [ - "protoplasm >=5.2, <6", + "protoplasm >=5.2.1, <6", "ccptools >= 1.1, <2", "Jinja2 >=3.1, <4", "semver >= 3.0.2, <4" diff --git a/requirements.txt b/requirements.txt index 2a8277a..b4a43c4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -protoplasm >=5.2, <6 +protoplasm >=5.2.1, <6 ccptools >=1.1, <2 Jinja2 >=3.1, <4 semver >= 3.0.2, <4 From 6472db87d97cd614260976545c414fea3e159d44 Mon Sep 17 00:00:00 2001 From: ccp_zeulix Date: Tue, 24 Sep 2024 15:27:19 +0000 Subject: [PATCH 2/3] Version 5.3.0 - Support for Value ### Added - Support for the `google.protobuf.Value` message --- pyproject.toml | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 54612aa..bfc7ae1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ classifiers = [ ] dependencies = [ - "protoplasm >=5.2.1, <6", + "protoplasm >=5.2, <6", "ccptools >= 1.1, <2", "Jinja2 >=3.1, <4", "semver >= 3.0.2, <4" diff --git a/requirements.txt b/requirements.txt index b4a43c4..2a8277a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -protoplasm >=5.2.1, <6 +protoplasm >=5.2, <6 ccptools >=1.1, <2 Jinja2 >=3.1, <4 semver >= 3.0.2, <4 From f17bcd49c64297bcc091eda9c23dfc0eaec7f394 Mon Sep 17 00:00:00 2001 From: ccp_zeulix Date: Tue, 24 Sep 2024 15:29:53 +0000 Subject: [PATCH 3/3] Version 5.3.0 - Support for Value ### Added - Support for the `google.protobuf.Value` message --- tests/res/expected/sandbox/test/googlestruct_dc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/res/expected/sandbox/test/googlestruct_dc.py b/tests/res/expected/sandbox/test/googlestruct_dc.py index f620b06..3398252 100644 --- a/tests/res/expected/sandbox/test/googlestruct_dc.py +++ b/tests/res/expected/sandbox/test/googlestruct_dc.py @@ -22,5 +22,5 @@ @dataclasses.dataclass class StructMessage(plasm.DataclassBase): __proto_cls__ = pb2.StructMessage - my_struct: typing.Dict[str, typing.Any] = dataclasses.field(default_factory=dict, metadata={'dictator': dictators.StructDictator, 'is_struct': True}) + my_struct: typing.Dict[str, typing.Any] = dataclasses.field(default_factory=dict, metadata={'dictator': dictators.StructDictator})