Skip to content

Commit 1480b55

Browse files
committed
Type Python WhichOneof in generated stubs
Emit literal-aware, positional-only WhichOneof signatures in generated Python stubs so callers can reject invalid group names and exhaustively handle members. Accept byte-string group names supported by the default runtimes, reject calls on messages without oneofs, and avoid a duplicate declaration when a field shadows the method. Include synthetic proto3-optional groups because runtime reflection exposes them. Extend the generated-stub harness with single, multiple, nested, synthetic, keyword, and shadowed oneofs plus messages without oneofs. Snapshot inferred return types, invalid groups, keyword calls, and missing-branch diagnostics with every type checker.
1 parent 65ab7b1 commit 1480b55

12 files changed

Lines changed: 279 additions & 52 deletions

python/pyi_test/BUILD.bazel

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,34 @@ pyi_files(
5151
dep = ":self_fields_py_pb2",
5252
)
5353

54+
proto_library(
55+
name = "keyword_oneof_proto",
56+
srcs = ["keyword_oneof.proto"],
57+
)
58+
59+
py_proto_library(
60+
name = "keyword_oneof_py_pb2",
61+
deps = [":keyword_oneof_proto"],
62+
)
63+
64+
pyi_files(
65+
name = "keyword_oneof_pyi",
66+
dep = ":keyword_oneof_py_pb2",
67+
)
68+
5469
py_test(
5570
name = "golden_test",
5671
size = "small",
5772
srcs = ["golden_test.py"],
5873
args = [
5974
"$(locations :fixture_pyi)",
6075
"$(locations :self_fields_pyi)",
76+
"$(locations :keyword_oneof_pyi)",
6177
],
6278
data = glob(["*_pb2.pyi.golden"]) + [
6379
":fixture_pyi",
6480
":self_fields_pyi",
81+
":keyword_oneof_pyi",
6582
],
6683
tags = [
6784
"manual",
@@ -99,6 +116,8 @@ py_test(
99116
"typing_test.py",
100117
":fixture_py_pb2",
101118
":fixture_pyi",
119+
":keyword_oneof_py_pb2",
120+
":keyword_oneof_pyi",
102121
":mypy_bin",
103122
":node",
104123
":self_fields_pyi",
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from google.protobuf import descriptor as _descriptor
22
from google.protobuf import message as _message
3-
from typing import ClassVar as _ClassVar, Optional as _Optional
3+
from typing import ClassVar as _ClassVar, NoReturn as _NoReturn, Optional as _Optional
44

55
DESCRIPTOR: _descriptor.FileDescriptor
66

@@ -9,3 +9,4 @@ class Imported(_message.Message):
99
VALUE_FIELD_NUMBER: _ClassVar[int]
1010
value: str
1111
def __init__(self, value: _Optional[str] = ...) -> None: ...
12+
def WhichOneof(self, oneof_group: _NoReturn, /) -> None: ...

python/pyi_test/fixture_pb2.pyi.golden

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
88
from google.protobuf import descriptor as _descriptor
99
from google.protobuf import message as _message
1010
from collections.abc import Iterable as _Iterable, Mapping as _Mapping
11-
from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union
11+
from typing import ClassVar as _ClassVar, Literal as _Literal, NoReturn as _NoReturn, Optional as _Optional, Union as _Union, overload as _overload
1212

1313
DESCRIPTOR: _descriptor.FileDescriptor
1414

@@ -24,6 +24,7 @@ class Child(_message.Message):
2424
VALUE_FIELD_NUMBER: _ClassVar[int]
2525
value: str
2626
def __init__(self, value: _Optional[str] = ...) -> None: ...
27+
def WhichOneof(self, oneof_group: _NoReturn, /) -> None: ...
2728

2829
class Step(_message.Message):
2930
__slots__ = ("a", "b", "ok", "error", "detail", "labels", "children", "children_by_name", "state", "payload", "imported", "created_at", "elapsed")
@@ -40,13 +41,15 @@ class Step(_message.Message):
4041
started: str
4142
finished: str
4243
def __init__(self, started: _Optional[str] = ..., finished: _Optional[str] = ...) -> None: ...
44+
def WhichOneof(self, oneof_group: _Literal["event", b"event"], /) -> _Optional[_Literal["started", "finished"]]: ...
4345
class ChildrenByNameEntry(_message.Message):
4446
__slots__ = ("key", "value")
4547
KEY_FIELD_NUMBER: _ClassVar[int]
4648
VALUE_FIELD_NUMBER: _ClassVar[int]
4749
key: str
4850
value: Child
4951
def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[Child, _Mapping]] = ...) -> None: ...
52+
def WhichOneof(self, oneof_group: _NoReturn, /) -> None: ...
5053
A_FIELD_NUMBER: _ClassVar[int]
5154
B_FIELD_NUMBER: _ClassVar[int]
5255
OK_FIELD_NUMBER: _ClassVar[int]
@@ -74,3 +77,9 @@ class Step(_message.Message):
7477
created_at: _timestamp_pb2.Timestamp
7578
elapsed: _duration_pb2.Duration
7679
def __init__(self, a: _Optional[str] = ..., b: _Optional[int] = ..., ok: _Optional[bool] = ..., error: _Optional[str] = ..., detail: _Optional[str] = ..., labels: _Optional[_Iterable[str]] = ..., children: _Optional[_Iterable[_Union[Child, _Mapping]]] = ..., children_by_name: _Optional[_Mapping[str, Child]] = ..., state: _Optional[_Union[State, str]] = ..., payload: _Optional[bytes] = ..., imported: _Optional[_Union[_fixture_import_pb2.Imported, _Mapping]] = ..., created_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., elapsed: _Optional[_Union[datetime.timedelta, _duration_pb2.Duration, _Mapping]] = ...) -> None: ...
80+
@_overload
81+
def WhichOneof(self, oneof_group: _Literal["action", b"action"], /) -> _Optional[_Literal["a", "b"]]: ...
82+
@_overload
83+
def WhichOneof(self, oneof_group: _Literal["result", b"result"], /) -> _Optional[_Literal["ok", "error"]]: ...
84+
@_overload
85+
def WhichOneof(self, oneof_group: _Literal["_detail", b"_detail"], /) -> _Optional[_Literal["detail"]]: ...
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Protocol Buffers - Google's data interchange format
2+
// Copyright 2008 Google Inc. All rights reserved.
3+
//
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file or at
6+
// https://developers.google.com/open-source/licenses/bsd
7+
8+
syntax = "proto3";
9+
10+
package protobuf.pyi_test;
11+
12+
message KeywordOneof {
13+
oneof choice {
14+
string from = 1;
15+
string class = 2;
16+
}
17+
}
18+
19+
message ShadowedOneof {
20+
string WhichOneof = 1;
21+
oneof action {
22+
string a = 2;
23+
}
24+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from google.protobuf import descriptor as _descriptor
2+
from google.protobuf import message as _message
3+
from typing import ClassVar as _ClassVar, Literal as _Literal, Optional as _Optional
4+
5+
DESCRIPTOR: _descriptor.FileDescriptor
6+
7+
class KeywordOneof(_message.Message):
8+
__slots__ = ()
9+
FROM_FIELD_NUMBER: _ClassVar[int]
10+
CLASS_FIELD_NUMBER: _ClassVar[int]
11+
def __init__(self, **kwargs) -> None: ...
12+
def WhichOneof(self, oneof_group: _Literal["choice", b"choice"], /) -> _Optional[_Literal["from", "class"]]: ...
13+
14+
class ShadowedOneof(_message.Message):
15+
__slots__ = ("WhichOneof", "a")
16+
WHICHONEOF_FIELD_NUMBER: _ClassVar[int]
17+
A_FIELD_NUMBER: _ClassVar[int]
18+
WhichOneof: str
19+
a: str
20+
def __init__(self, WhichOneof: _Optional[str] = ..., a: _Optional[str] = ...) -> None: ...

python/pyi_test/mypy.golden

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,34 @@
1-
python/pyi_test/typing_test.py:28: note: Revealed type is "bool"
2-
python/pyi_test/typing_test.py:29: note: Revealed type is "str"
3-
python/pyi_test/typing_test.py:30: note: Revealed type is "bytes"
4-
python/pyi_test/typing_test.py:31: note: Revealed type is "str"
5-
python/pyi_test/typing_test.py:32: note: Revealed type is "python.pyi_test.fixture_pb2.State"
1+
python/pyi_test/typing_test.py:33: note: Revealed type is "bool"
62
python/pyi_test/typing_test.py:34: note: Revealed type is "str"
7-
python/pyi_test/typing_test.py:40: note: Revealed type is "int"
8-
python/pyi_test/typing_test.py:41: note: Revealed type is "str"
3+
python/pyi_test/typing_test.py:35: note: Revealed type is "bytes"
4+
python/pyi_test/typing_test.py:36: note: Revealed type is "str"
5+
python/pyi_test/typing_test.py:37: note: Revealed type is "python.pyi_test.fixture_pb2.State"
6+
python/pyi_test/typing_test.py:38: note: Revealed type is "Literal['detail'] | None"
7+
python/pyi_test/typing_test.py:39: note: Revealed type is "Literal['ok'] | Literal['error'] | None"
8+
python/pyi_test/typing_test.py:40: note: Revealed type is "Literal['ok'] | Literal['error'] | None"
99
python/pyi_test/typing_test.py:42: note: Revealed type is "str"
10-
python/pyi_test/typing_test.py:44: error: Argument "payload" to "Step" has incompatible type "str"; expected "bytes | None" [arg-type]
11-
python/pyi_test/typing_test.py:45: error: Incompatible types in assignment (expression has type "str", variable has type "bytes") [assignment]
12-
python/pyi_test/typing_test.py:46: error: Unexpected keyword argument "not_a_field" for "Step" [call-arg]
13-
python/pyi_test/typing_test.py:46: note: "Step" defined in "python.pyi_test.fixture_pb2"
10+
python/pyi_test/typing_test.py:43: note: Revealed type is "Literal['started'] | Literal['finished'] | None"
11+
python/pyi_test/typing_test.py:45: note: Revealed type is "Literal['from'] | Literal['class'] | None"
12+
python/pyi_test/typing_test.py:47: note: Revealed type is "str"
13+
python/pyi_test/typing_test.py:50: note: Revealed type is "Literal['a'] | Literal['b'] | None"
14+
python/pyi_test/typing_test.py:52: note: Revealed type is "str"
15+
python/pyi_test/typing_test.py:54: note: Revealed type is "int"
16+
python/pyi_test/typing_test.py:65: note: Revealed type is "int"
17+
python/pyi_test/typing_test.py:66: note: Revealed type is "str"
18+
python/pyi_test/typing_test.py:67: note: Revealed type is "str"
19+
python/pyi_test/typing_test.py:69: error: Argument "payload" to "Step" has incompatible type "str"; expected "bytes | None" [arg-type]
20+
python/pyi_test/typing_test.py:70: error: Incompatible types in assignment (expression has type "str", variable has type "bytes") [assignment]
21+
python/pyi_test/typing_test.py:71: error: Unexpected keyword argument "not_a_field" for "Step" [call-arg]
22+
python/pyi_test/typing_test.py:71: note: "Step" defined in "python.pyi_test.fixture_pb2"
23+
python/pyi_test/typing_test.py:72: error: No overload variant of "WhichOneof" of "Step" matches argument type "str" [call-overload]
24+
python/pyi_test/typing_test.py:72: note: Possible overload variants:
25+
python/pyi_test/typing_test.py:72: note: def WhichOneof(self, Literal['action', b'action'], /) -> Literal['a', 'b'] | None
26+
python/pyi_test/typing_test.py:72: note: def WhichOneof(self, Literal['result', b'result'], /) -> Literal['ok', 'error'] | None
27+
python/pyi_test/typing_test.py:72: note: def WhichOneof(self, Literal['_detail', b'_detail'], /) -> Literal['detail'] | None
28+
python/pyi_test/typing_test.py:73: error: No overload variant of "WhichOneof" of "Step" matches argument type "str" [call-overload]
29+
python/pyi_test/typing_test.py:73: note: Possible overload variants:
30+
python/pyi_test/typing_test.py:73: note: def WhichOneof(self, Literal['action', b'action'], /) -> Literal['a', 'b'] | None
31+
python/pyi_test/typing_test.py:73: note: def WhichOneof(self, Literal['result', b'result'], /) -> Literal['ok', 'error'] | None
32+
python/pyi_test/typing_test.py:73: note: def WhichOneof(self, Literal['_detail', b'_detail'], /) -> Literal['detail'] | None
33+
python/pyi_test/typing_test.py:74: error: Argument 1 to "WhichOneof" of "SelfFields" has incompatible type "str"; expected "Never" [arg-type]
34+
python/pyi_test/typing_test.py:81: error: Argument 1 to "assert_never" has incompatible type "Literal['b']"; expected "Never" [arg-type]

python/pyi_test/pyrefly.golden

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
1-
INFO python/pyi_test/typing_test.py:28:12-21: revealed type: bool [reveal-type]
2-
INFO python/pyi_test/typing_test.py:29:12-25: revealed type: str [reveal-type]
3-
INFO python/pyi_test/typing_test.py:30:12-26: revealed type: bytes [reveal-type]
4-
INFO python/pyi_test/typing_test.py:31:12-33: revealed type: str [reveal-type]
5-
INFO python/pyi_test/typing_test.py:32:12-24: revealed type: State [reveal-type]
6-
INFO python/pyi_test/typing_test.py:34:12-28: revealed type: str [reveal-type]
7-
INFO python/pyi_test/typing_test.py:40:12-35: revealed type: int [reveal-type]
8-
INFO python/pyi_test/typing_test.py:41:12-30: revealed type: str [reveal-type]
9-
INFO python/pyi_test/typing_test.py:42:12-31: revealed type: str [reveal-type]
10-
ERROR python/pyi_test/typing_test.py:44:26-37: Argument `Literal['not bytes']` is not assignable to parameter `payload` with type `bytes | None` in function `python.pyi_test.fixture_pb2.Step.__init__` [bad-argument-type]
11-
ERROR python/pyi_test/typing_test.py:45:16-27: `Literal['not bytes']` is not assignable to attribute `payload` with type `bytes` [bad-assignment]
12-
ERROR python/pyi_test/typing_test.py:46:18-29: Unexpected keyword argument `not_a_field` in function `python.pyi_test.fixture_pb2.Step.__init__` [unexpected-keyword]
1+
INFO python/pyi_test/typing_test.py:33:12-21: revealed type: bool [reveal-type]
2+
INFO python/pyi_test/typing_test.py:34:12-25: revealed type: str [reveal-type]
3+
INFO python/pyi_test/typing_test.py:35:12-26: revealed type: bytes [reveal-type]
4+
INFO python/pyi_test/typing_test.py:36:12-33: revealed type: str [reveal-type]
5+
INFO python/pyi_test/typing_test.py:37:12-24: revealed type: State [reveal-type]
6+
INFO python/pyi_test/typing_test.py:38:12-40: revealed type: Literal['detail'] | None [reveal-type]
7+
INFO python/pyi_test/typing_test.py:39:12-39: revealed type: Literal['error', 'ok'] | None [reveal-type]
8+
INFO python/pyi_test/typing_test.py:40:12-40: revealed type: Literal['error', 'ok'] | None [reveal-type]
9+
INFO python/pyi_test/typing_test.py:42:12-28: revealed type: str [reveal-type]
10+
INFO python/pyi_test/typing_test.py:43:12-40: revealed type: Literal['finished', 'started'] | None [reveal-type]
11+
INFO python/pyi_test/typing_test.py:45:12-42: revealed type: Literal['class', 'from'] | None [reveal-type]
12+
INFO python/pyi_test/typing_test.py:47:12-33: revealed type: str [reveal-type]
13+
INFO python/pyi_test/typing_test.py:50:12-20: revealed type: Literal['a', 'b'] | None [reveal-type]
14+
INFO python/pyi_test/typing_test.py:52:16-24: revealed type: str [reveal-type]
15+
INFO python/pyi_test/typing_test.py:54:16-24: revealed type: int [reveal-type]
16+
INFO python/pyi_test/typing_test.py:65:12-35: revealed type: int [reveal-type]
17+
INFO python/pyi_test/typing_test.py:66:12-30: revealed type: str [reveal-type]
18+
INFO python/pyi_test/typing_test.py:67:12-31: revealed type: str [reveal-type]
19+
ERROR python/pyi_test/typing_test.py:69:26-37: Argument `Literal['not bytes']` is not assignable to parameter `payload` with type `bytes | None` in function `python.pyi_test.fixture_pb2.Step.__init__` [bad-argument-type]
20+
ERROR python/pyi_test/typing_test.py:70:16-27: `Literal['not bytes']` is not assignable to attribute `payload` with type `bytes` [bad-assignment]
21+
ERROR python/pyi_test/typing_test.py:71:18-29: Unexpected keyword argument `not_a_field` in function `python.pyi_test.fixture_pb2.Step.__init__` [unexpected-keyword]
22+
ERROR python/pyi_test/typing_test.py:72:16-31: No matching overload found for function `python.pyi_test.fixture_pb2.Step.WhichOneof` called with arguments: (Literal['not_a_oneof']) [no-matching-overload]
23+
ERROR python/pyi_test/typing_test.py:73:16-38: No matching overload found for function `python.pyi_test.fixture_pb2.Step.WhichOneof` called with arguments: (oneof_group=Literal['action']) [no-matching-overload]
24+
ERROR python/pyi_test/typing_test.py:74:24-37: Argument `Literal['not_a_oneof']` is not assignable to parameter `oneof_group` with type `NoReturn` in function `python.pyi_test.self_fields_pb2.SelfFields.WhichOneof` [bad-argument-type]
25+
ERROR python/pyi_test/typing_test.py:81:18-24: Argument `Literal['b']` is not assignable to parameter `arg` with type `Never` in function `typing_extensions.assert_never` [bad-argument-type]

python/pyi_test/pyright.golden

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,38 @@
11
python/pyi_test/typing_test.py
2-
python/pyi_test/typing_test.py:28:13 - information: Type of "step.ok" is "bool"
3-
python/pyi_test/typing_test.py:29:13 - information: Type of "step.detail" is "str"
4-
python/pyi_test/typing_test.py:30:13 - information: Type of "step.payload" is "bytes"
5-
python/pyi_test/typing_test.py:31:13 - information: Type of "step.imported.value" is "str"
6-
python/pyi_test/typing_test.py:32:13 - information: Type of "step.state" is "State"
7-
python/pyi_test/typing_test.py:34:13 - information: Type of "nested.started" is "str"
8-
python/pyi_test/typing_test.py:40:13 - information: Type of "self_fields.something" is "int"
9-
python/pyi_test/typing_test.py:41:13 - information: Type of "self_fields.self" is "str"
10-
python/pyi_test/typing_test.py:42:13 - information: Type of "self_fields.self_" is "str"
11-
python/pyi_test/typing_test.py:44:26 - error: Argument of type "Literal['not bytes']" cannot be assigned to parameter "payload" of type "bytes | None" in function "__init__"
2+
python/pyi_test/typing_test.py:33:13 - information: Type of "step.ok" is "bool"
3+
python/pyi_test/typing_test.py:34:13 - information: Type of "step.detail" is "str"
4+
python/pyi_test/typing_test.py:35:13 - information: Type of "step.payload" is "bytes"
5+
python/pyi_test/typing_test.py:36:13 - information: Type of "step.imported.value" is "str"
6+
python/pyi_test/typing_test.py:37:13 - information: Type of "step.state" is "State"
7+
python/pyi_test/typing_test.py:38:13 - information: Type of "step.WhichOneof("_detail")" is "Literal['detail'] | None"
8+
python/pyi_test/typing_test.py:39:13 - information: Type of "step.WhichOneof("result")" is "Literal['ok', 'error'] | None"
9+
python/pyi_test/typing_test.py:40:13 - information: Type of "step.WhichOneof(b"result")" is "Literal['ok', 'error'] | None"
10+
python/pyi_test/typing_test.py:42:13 - information: Type of "nested.started" is "str"
11+
python/pyi_test/typing_test.py:43:13 - information: Type of "nested.WhichOneof("event")" is "Literal['started', 'finished'] | None"
12+
python/pyi_test/typing_test.py:45:13 - information: Type of "keyword.WhichOneof("choice")" is "Literal['from', 'class'] | None"
13+
python/pyi_test/typing_test.py:47:13 - information: Type of "shadowed.WhichOneof" is "str"
14+
python/pyi_test/typing_test.py:50:13 - information: Type of "action" is "Literal['a', 'b'] | None"
15+
python/pyi_test/typing_test.py:52:17 - information: Type of "step.a" is "str"
16+
python/pyi_test/typing_test.py:54:17 - information: Type of "step.b" is "int"
17+
python/pyi_test/typing_test.py:65:13 - information: Type of "self_fields.something" is "int"
18+
python/pyi_test/typing_test.py:66:13 - information: Type of "self_fields.self" is "str"
19+
python/pyi_test/typing_test.py:67:13 - information: Type of "self_fields.self_" is "str"
20+
python/pyi_test/typing_test.py:69:26 - error: Argument of type "Literal['not bytes']" cannot be assigned to parameter "payload" of type "bytes | None" in function "__init__"
1221
Type "Literal['not bytes']" is not assignable to type "bytes | None"
1322
"Literal['not bytes']" is not assignable to "bytes"
1423
"Literal['not bytes']" is not assignable to "None" (reportArgumentType)
15-
python/pyi_test/typing_test.py:45:16 - error: Cannot assign to attribute "payload" for class "Step"
24+
python/pyi_test/typing_test.py:70:16 - error: Cannot assign to attribute "payload" for class "Step"
1625
"Literal['not bytes']" is not assignable to "bytes" (reportAttributeAccessIssue)
17-
python/pyi_test/typing_test.py:46:18 - error: No parameter named "not_a_field" (reportCallIssue)
18-
3 errors, 0 warnings, 9 informations
26+
python/pyi_test/typing_test.py:71:18 - error: No parameter named "not_a_field" (reportCallIssue)
27+
python/pyi_test/typing_test.py:72:1 - error: No overloads for "WhichOneof" match the provided arguments (reportCallIssue)
28+
python/pyi_test/typing_test.py:72:17 - error: Argument of type "Literal['not_a_oneof']" cannot be assigned to parameter "oneof_group" of type "Literal['_detail', b"_detail"]" in function "WhichOneof"
29+
Type "Literal['not_a_oneof']" is not assignable to type "Literal['_detail', b"_detail"]"
30+
"Literal['not_a_oneof']" is not assignable to type "Literal['_detail']"
31+
"Literal['not_a_oneof']" is not assignable to "Literal[b"_detail"]" (reportArgumentType)
32+
python/pyi_test/typing_test.py:73:1 - error: No overloads for "WhichOneof" match the provided arguments
33+
Argument types: (Literal['action']) (reportCallIssue)
34+
python/pyi_test/typing_test.py:74:24 - error: Argument of type "Literal['not_a_oneof']" cannot be assigned to parameter "oneof_group" of type "NoReturn" in function "WhichOneof"
35+
Type "Literal['not_a_oneof']" is not assignable to type "NoReturn" (reportArgumentType)
36+
python/pyi_test/typing_test.py:81:18 - error: Argument of type "Literal['b']" cannot be assigned to parameter "arg" of type "Never" in function "assert_never"
37+
Type "Literal['b']" is not assignable to type "Never" (reportArgumentType)
38+
8 errors, 0 warnings, 18 informations

python/pyi_test/self_fields_pb2.pyi.golden

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from google.protobuf import descriptor as _descriptor
22
from google.protobuf import message as _message
3-
from typing import ClassVar as _ClassVar, Optional as _Optional
3+
from typing import ClassVar as _ClassVar, NoReturn as _NoReturn, Optional as _Optional
44

55
DESCRIPTOR: _descriptor.FileDescriptor
66

@@ -13,3 +13,4 @@ class SelfFields(_message.Message):
1313
self: str
1414
self_: str
1515
def __init__(self__, something: _Optional[int] = ..., self: _Optional[str] = ..., self_: _Optional[str] = ...) -> None: ...
16+
def WhichOneof(self, oneof_group: _NoReturn, /) -> None: ...

0 commit comments

Comments
 (0)