Skip to content

Commit 1ebaa01

Browse files
committed
Rename *NamesType to *ArgType
Add WhichOneofArgType and WhichOneofReturnType aliases Signed-off-by: Aidan Jensen <aidandj.github@gmail.com>
1 parent 3d681ce commit 1ebaa01

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+349
-277
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
- Protobuf <6.32 still had the edition enums and field options, so it *should* still work. But is untested
88
- Add support for editions (up to 2024)
99
- Add `generate_concrete_servicer_stubs` option to generate concrete instead of abstract servicer stubs
10-
- Add `_HasFieldNamesType` and `_ClearFieldNamesType` aliases to allow for typing field manipulation functions
10+
- Add `_HasFieldArgType` and `_ClearFieldArgType` aliases to allow for typing field manipulation functions
11+
- Add `_WhichOneofArgType_<field_name>` and `_WhichOneofReturnType_<field_name>` type aliases
1112

1213
## 3.7.0
1314

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ See [Changelog](CHANGELOG.md) for full listing
101101
* `mypy-protobuf` generates correctly typed constructors dependinding on field presence.
102102
* `mypy-protobuf` generates correctly typed `HasField`, `WhichOneof`, and `ClearField` methods.
103103
* There are differences in how `mypy-protobuf` and `pyi_out` generate enums. See [this issue](https://github.com/protocolbuffers/protobuf/issues/8175) for details
104+
* Type aliases exported for `HasField`, `WhichOneof` and `ClearField` arguments
104105

105106
#### Examples
106107

@@ -372,7 +373,7 @@ If you need stubs for grpc internal code we suggest using this package https://g
372373

373374
### `_ClearFieldNamesType` and `_HasFieldNamesType` aliases
374375

375-
Where applicable, type aliases are generated for the arguments to `ClearField` and `HasField`. These can be used to create typed functions for field manipulation:
376+
Where applicable, type aliases are generated for the arguments to `ClearField`, `WhichOneof` and `HasField`. These can be used to create typed functions for field manipulation:
376377

377378
```python
378379
from testproto.edition2024_pb2 import Editions2024Test
@@ -381,6 +382,14 @@ Where applicable, type aliases are generated for the arguments to `ClearField` a
381382
return msg.HasField(field)
382383

383384
test_hasfield_alias(Editions2024Test(), "legacy")
385+
386+
def test_whichoneof_alias(
387+
msg: SimpleProto3,
388+
oneof: "SimpleProto3._WhichOneofArgType_a_oneof",
389+
) -> "SimpleProto3._WhichOneofReturnType_a_oneof | None":
390+
return msg.WhichOneof(oneof)
391+
392+
test_whichoneof_alias(SimpleProto3(), "a_oneof")
384393
```
385394

386395
Note the deferred evaluation (string reference, or `from __future__ import annotations`. This bypasses the fact that the alias does not exist on the stub)

mypy_protobuf/extensions_pb2.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ class FieldOptions(google.protobuf.message.Message):
3838
keytype: builtins.str = ...,
3939
valuetype: builtins.str = ...,
4040
) -> None: ...
41-
_ClearFieldNamesType: typing_extensions.TypeAlias = typing.Literal["casttype", b"casttype", "keytype", b"keytype", "valuetype", b"valuetype"]
42-
def ClearField(self, field_name: _ClearFieldNamesType) -> None: ...
41+
_ClearFieldArgType: typing_extensions.TypeAlias = typing.Literal["casttype", b"casttype", "keytype", b"keytype", "valuetype", b"valuetype"]
42+
def ClearField(self, field_name: _ClearFieldArgType) -> None: ...
4343

4444
Global___FieldOptions: typing_extensions.TypeAlias = FieldOptions
4545

mypy_protobuf/main.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -578,29 +578,43 @@ def write_stringly_typed_fields(self, desc: d.DescriptorProto) -> None:
578578
return
579579

580580
if hf_fields:
581-
wl("_HasFieldNamesType: {} = {}[{}]", self._import("typing_extensions", "TypeAlias"), self._import("typing", "Literal"), hf_fields_text)
581+
wl("_HasFieldArgType: {} = {}[{}]", self._import("typing_extensions", "TypeAlias"), self._import("typing", "Literal"), hf_fields_text)
582582
wl(
583-
"def HasField(self, field_name: _HasFieldNamesType) -> {}: ...",
583+
"def HasField(self, field_name: _HasFieldArgType) -> {}: ...",
584584
self._builtin("bool"),
585585
)
586586
if cf_fields:
587-
wl("_ClearFieldNamesType: {} = {}[{}]", self._import("typing_extensions", "TypeAlias"), self._import("typing", "Literal"), cf_fields_text)
587+
wl("_ClearFieldArgType: {} = {}[{}]", self._import("typing_extensions", "TypeAlias"), self._import("typing", "Literal"), cf_fields_text)
588588
wl(
589-
"def ClearField(self, field_name: _ClearFieldNamesType) -> None: ...",
589+
"def ClearField(self, field_name: _ClearFieldArgType) -> None: ...",
590590
)
591591

592+
# Write type aliases first so overloads are not interrupted
592593
for wo_field, members in sorted(wo_fields.items()):
593-
if len(wo_fields) > 1:
594-
wl("@{}", self._import("typing", "overload"))
595594
wl(
596-
"def WhichOneof(self, oneof_group: {}[{}]) -> {}[{}] | None: ...",
597-
self._import("typing", "Literal"),
598-
# Accepts both str and bytes
599-
f'"{wo_field}", b"{wo_field}"',
595+
"_WhichOneofReturnType_{}: {} = {}[{}]",
596+
wo_field,
597+
self._import("typing_extensions", "TypeAlias"),
600598
self._import("typing", "Literal"),
601599
# Returns `str`
602600
", ".join(f'"{m}"' for m in members),
603601
)
602+
wl(
603+
"_WhichOneofArgType_{}: {} = {}[{}]",
604+
wo_field,
605+
self._import("typing_extensions", "TypeAlias"),
606+
self._import("typing", "Literal"),
607+
# Accepts both str and bytes
608+
f'"{wo_field}", b"{wo_field}"',
609+
)
610+
for wo_field, members in sorted(wo_fields.items()):
611+
if len(wo_fields) > 1:
612+
wl("@{}", self._import("typing", "overload"))
613+
wl(
614+
"def WhichOneof(self, oneof_group: {}) -> {} | None: ...",
615+
f"_WhichOneofArgType_{wo_field}",
616+
f"_WhichOneofReturnType_{wo_field}",
617+
)
604618

605619
def write_extensions(
606620
self,

stubtest_allowlist.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,5 +242,7 @@ testproto.test_pb2.Extensions1.ext
242242

243243

244244
# Generated type aliases for HasField and ClearField. These do not exist on a message, but are also just type aliases
245-
.*_HasFieldNamesType
246-
.*_ClearFieldNamesType
245+
.*_HasFieldArgType
246+
.*_ClearFieldArgType
247+
.*_WhichOneofReturnType.*
248+
.*_WhichOneofArgType.*

test/generated/google/protobuf/duration_pb2.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class Duration(google.protobuf.message.Message, google.protobuf.internal.well_kn
131131
seconds: builtins.int = ...,
132132
nanos: builtins.int = ...,
133133
) -> None: ...
134-
_ClearFieldNamesType: typing_extensions.TypeAlias = typing.Literal["nanos", b"nanos", "seconds", b"seconds"]
135-
def ClearField(self, field_name: _ClearFieldNamesType) -> None: ...
134+
_ClearFieldArgType: typing_extensions.TypeAlias = typing.Literal["nanos", b"nanos", "seconds", b"seconds"]
135+
def ClearField(self, field_name: _ClearFieldArgType) -> None: ...
136136

137137
Global___Duration: typing_extensions.TypeAlias = Duration

test/generated/mypy_protobuf/extensions_pb2.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ class FieldOptions(google.protobuf.message.Message):
3838
keytype: builtins.str = ...,
3939
valuetype: builtins.str = ...,
4040
) -> None: ...
41-
_ClearFieldNamesType: typing_extensions.TypeAlias = typing.Literal["casttype", b"casttype", "keytype", b"keytype", "valuetype", b"valuetype"]
42-
def ClearField(self, field_name: _ClearFieldNamesType) -> None: ...
41+
_ClearFieldArgType: typing_extensions.TypeAlias = typing.Literal["casttype", b"casttype", "keytype", b"keytype", "valuetype", b"valuetype"]
42+
def ClearField(self, field_name: _ClearFieldArgType) -> None: ...
4343

4444
Global___FieldOptions: typing_extensions.TypeAlias = FieldOptions
4545

test/generated/testproto/Capitalized/Capitalized_pb2.pyi

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ class lower(google.protobuf.message.Message):
2727
*,
2828
a: builtins.int = ...,
2929
) -> None: ...
30-
_ClearFieldNamesType: typing_extensions.TypeAlias = typing.Literal["a", b"a"]
31-
def ClearField(self, field_name: _ClearFieldNamesType) -> None: ...
30+
_ClearFieldArgType: typing_extensions.TypeAlias = typing.Literal["a", b"a"]
31+
def ClearField(self, field_name: _ClearFieldArgType) -> None: ...
3232

3333
Global___lower: typing_extensions.TypeAlias = lower
3434

@@ -44,10 +44,10 @@ class Upper(google.protobuf.message.Message):
4444
*,
4545
Lower: Global___lower | None = ...,
4646
) -> None: ...
47-
_HasFieldNamesType: typing_extensions.TypeAlias = typing.Literal["Lower", b"Lower"]
48-
def HasField(self, field_name: _HasFieldNamesType) -> builtins.bool: ...
49-
_ClearFieldNamesType: typing_extensions.TypeAlias = typing.Literal["Lower", b"Lower"]
50-
def ClearField(self, field_name: _ClearFieldNamesType) -> None: ...
47+
_HasFieldArgType: typing_extensions.TypeAlias = typing.Literal["Lower", b"Lower"]
48+
def HasField(self, field_name: _HasFieldArgType) -> builtins.bool: ...
49+
_ClearFieldArgType: typing_extensions.TypeAlias = typing.Literal["Lower", b"Lower"]
50+
def ClearField(self, field_name: _ClearFieldArgType) -> None: ...
5151

5252
Global___Upper: typing_extensions.TypeAlias = Upper
5353

@@ -63,9 +63,9 @@ class lower2(google.protobuf.message.Message):
6363
*,
6464
upper: Global___Upper | None = ...,
6565
) -> None: ...
66-
_HasFieldNamesType: typing_extensions.TypeAlias = typing.Literal["upper", b"upper"]
67-
def HasField(self, field_name: _HasFieldNamesType) -> builtins.bool: ...
68-
_ClearFieldNamesType: typing_extensions.TypeAlias = typing.Literal["upper", b"upper"]
69-
def ClearField(self, field_name: _ClearFieldNamesType) -> None: ...
66+
_HasFieldArgType: typing_extensions.TypeAlias = typing.Literal["upper", b"upper"]
67+
def HasField(self, field_name: _HasFieldArgType) -> builtins.bool: ...
68+
_ClearFieldArgType: typing_extensions.TypeAlias = typing.Literal["upper", b"upper"]
69+
def ClearField(self, field_name: _ClearFieldArgType) -> None: ...
7070

7171
Global___lower2: typing_extensions.TypeAlias = lower2

test/generated/testproto/comment_special_chars_pb2.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class Test(google.protobuf.message.Message):
7777
j: builtins.str = ...,
7878
k: builtins.str = ...,
7979
) -> None: ...
80-
_ClearFieldNamesType: typing_extensions.TypeAlias = typing.Literal["a", b"a", "b", b"b", "c", b"c", "d", b"d", "e", b"e", "f", b"f", "g", b"g", "h", b"h", "i", b"i", "j", b"j", "k", b"k"]
81-
def ClearField(self, field_name: _ClearFieldNamesType) -> None: ...
80+
_ClearFieldArgType: typing_extensions.TypeAlias = typing.Literal["a", b"a", "b", b"b", "c", b"c", "d", b"d", "e", b"e", "f", b"f", "g", b"g", "h", b"h", "i", b"i", "j", b"j", "k", b"k"]
81+
def ClearField(self, field_name: _ClearFieldArgType) -> None: ...
8282

8383
Global___Test: typing_extensions.TypeAlias = Test

test/generated/testproto/dot/com/test_pb2.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class TestMessage(google.protobuf.message.Message):
2727
*,
2828
foo: builtins.str = ...,
2929
) -> None: ...
30-
_ClearFieldNamesType: typing_extensions.TypeAlias = typing.Literal["foo", b"foo"]
31-
def ClearField(self, field_name: _ClearFieldNamesType) -> None: ...
30+
_ClearFieldArgType: typing_extensions.TypeAlias = typing.Literal["foo", b"foo"]
31+
def ClearField(self, field_name: _ClearFieldArgType) -> None: ...
3232

3333
Global___TestMessage: typing_extensions.TypeAlias = TestMessage

0 commit comments

Comments
 (0)