Support deprecated message and fields (#126)

This commit is contained in:
Arun Babu Neelicattu 2020-07-30 14:47:01 +02:00 committed by GitHub
parent beafc812ff
commit 0cd9510b54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 0 deletions

View File

@ -33,6 +33,7 @@ import re
from dataclasses import dataclass
from dataclasses import field
from typing import (
Iterator,
Union,
Type,
List,
@ -249,6 +250,13 @@ class OutputTemplate:
"""
return [f.name for f in self.input_files]
@property
def python_module_imports(self) -> Set[str]:
imports = set()
if any(x for x in self.messages if any(x.deprecated_fields)):
imports.add("warnings")
return imports
@dataclass
class MessageCompiler(ProtoContentBase):
@ -261,6 +269,7 @@ class MessageCompiler(ProtoContentBase):
fields: List[Union["FieldCompiler", "MessageCompiler"]] = field(
default_factory=list
)
deprecated: bool = field(default=False, init=False)
def __post_init__(self):
# Add message to output file
@ -269,6 +278,7 @@ class MessageCompiler(ProtoContentBase):
self.output_file.enums.append(self)
else:
self.output_file.messages.append(self)
self.deprecated = self.proto_obj.options.deprecated
super().__post_init__()
@property
@ -285,6 +295,12 @@ class MessageCompiler(ProtoContentBase):
return f"List[{self.py_name}]"
return self.py_name
@property
def deprecated_fields(self) -> Iterator[str]:
for f in self.fields:
if f.deprecated:
yield f.py_name
def is_map(
proto_field_obj: FieldDescriptorProto, parent_message: DescriptorProto

View File

@ -1,6 +1,9 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# sources: {{ ', '.join(description.input_filenames) }}
# plugin: python-betterproto
{% for i in description.python_module_imports|sort %}
import {{ i }}
{% endfor %}
from dataclasses import dataclass
{% if description.datetime_imports %}
from datetime import {% for i in description.datetime_imports|sort %}{{ i }}{% if not loop.last %}, {% endif %}{% endfor %}
@ -50,6 +53,18 @@ class {{ message.py_name }}(betterproto.Message):
pass
{% endif %}
{% if message.deprecated or message.deprecated_fields %}
def __post_init__(self) -> None:
{% if message.deprecated %}
warnings.warn("{{ message.py_name }} is deprecated", DeprecationWarning)
{% endif %}
super().__post_init__()
{% for field in message.deprecated_fields %}
if self.{{ field }}:
warnings.warn("{{ message.py_name }}.{{ field }} is deprecated", DeprecationWarning)
{% endfor %}
{% endif %}
{% endfor %}
{% for service in description.services %}

View File

@ -0,0 +1,4 @@
{
"v": 10,
"value": 10
}

View File

@ -0,0 +1,9 @@
syntax = "proto3";
// Some documentation about the Test message.
message Test {
// Some documentation about the value.
option deprecated = true;
int32 v = 1 [deprecated=true];
int32 value = 2;
}

View File

@ -0,0 +1,4 @@
{
"v": 10,
"value": 10
}

View File

@ -0,0 +1,8 @@
syntax = "proto3";
// Some documentation about the Test message.
message Test {
// Some documentation about the value.
int32 v = 1 [deprecated=true];
int32 value = 2;
}

26
tests/test_deprecated.py Normal file
View File

@ -0,0 +1,26 @@
import pytest
from tests.output_betterproto.deprecated import Test as DeprecatedMessageTest
from tests.output_betterproto.deprecated_field import Test as DeprecatedFieldTest
def test_deprecated_message():
with pytest.deprecated_call():
DeprecatedMessageTest(value=10)
def test_deprecated_message_with_deprecated_field():
with pytest.warns(None) as record:
DeprecatedMessageTest(v=10, value=10)
assert len(record) == 2
def test_deprecated_field_warning():
with pytest.deprecated_call():
DeprecatedFieldTest(v=10, value=10)
def test_deprecated_field_no_warning():
with pytest.warns(None) as record:
DeprecatedFieldTest(value=10)
assert not record