8000 fix incorrect deprecation warnings on defaults · abn/python-betterproto@b1fd73d · GitHub
[go: up one dir, main page]

Skip to content

Commit b1fd73d

Browse files
committed
fix incorrect deprecation warnings on defaults
This change ensures that deprecation warnings are only raised when either a deprecated field is explicitly set or a deprecated message is initialised. Resolves: danielgtaylor#347
1 parent 28644e3 commit b1fd73d

File tree

7 files changed

+61
-33
lines changed

7 files changed

+61
-33
lines changed

src/betterproto/__init__.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,12 @@ def _cls_for(cls, field: dataclasses.Field, index: int = 0) -> Type:
867867
return field_cls
868868

869869
def _get_field_default(self, field_name: str) -> Any:
870-
return self._betterproto.default_gen[field_name]()
870+
import warnings
871+
872+
with warnings.catch_warnings():
873+
# ignore warnings when initialising deprecated field defaults
874+
warnings.filterwarnings("ignore", category=DeprecationWarning)
875+
return self._betterproto.default_gen[field_name]()
871876

872877
@classmethod
873878
def _get_field_default_gen(cls, field: dataclasses.Field) -> Any:
@@ -1288,6 +1293,22 @@ def from_json(self: T, value: Union[str, bytes]) -> T:
12881293
"""
12891294
return self.from_dict(json.loads(value))
12901295

1296+
def is_set(self, name: str) -> bool:
1297+
"""
1298+
Check if field with the given name has been set.
1299+
1300+
Parameters
1301+
-----------
1302+
name: :class:`str`
1303+
The name of the field to check for.
1304+
1305+
Returns
1306+
--------
1307+
:class:`bool`
1308+
`True` if field has been set, otherwise `False`.
1309+
"""
1310+
return self.__raw_get(name) is not PLACEHOLDER
1311+
12911312

12921313
def serialized_on_wire(message: Message) -> bool:
12931314
"""

src/betterproto/templates/template.py.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class {{ message.py_name }}(betterproto.Message):
6363
{% endif %}
6464
super().__post_init__()
6565
{% for field in message.deprecated_fields %}
66-
if self.{{ field }}:
66+
if self.is_set("{{ field }}"):
6767
warnings.warn("{{ message.py_name }}.{{ field }} is deprecated", DeprecationWarning)
6868
{% endfor %}
6969
{% endif %}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
{
2-
"v": 10,
2+
"message": {
3+
"value": "hello"
4+
},
35
"value": 10
46
}

tests/inputs/deprecated/deprecated.proto

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ package deprecated;
44

55
// Some documentation about the Test message.
66
message Test {
7-
// Some documentation about the value.
8-
option deprecated = true;
9-
int32 v = 1 [deprecated=true];
7+
Message message = 1 [deprecated=true];
108
int32 value = 2;
119
}
10+
11+
message Message {
12+
option deprecated = true;
13+
string value = 1;
14+
}

tests/inputs/deprecated_field/deprecated_field.json

Lines changed: 0 additions & 4 deletions
This file was deleted.

tests/inputs/deprecated_field/deprecated_field.proto

Lines changed: 0 additions & 10 deletions
This file was deleted.

tests/test_deprecated.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,42 @@
1+
import warnings
2+
13
import pytest
24

3-
from tests.output_betterproto.deprecated import Test as DeprecatedMessageTest
4-
from tests.output_betterproto.deprecated_field import Test as DeprecatedFieldTest
5+
from tests.output_betterproto.deprecated import Message, Test
6+
7+
8+
@pytest.fixture
9+
def message():
10+
with warnings.catch_warnings():
11+
warnings.filterwarnings("ignore", category=DeprecationWarning)
12+
return Message(value="hello")
51 B41A 3

614

715
def test_deprecated_message():
8-
with pytest.deprecated_call():
9-
DeprecatedMessageTest(value=10)
16+
with pytest.warns(DeprecationWarning) as record:
17+
Message(value="hello")
1018

19+
assert len(record) == 1
20+
assert str(record[0].message) == f"{Message.__name__} is deprecated"
1121

12-
def test_deprecated_message_with_deprecated_field():
13-
with pytest.warns(None) as record:
14-
DeprecatedMessageTest(v=10, value=10)
15-
assert len(record) == 2
1622

23+
def test_message_with_deprecated_field(message):
24+
with pytest.warns(DeprecationWarning) as record:
25+
Test(message=message, value=10)
26+
27+
assert len(record) == 1
28+
assert str(record[0].message) == f"{Test.__name__}.message is deprecated"
1729

18-
def test_deprecated_field_warning():
19-
with pytest.deprecated_call():
20-
DeprecatedFieldTest(v=10, value=10)
2130

31+
def test_message_with_deprecated_field_not_set(message):
32+
with pytest.warns(None) as record:
33+
Test(value=10)
34+
35+
assert not record
2236

23-
def test_deprecated_field_no_warning():
37+
38+
def test_message_with_deprecated_field_not_set_default(message):
2439
with pytest.warns(None) as record:
25-
DeprecatedFieldTest(value=10)
40+
_ = Test(value=10).message
41+
2642
assert not record

0 commit comments

Comments
 (0)
0