Skip to content

Commit 578cebe

Browse files
ikonstAlexWaygood
andauthored
protobuf: Annotate well_known_types.pyi (#9323)
Co-authored-by: Alex Waygood <[email protected]>
1 parent 503eab3 commit 578cebe

File tree

4 files changed

+51
-19
lines changed

4 files changed

+51
-19
lines changed

stubs/protobuf/@tests/stubtest_allowlist.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ google.protobuf.internal.containers.BaseContainer.__hash__
3636

3737
# Metaclass differs:
3838
google.protobuf.descriptor.OneofDescriptor
39+
40+
# Runtime does not have __iter__ (yet...): hack in spirit of https://github.com/python/typeshed/issues/7813
41+
google.protobuf.internal.well_known_types.ListValue.__iter__
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# pyright: reportUnnecessaryTypeIgnoreComment=true
2+
from __future__ import annotations
3+
4+
from google.protobuf.struct_pb2 import ListValue, Struct
5+
6+
list_value = ListValue()
7+
8+
lst = list(list_value) # Ensure type checkers recognise that the class is iterable (doesn't have an `__iter__` method at runtime)
9+
10+
list_value[0] = 42.42
11+
list_value[0] = "42"
12+
list_value[0] = None
13+
list_value[0] = True
14+
list_value[0] = [42.42, "42", None, True, [42.42, "42", None, True], {"42": 42}]
15+
list_value[0] = ListValue()
16+
list_value[0] = Struct()
17+
18+
list_element = list_value[0]

stubs/protobuf/google/protobuf/internal/well_known_types.pyi

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
from _typeshed import SupportsItems
2+
from collections.abc import Iterable, Iterator, KeysView, Mapping, Sequence
13
from datetime import datetime, timedelta, tzinfo
24
from typing import Any as tAny
5+
from typing_extensions import TypeAlias
6+
7+
from google.protobuf import struct_pb2
38

49
class Any:
510
type_url: tAny = ...
@@ -63,29 +68,34 @@ class _FieldMaskTree:
6368
def AddLeafNodes(self, prefix: tAny, node: tAny) -> None: ...
6469
def MergeMessage(self, source: tAny, destination: tAny, replace_message: tAny, replace_repeated: tAny) -> None: ...
6570

71+
_StructValue: TypeAlias = struct_pb2.Struct | struct_pb2.ListValue | str | float | bool | None
72+
_StructValueArg: TypeAlias = _StructValue | Mapping[str, _StructValueArg] | Sequence[_StructValueArg]
73+
6674
class Struct:
67-
def __getitem__(self, key: tAny): ...
68-
def __contains__(self, item: tAny): ...
69-
def __setitem__(self, key: tAny, value: tAny) -> None: ...
70-
def __delitem__(self, key: tAny) -> None: ...
75+
def __getitem__(self, key: str) -> _StructValue: ...
76+
def __contains__(self, item: object) -> bool: ...
77+
def __setitem__(self, key: str, value: _StructValueArg) -> None: ...
78+
def __delitem__(self, key: str) -> None: ...
7179
def __len__(self) -> int: ...
72-
def __iter__(self): ...
73-
def keys(self): ...
74-
def values(self): ...
75-
def items(self): ...
76-
def get_or_create_list(self, key: tAny): ...
77-
def get_or_create_struct(self, key: tAny): ...
78-
def update(self, dictionary: tAny) -> None: ...
80+
def __iter__(self) -> Iterator[str]: ...
81+
def keys(self) -> KeysView[str]: ...
82+
def values(self) -> list[_StructValue]: ...
83+
def items(self) -> list[tuple[str, _StructValue]]: ...
84+
def get_or_create_list(self, key: str) -> struct_pb2.ListValue: ...
85+
def get_or_create_struct(self, key: str) -> struct_pb2.Struct: ...
86+
def update(self, dictionary: SupportsItems[str, _StructValueArg]) -> None: ...
7987

8088
class ListValue:
8189
def __len__(self) -> int: ...
82-
def append(self, value: tAny) -> None: ...
83-
def extend(self, elem_seq: tAny) -> None: ...
84-
def __getitem__(self, index: tAny): ...
85-
def __setitem__(self, index: tAny, value: tAny) -> None: ...
86-
def __delitem__(self, key: tAny) -> None: ...
87-
def items(self) -> None: ...
88-
def add_struct(self): ...
89-
def add_list(self): ...
90+
def append(self, value: _StructValue) -> None: ...
91+
def extend(self, elem_seq: Iterable[_StructValue]) -> None: ...
92+
def __getitem__(self, index: int) -> _StructValue: ...
93+
def __setitem__(self, index: int, value: _StructValueArg) -> None: ...
94+
def __delitem__(self, key: int) -> None: ...
95+
# Doesn't actually exist at runtime; needed so type checkers understand the class is iterable
96+
def __iter__(self) -> Iterator[_StructValue]: ...
97+
def items(self) -> Iterator[_StructValue]: ...
98+
def add_struct(self) -> struct_pb2.Struct: ...
99+
def add_list(self) -> struct_pb2.ListValue: ...
90100

91101
WKTBASES: dict[str, type[tAny]]

tests/pytype_exclude_list.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ stubs/protobuf/google/protobuf/internal/decoder.pyi
2727
stubs/protobuf/google/protobuf/internal/encoder.pyi
2828
stubs/protobuf/google/protobuf/internal/enum_type_wrapper.pyi
2929
stubs/protobuf/google/protobuf/internal/extension_dict.pyi
30+
stubs/protobuf/google/protobuf/internal/well_known_types.pyi
3031
stubs/protobuf/google/protobuf/json_format.pyi
3132
stubs/protobuf/google/protobuf/message.pyi
3233
stubs/protobuf/google/protobuf/message_factory.pyi

0 commit comments

Comments
 (0)