Skip to content

Commit ede00cb

Browse files
committed
Implement closed support in stubgen
1 parent 8b65bd5 commit ede00cb

2 files changed

Lines changed: 26 additions & 7 deletions

File tree

mypy/stubgen.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,9 +1094,13 @@ def process_typeddict(self, lvalue: NameExpr, rvalue: CallExpr) -> None:
10941094
if not isinstance(rvalue.args[0], StrExpr):
10951095
self.annotate_as_incomplete(lvalue)
10961096
return
1097+
if len(rvalue.args) > 2 and rvalue.arg_kinds[2] != ARG_NAMED:
1098+
self.annotate_as_incomplete(lvalue)
1099+
return
10971100

10981101
items: list[tuple[str, Expression]] = []
10991102
total: Expression | None = None
1103+
closed: Expression | None = None
11001104
if len(rvalue.args) > 1 and rvalue.arg_kinds[1] == ARG_POS:
11011105
if not isinstance(rvalue.args[1], DictExpr):
11021106
self.annotate_as_incomplete(lvalue)
@@ -1106,11 +1110,14 @@ def process_typeddict(self, lvalue: NameExpr, rvalue: CallExpr) -> None:
11061110
self.annotate_as_incomplete(lvalue)
11071111
return
11081112
items.append((attr_name.value, attr_type))
1109-
if len(rvalue.args) > 2:
1110-
if rvalue.arg_kinds[2] != ARG_NAMED or rvalue.arg_names[2] != "total":
1113+
for arg_name, arg in zip(rvalue.arg_names[2:], rvalue.args[2:]):
1114+
if arg_name == "total":
1115+
total = arg
1116+
elif arg_name == "closed":
1117+
closed = arg
1118+
else:
11111119
self.annotate_as_incomplete(lvalue)
11121120
return
1113-
total = rvalue.args[2]
11141121
else:
11151122
for arg_name, arg in zip(rvalue.arg_names[1:], rvalue.args[1:]):
11161123
if not isinstance(arg_name, str):
@@ -1130,6 +1137,8 @@ def process_typeddict(self, lvalue: NameExpr, rvalue: CallExpr) -> None:
11301137
# TODO: Add support for generic TypedDicts. Requires `Generic` as base class.
11311138
if total is not None:
11321139
bases += f", total={total.accept(p)}"
1140+
if closed is not None:
1141+
bases += f", closed={closed.accept(p)}"
11331142
class_def = f"{self._indent}class {lvalue.name}({bases}):"
11341143
if len(items) == 0:
11351144
self.add(f"{class_def} ...\n")

test-data/unit/stubgen.test

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3822,16 +3822,26 @@ def f(x: str | None) -> None: ...
38223822

38233823
[case testTypeddict]
38243824
import typing, x
3825-
X = typing.TypedDict('X', {'a': int, 'b': str})
3826-
Y = typing.TypedDict('X', {'a': int, 'b': str}, total=False)
3825+
D1 = typing.TypedDict('D1', {'a': int, 'b': str})
3826+
D2 = typing.TypedDict('D2', {'a': int, 'b': str}, total=False)
3827+
D3 = typing.TypedDict('D3', {'a': int, 'b': str}, closed=True)
3828+
D4 = typing.TypedDict('D4', {'a': int, 'b': str}, closed=True, total=False)
38273829
[out]
38283830
from typing_extensions import TypedDict
38293831

3830-
class X(TypedDict):
3832+
class D1(TypedDict):
38313833
a: int
38323834
b: str
38333835

3834-
class Y(TypedDict, total=False):
3836+
class D2(TypedDict, total=False):
3837+
a: int
3838+
b: str
3839+
3840+
class D3(TypedDict, closed=True):
3841+
a: int
3842+
b: str
3843+
3844+
class D4(TypedDict, total=False, closed=True):
38353845
a: int
38363846
b: str
38373847

0 commit comments

Comments
 (0)