8 Commits

Author SHA1 Message Date
Daniel G. Taylor
559b8833d8 Bump version to 1.2.2 2020-01-09 16:47:25 -08:00
Daniel G. Taylor
7ccef16579 Mention no proto 2, fixes #6 2020-01-09 16:43:45 -08:00
Daniel G. Taylor
d8785b4622 Merge pull request #10 from qix/master
Fix serialization of dataclass constructor parameters
2020-01-09 16:35:06 -08:00
Daniel G. Taylor
45e7a30300 Merge pull request #7 from ulasozguler/master
Fix - propagate `casing` param of `to_dict` function recursively
2020-01-09 16:32:29 -08:00
Josh Yudaken
d7559c22f8 Fix serialization of dataclass constructor parameters 2020-01-08 11:29:45 -05:00
ulas
f9c351a98d propagate casing param recursively. 2019-12-04 19:28:53 +03:00
Daniel G. Taylor
feea790116 Bump library version 2019-10-29 22:00:27 -07:00
Daniel G. Taylor
33f74f6a45 Fix comment indent bug; bump version 2019-10-29 21:59:23 -07:00
7 changed files with 48 additions and 16 deletions

View File

@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [1.2.2] - 2020-01-09
- Mention lack of Proto 2 support in README.
- Fix serialization of constructor parameters [#10](https://github.com/danielgtaylor/python-betterproto/pull/10)
- Fix `casing` parameter propagation [#7](https://github.com/danielgtaylor/python-betterproto/pull/7)
## [1.2.1] - 2019-10-29
- Fix comment indentation bug in rendered gRPC methods.
## [1.2.0] - 2019-10-28
- Generated code output auto-formatting via [Black](https://github.com/psf/black)
@@ -29,7 +39,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Initial release
[unreleased]: https://github.com/danielgtaylor/python-betterproto/compare/v1.2.0...HEAD
[unreleased]: https://github.com/danielgtaylor/python-betterproto/compare/v1.2.2...HEAD
[1.2.2]: https://github.com/danielgtaylor/python-betterproto/compare/v1.2.1...v1.2.2
[1.2.1]: https://github.com/danielgtaylor/python-betterproto/compare/v1.2.0...v1.2.1
[1.2.0]: https://github.com/danielgtaylor/python-betterproto/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/danielgtaylor/python-betterproto/compare/v1.0.1...v1.1.0
[1.0.1]: https://github.com/danielgtaylor/python-betterproto/compare/v1.0.0...v1.0.1

View File

@@ -2,7 +2,7 @@
![](https://github.com/danielgtaylor/python-betterproto/workflows/CI/badge.svg)
This project aims to provide an improved experience when using Protobuf / gRPC in a modern Python environment by making use of modern language features and generating readable, understandable, idiomatic Python code. It will not support legacy features or environments. The following are supported:
This project aims to provide an improved experience when using Protobuf / gRPC in a modern Python environment by making use of modern language features and generating readable, understandable, idiomatic Python code. It will not support legacy features or environments (e.g. Protobuf 2). The following are supported:
- Protobuf 3 & gRPC code generation
- Both binary & JSON serialization is built-in

View File

@@ -430,6 +430,9 @@ class Message(ABC):
_group_map: Dict[str, dict]
def __post_init__(self) -> None:
# Keep track of whether every field was default
all_sentinel = True
# Set a default value for each field in the class after `__init__` has
# already been run.
group_map: Dict[str, dict] = {"fields": {}, "groups": {}}
@@ -446,6 +449,7 @@ class Message(ABC):
if getattr(self, field.name) != PLACEHOLDER:
# Skip anything not set to the sentinel value
all_sentinel = False
if meta.group:
# This was set, so make it the selected value of the one-of.
@@ -456,7 +460,7 @@ class Message(ABC):
setattr(self, field.name, self._get_field_default(field, meta))
# Now that all the defaults are set, reset it!
self.__dict__["_serialized_on_wire"] = False
self.__dict__["_serialized_on_wire"] = not all_sentinel
self.__dict__["_unknown_fields"] = b""
self.__dict__["_group_map"] = group_map
@@ -723,14 +727,14 @@ class Message(ABC):
output[cased_name] = v
elif isinstance(v, list):
# Convert each item.
v = [i.to_dict() for i in v]
v = [i.to_dict(casing) for i in v]
output[cased_name] = v
elif v._serialized_on_wire:
output[cased_name] = v.to_dict()
output[cased_name] = v.to_dict(casing)
elif meta.proto_type == "map":
for k in v:
if hasattr(v[k], "to_dict"):
v[k] = v[k].to_dict()
v[k] = v[k].to_dict(casing)
if v:
output[cased_name] = v

View File

@@ -142,25 +142,26 @@ def traverse(proto_file):
)
def get_comment(proto_file, path: List[int]) -> str:
def get_comment(proto_file, path: List[int], indent: int = 4) -> str:
pad = " " * indent
for sci in proto_file.source_code_info.location:
# print(list(sci.path), path, file=sys.stderr)
if list(sci.path) == path and sci.leading_comments:
lines = textwrap.wrap(
sci.leading_comments.strip().replace("\n", ""), width=75
sci.leading_comments.strip().replace("\n", ""), width=79 - indent
)
if path[-2] == 2 and path[-4] != 6:
# This is a field
return " # " + "\n # ".join(lines)
return f"{pad}# " + f"\n{pad}# ".join(lines)
else:
# This is a message, enum, service, or method
if len(lines) == 1 and len(lines[0]) < 70:
if len(lines) == 1 and len(lines[0]) < 79 - indent - 6:
lines[0] = lines[0].strip('"')
return f' """{lines[0]}"""'
return f'{pad}"""{lines[0]}"""'
else:
joined = "\n ".join(lines)
return f' """\n {joined}\n """'
joined = f"\n{pad}".join(lines)
return f'{pad}"""\n{pad}{joined}\n{pad}"""'
return ""
@@ -371,7 +372,7 @@ def generate_code(request, response):
{
"name": method.name,
"py_name": stringcase.snakecase(method.name),
"comment": get_comment(proto_file, [6, i, 2, j]),
"comment": get_comment(proto_file, [6, i, 2, j], indent=8),
"route": f"/{package}.{service.name}/{method.name}",
"input": get_ref_type(
package, output["imports"], method.input_type

View File

@@ -15,8 +15,8 @@ import betterproto
{% if description.services %}
import grpclib
{% endif %}
{% for i in description.imports %}
{% for i in description.imports %}
{{ i }}
{% endfor %}

View File

@@ -33,6 +33,21 @@ def test_has_field():
assert betterproto.serialized_on_wire(foo.bar) == False
def test_class_init():
@dataclass
class Bar(betterproto.Message):
name: str = betterproto.string_field(1)
@dataclass
class Foo(betterproto.Message):
name: str = betterproto.string_field(1)
child: Bar = betterproto.message_field(2)
foo = Foo(name="foo", child=Bar(name="bar"))
assert foo.to_dict() == {"name": "foo", "child": {"name": "bar"}}
def test_enum_as_int_json():
class TestEnum(betterproto.Enum):
ZERO = 0

View File

@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name="betterproto",
version="1.2.0",
version="1.2.2",
description="A better Protobuf / gRPC generator & library",
long_description=open("README.md", "r").read(),
long_description_content_type="text/markdown",