[ty] Support Unpack[TypedDict] in **kwargs signatures#24653
[ty] Support Unpack[TypedDict] in **kwargs signatures#24653charliermarsh wants to merge 3 commits intomainfrom
Unpack[TypedDict] in **kwargs signatures#24653Conversation
Typing conformance results improved 🎉The percentage of diagnostics emitted that were expected errors increased from 87.94% to 88.34%. The percentage of expected errors that received a diagnostic increased from 83.36% to 84.42%. The number of fully passing files improved from 79/133 to 81/133. SummaryHow are test cases classified?Each test case represents one expected error annotation or a group of annotations sharing a tag. Counts are per test case, not per diagnostic — multiple diagnostics on the same line count as one. Required annotations (
Test file breakdown3 files altered
True positives added (11)11 diagnostics
False positives removed (4)4 diagnostics
True positives changed (2)2 diagnostics
False positives added (1)1 diagnostic
Optional Diagnostics Added (1)1 diagnostic
|
Memory usage reportSummary
Significant changesClick to expand detailed breakdownprefect
sphinx
trio
flake8
|
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-argument-type |
90 | 1 | 5 |
unused-type-ignore-comment |
0 | 36 | 0 |
unknown-argument |
31 | 0 | 0 |
invalid-type-form |
11 | 0 | 0 |
no-matching-overload |
8 | 0 | 0 |
invalid-method-override |
3 | 0 | 0 |
not-subscriptable |
0 | 3 | 0 |
invalid-return-type |
1 | 1 | 0 |
unresolved-attribute |
0 | 2 | 0 |
invalid-assignment |
0 | 1 | 0 |
type-assertion-failure |
0 | 1 | 0 |
| Total | 144 | 45 | 5 |
Raw diff (194 changes)
aiohttp-devtools (https://github.com/aio-libs/aiohttp-devtools)
+ aiohttp_devtools/runserver/watch.py:120:55 error[invalid-argument-type] Argument to bound method `ClientSession.get` is incorrect: Expected `SSLContext | bool | Fingerprint`, found `None | SSLContext`
+ aiohttp_devtools/runserver/watch.py:155:57 error[invalid-argument-type] Argument to bound method `ClientSession.get` is incorrect: Expected `SSLContext | bool | Fingerprint`, found `None | SSLContext`
altair (https://github.com/vega/altair)
- altair/datasets/_constraints.py:54:24 error[invalid-return-type] Return type does not match returned value: expected `Metadata`, found `dict[str, @Todo]`
- altair/datasets/_constraints.py:108:33 error[invalid-argument-type] Argument to bound method `MetaIs.from_metadata` is incorrect: Expected `Metadata`, found `dict[str, @Todo]`
- altair/utils/core.py:680:18 error[unresolved-attribute] Attribute `schema` is not defined on `NativeDataFrame`, `DataFrameLike`, `None` in union `NativeDataFrame | DataFrameLike | Unknown | None`
- altair/utils/core.py:682:22 error[not-subscriptable] Cannot subscript object of type `DataFrameLike` with no `__getitem__` method
- altair/utils/core.py:682:22 error[not-subscriptable] Cannot subscript object of type `NativeDataFrame` with no `__getitem__` method
- altair/utils/core.py:682:22 error[not-subscriptable] Cannot subscript object of type `None` with no `__getitem__` method
- altair/utils/core.py:686:39 error[unresolved-attribute] Attribute `to_native` is not defined on `NativeDataFrame`, `DataFrameLike`, `None` in union `NativeDataFrame | DataFrameLike | Unknown | None`
bokeh (https://github.com/bokeh/bokeh)
+ src/bokeh/plotting/_graph.py:131:9 error[invalid-argument-type] Argument to `GlyphRenderer.__init__` is incorrect: Argument type `Glyph | None` does not satisfy upper bound `Glyph` of type variable `GlyphType`
+ src/bokeh/plotting/_graph.py:131:9 error[invalid-argument-type] Argument to `GlyphRenderer.__init__` is incorrect: Expected `Glyph`, found `Glyph | None`
+ src/bokeh/plotting/_graph.py:149:9 error[invalid-argument-type] Argument to `GlyphRenderer.__init__` is incorrect: Argument type `Glyph | None` does not satisfy upper bound `Glyph` of type variable `GlyphType`
+ src/bokeh/plotting/_graph.py:149:9 error[invalid-argument-type] Argument to `GlyphRenderer.__init__` is incorrect: Expected `Glyph`, found `Glyph | None`
+ src/bokeh/transform.py:155:13 error[invalid-argument-type] Argument to `EqHistColorMapper.__init__` is incorrect: Expected `Sequence[str | tuple[int, int, int] | tuple[int, int, int, int | float]]`, found `Sequence[str | Color | tuple[int, int, int] | tuple[int, int, int, int | float]]`
+ src/bokeh/transform.py:158:13 error[invalid-argument-type] Argument to `EqHistColorMapper.__init__` is incorrect: Expected `str | tuple[int, int, int] | tuple[int, int, int, int | float]`, found `str | Color | tuple[int, int, int] | tuple[int, int, int, int | float]`
+ src/bokeh/transform.py:159:13 error[invalid-argument-type] Argument to `EqHistColorMapper.__init__` is incorrect: Expected `str | tuple[int, int, int] | tuple[int, int, int, int | float] | None`, found `str | Color | tuple[int, int, int] | tuple[int, int, int, int | float] | None`
+ src/bokeh/transform.py:160:13 error[invalid-argument-type] Argument to `EqHistColorMapper.__init__` is incorrect: Expected `str | tuple[int, int, int] | tuple[int, int, int, int | float] | None`, found `str | Color | tuple[int, int, int] | tuple[int, int, int, int | float] | None`
+ src/bokeh/transform.py:200:13 error[invalid-argument-type] Argument to `CategoricalColorMapper.__init__` is incorrect: Expected `Sequence[str | tuple[int, int, int] | tuple[int, int, int, int | float]]`, found `Sequence[str | Color | tuple[int, int, int] | tuple[int, int, int, int | float]]`
+ src/bokeh/transform.py:202:13 error[invalid-argument-type] Argument to `CategoricalColorMapper.__init__` is incorrect: Expected `int`, found `int | float`
+ src/bokeh/transform.py:203:13 error[invalid-argument-type] Argument to `CategoricalColorMapper.__init__` is incorrect: Expected `int | None`, found `int | float | None`
+ src/bokeh/transform.py:204:13 error[invalid-argument-type] Argument to `CategoricalColorMapper.__init__` is incorrect: Expected `str | tuple[int, int, int] | tuple[int, int, int, int | float]`, found `str | Color | tuple[int, int, int] | tuple[int, int, int, int | float]`
+ src/bokeh/transform.py:242:13 error[invalid-argument-type] Argument to `CategoricalPatternMapper.__init__` is incorrect: Expected `Sequence[Property[Literal["blank", "dot", "ring", "horizontal_line", "vertical_line", ... omitted 29 literals]]]`, found `Sequence[str]`
+ src/bokeh/transform.py:244:13 error[invalid-argument-type] Argument to `CategoricalPatternMapper.__init__` is incorrect: Expected `int`, found `int | float`
+ src/bokeh/transform.py:245:13 error[invalid-argument-type] Argument to `CategoricalPatternMapper.__init__` is incorrect: Expected `int | None`, found `int | float | None`
+ src/bokeh/transform.py:285:13 error[invalid-argument-type] Argument to `CategoricalMarkerMapper.__init__` is incorrect: Expected `Sequence[Literal["asterisk", "circle", "circle_cross", "circle_dot", "circle_x", ... omitted 23 literals]]`, found `Sequence[str]`
+ src/bokeh/transform.py:287:13 error[invalid-argument-type] Argument to `CategoricalMarkerMapper.__init__` is incorrect: Expected `int`, found `int | float`
+ src/bokeh/transform.py:288:13 error[invalid-argument-type] Argument to `CategoricalMarkerMapper.__init__` is incorrect: Expected `int | None`, found `int | float | None`
+ src/bokeh/transform.py:368:13 error[invalid-argument-type] Argument to `LinearColorMapper.__init__` is incorrect: Expected `Sequence[str | tuple[int, int, int] | tuple[int, int, int, int | float]]`, found `Sequence[str | Color | tuple[int, int, int] | tuple[int, int, int, int | float]]`
+ src/bokeh/transform.py:371:13 error[invalid-argument-type] Argument to `LinearColorMapper.__init__` is incorrect: Expected `str | tuple[int, int, int] | tuple[int, int, int, int | float]`, found `str | Color | tuple[int, int, int] | tuple[int, int, int, int | float]`
+ src/bokeh/transform.py:372:13 error[invalid-argument-type] Argument to `LinearColorMapper.__init__` is incorrect: Expected `str | tuple[int, int, int] | tuple[int, int, int, int | float] | None`, found `str | Color | tuple[int, int, int] | tuple[int, int, int, int | float] | None`
+ src/bokeh/transform.py:373:13 error[invalid-argument-type] Argument to `LinearColorMapper.__init__` is incorrect: Expected `str | tuple[int, int, int] | tuple[int, int, int, int | float] | None`, found `str | Color | tuple[int, int, int] | tuple[int, int, int, int | float] | None`
+ src/bokeh/transform.py:415:13 error[invalid-argument-type] Argument to `LogColorMapper.__init__` is incorrect: Expected `Sequence[str | tuple[int, int, int] | tuple[int, int, int, int | float]]`, found `Sequence[str | Color | tuple[int, int, int] | tuple[int, int, int, int | float]]`
+ src/bokeh/transform.py:418:13 error[invalid-argument-type] Argument to `LogColorMapper.__init__` is incorrect: Expected `str | tuple[int, int, int] | tuple[int, int, int, int | float]`, found `str | Color | tuple[int, int, int] | tuple[int, int, int, int | float]`
+ src/bokeh/transform.py:419:13 error[invalid-argument-type] Argument to `LogColorMapper.__init__` is incorrect: Expected `str | tuple[int, int, int] | tuple[int, int, int, int | float] | None`, found `str | Color | tuple[int, int, int] | tuple[int, int, int, int | float] | None`
+ src/bokeh/transform.py:420:13 error[invalid-argument-type] Argument to `LogColorMapper.__init__` is incorrect: Expected `str | tuple[int, int, int] | tuple[int, int, int, int | float] | None`, found `str | Color | tuple[int, int, int] | tuple[int, int, int, int | float] | None`
+ src/bokeh/layouts.py:384:9 error[invalid-argument-type] Argument to `Toolbar.__init__` is incorrect: Expected `Literal["normal", "grey"] | None`, found `Literal["normal", "grey"] | None | UndefinedType`
+ src/bokeh/layouts.py:385:9 error[invalid-argument-type] Argument to `Toolbar.__init__` is incorrect: Expected `bool`, found `bool | UndefinedType`
+ src/bokeh/layouts.py:386:9 error[invalid-argument-type] Argument to `Toolbar.__init__` is incorrect: Expected `Literal["auto"] | Drag | ToolProxy | None`, found `ToolProxy | Tool | UndefinedType`
+ src/bokeh/layouts.py:387:9 error[invalid-argument-type] Argument to `Toolbar.__init__` is incorrect: Expected `Literal["auto"] | InspectTool | ToolProxy | Sequence[InspectTool] | None`, found `ToolProxy | Tool | UndefinedType`
+ src/bokeh/layouts.py:388:9 error[invalid-argument-type] Argument to `Toolbar.__init__` is incorrect: Expected `Literal["auto"] | Scroll | ToolProxy | None`, found `ToolProxy | Tool | UndefinedType`
+ src/bokeh/layouts.py:389:9 error[invalid-argument-type] Argument to `Toolbar.__init__` is incorrect: Expected `Literal["auto"] | Tap | ToolProxy | None`, found `ToolProxy | Tool | UndefinedType`
+ src/bokeh/layouts.py:390:9 error[invalid-argument-type] Argument to `Toolbar.__init__` is incorrect: Expected `Literal["auto"] | GestureTool | ToolProxy | None`, found `ToolProxy | Tool | UndefinedType`
+ src/bokeh/layouts.py:394:9 error[unknown-argument] Argument `children` does not match any known parameter of `GridPlot.__init__`
+ src/bokeh/models/renderers/contour_renderer.py:112:13 error[invalid-argument-type] Argument to `ContourColorBar.__init__` is incorrect: Expected `GlyphRenderer[Glyph]`, found `Instance[GlyphRenderer[Unknown]]`
+ src/bokeh/models/renderers/contour_renderer.py:113:13 error[invalid-argument-type] Argument to `ContourColorBar.__init__` is incorrect: Expected `GlyphRenderer[Glyph]`, found `Instance[GlyphRenderer[Unknown]]`
+ src/bokeh/models/renderers/contour_renderer.py:114:13 error[invalid-argument-type] Argument to `ContourColorBar.__init__` is incorrect: Expected `Sequence[int | float]`, found `Seq[T@Seq]`
+ src/bokeh/models/renderers/contour_renderer.py:115:32 error[invalid-argument-type] Argument to `FixedTicker.__init__` is incorrect: Expected `Sequence[int | float]`, found `Seq[T@Seq]`
- src/bokeh/models/renderers/graph_renderer.py:84:45 error[invalid-argument-type] Argument to `Object.__init__` is incorrect: Argument type `() -> GlyphRenderer[Unknown]` does not satisfy upper bound `Serializable` of type variable `S`
+ src/bokeh/models/renderers/graph_renderer.py:84:45 error[invalid-argument-type] Argument to `Object.__init__` is incorrect: Argument type `() -> GlyphRenderer[Scatter]` does not satisfy upper bound `Serializable` of type variable `S`
- src/bokeh/models/renderers/graph_renderer.py:84:45 error[invalid-argument-type] Argument to `Object.__init__` is incorrect: Expected `GlyphRenderer[Unknown] | UndefinedType | IntrinsicType`, found `() -> GlyphRenderer[Unknown]`
+ src/bokeh/models/renderers/graph_renderer.py:84:45 error[invalid-argument-type] Argument to `Object.__init__` is incorrect: Expected `GlyphRenderer[Unknown] | UndefinedType | IntrinsicType`, found `() -> GlyphRenderer[Scatter]`
- src/bokeh/models/renderers/graph_renderer.py:89:45 error[invalid-argument-type] Argument to `Object.__init__` is incorrect: Argument type `() -> GlyphRenderer[Unknown]` does not satisfy upper bound `Serializable` of type variable `S`
+ src/bokeh/models/renderers/graph_renderer.py:89:45 error[invalid-argument-type] Argument to `Object.__init__` is incorrect: Argument type `() -> GlyphRenderer[MultiLine]` does not satisfy upper bound `Serializable` of type variable `S`
- src/bokeh/models/renderers/graph_renderer.py:89:45 error[invalid-argument-type] Argument to `Object.__init__` is incorrect: Expected `GlyphRenderer[Unknown] | UndefinedType | IntrinsicType`, found `() -> GlyphRenderer[Unknown]`
+ src/bokeh/models/renderers/graph_renderer.py:89:45 error[invalid-argument-type] Argument to `Object.__init__` is incorrect: Expected `GlyphRenderer[Unknown] | UndefinedType | IntrinsicType`, found `() -> GlyphRenderer[MultiLine]`
+ src/bokeh/plotting/_figure.py:243:41 error[invalid-argument-type] Argument to `CoordinateMapping.__init__` is incorrect: Expected `Range`, found `Range | None`
+ src/bokeh/plotting/_figure.py:243:60 error[invalid-argument-type] Argument to `CoordinateMapping.__init__` is incorrect: Expected `Range`, found `Range | None`
+ src/bokeh/plotting/_geo_feature.pyi:24:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_geo_feature.pyi:31:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_geo_feature.pyi:38:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_geo_feature.pyi:45:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_geo_feature.pyi:52:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_geo_feature.pyi:59:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_geo_feature.pyi:66:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_geo_feature.pyi:73:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_geo_feature.pyi:79:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_geo_feature.pyi:86:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_geo_feature.pyi:93:24 error[invalid-type-form] Unpacked value for `**kwargs` must be a TypedDict, not `Unknown`
+ src/bokeh/plotting/_plot.py:98:32 error[invalid-argument-type] Argument to `Range1d.__init__` is incorrect: Expected `int | float | datetime | timedelta`, found `int | float | (Unknown & ~None) | str | IntrinsicType`
+ src/bokeh/plotting/_plot.py:98:45 error[invalid-argument-type] Argument to `Range1d.__init__` is incorrect: Expected `int | float | datetime | timedelta`, found `int | float | (Unknown & ~None) | str | IntrinsicType`
+ src/bokeh/plotting/_renderer.py:127:9 error[invalid-argument-type] Argument to `GlyphRenderer.__init__` is incorrect: Argument type `Glyph | None` does not satisfy upper bound `Glyph` of type variable `GlyphType`
+ src/bokeh/plotting/_renderer.py:127:9 error[invalid-argument-type] Argument to `GlyphRenderer.__init__` is incorrect: Expected `Glyph`, found `Glyph | None`
+ src/bokeh/plotting/_renderer.py:139:56 error[invalid-argument-type] Argument to function `update_legend` is incorrect: Expected `GlyphRenderer[Glyph]`, found `GlyphRenderer[GlyphType@GlyphRenderer]`
+ src/bokeh/plotting/_renderer.py:141:12 error[invalid-return-type] Return type does not match returned value: expected `GlyphRenderer[Glyph]`, found `GlyphRenderer[GlyphType@GlyphRenderer]`
discord.py (https://github.com/Rapptz/discord.py)
- discord/permissions.py:216:48 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/permissions.py:488:46 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ discord/shard.py:380:50 error[unknown-argument] Argument `shard_connect_timeout` does not match any known parameter of `Client.__init__`
+ discord/shard.py:380:50 error[unknown-argument] Argument `shard_ids` does not match any known parameter of `Client.__init__`
+ discord/shard.py:380:50 error[invalid-argument-type] Argument to `Client.__init__` is incorrect: Expected `Status | None`, found `int | None`
+ discord/shard.py:380:50 error[invalid-argument-type] Argument to `Client.__init__` is incorrect: Expected `int | None`, found `int | float | None`
- discord/ext/commands/bot.py:294:59 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/bot.py:306:48 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/bot.py:307:107 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/bot.py:318:57 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/bot.py:330:48 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/bot.py:331:105 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/core.py:1551:48 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/core.py:1608:48 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `CooldownMapping[Context[Any]]`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `MaxConcurrency`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `bool`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `bool`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `bool`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `bool`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `bool`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `bool`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `dict[Any, Any]`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `list[(Context[Any], /) -> bool | Coroutine[Any, Any, bool]]`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `list[str] | tuple[str, ...]`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `str | None`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `str | None`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `str | None`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `str`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:602:38 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `str`, found `Any | list[str] | tuple[str, ...] | ... omitted 7 union elements`
+ discord/ext/commands/core.py:1859:12 error[no-matching-overload] No overload of function `command` matches arguments
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `arguments_heading` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `commands_heading` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `default_argument_description` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `dm_help_threshold` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `dm_help` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `indent` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `no_category` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `paginator` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `show_parameter_descriptions` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `sort_commands` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[unknown-argument] Argument `width` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1087:26 error[invalid-argument-type] Argument to `HelpCommand.__init__` is incorrect: Expected `_CommandKwargs`, found `str`
+ discord/ext/commands/help.py:1087:26 error[invalid-argument-type] Argument to `HelpCommand.__init__` is incorrect: Expected `bool | None`, found `str`
+ discord/ext/commands/help.py:1087:26 error[invalid-argument-type] Argument to `HelpCommand.__init__` is incorrect: Expected `bool`, found `_CommandKwargs`
+ discord/ext/commands/help.py:1378:26 error[unknown-argument] Argument `aliases_heading` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1378:26 error[unknown-argument] Argument `commands_heading` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1378:26 error[unknown-argument] Argument `dm_help_threshold` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1378:26 error[unknown-argument] Argument `dm_help` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1378:26 error[unknown-argument] Argument `no_category` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1378:26 error[unknown-argument] Argument `paginator` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1378:26 error[unknown-argument] Argument `sort_commands` does not match any known parameter of `HelpCommand.__init__`
+ discord/ext/commands/help.py:1378:26 error[invalid-argument-type] Argument to `HelpCommand.__init__` is incorrect: Expected `_CommandKwargs`, found `str`
+ discord/ext/commands/help.py:1378:26 error[invalid-argument-type] Argument to `HelpCommand.__init__` is incorrect: Expected `bool | None`, found `str`
+ discord/ext/commands/help.py:1378:26 error[invalid-argument-type] Argument to `HelpCommand.__init__` is incorrect: Expected `bool`, found `_CommandKwargs`
- discord/ext/commands/hybrid.py:517:50 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:641:47 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:849:59 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:861:48 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:862:107 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:873:57 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:885:48 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:886:105 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:897:54 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:940:92 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:949:52 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:973:90 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ discord/ext/commands/hybrid.py:528:32 error[unknown-argument] Argument `default_permissions` does not match any known parameter of `Command.__init__`
+ discord/ext/commands/hybrid.py:528:32 error[unknown-argument] Argument `guild_ids` does not match any known parameter of `Command.__init__`
+ discord/ext/commands/hybrid.py:528:32 error[unknown-argument] Argument `guild_only` does not match any known parameter of `Command.__init__`
+ discord/ext/commands/hybrid.py:528:32 error[unknown-argument] Argument `nsfw` does not match any known parameter of `Command.__init__`
+ discord/ext/commands/hybrid.py:528:32 error[unknown-argument] Argument `with_app_command` does not match any known parameter of `Command.__init__`
+ discord/ext/commands/hybrid.py:528:32 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `MaxConcurrency`, found `str | None`
+ discord/ext/commands/hybrid.py:528:32 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `bool`, found `MaxConcurrency`
+ discord/ext/commands/hybrid.py:528:32 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `bool`, found `list[int]`
+ discord/ext/commands/hybrid.py:528:32 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `bool`, found `str`
+ discord/ext/commands/hybrid.py:528:32 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `dict[Any, Any]`, found `bool`
+ discord/ext/commands/hybrid.py:528:32 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `str | None`, found `dict[Any, Any]`
+ discord/ext/commands/hybrid.py:528:32 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `str`, found `bool`
+ discord/ext/commands/hybrid.py:528:32 error[invalid-argument-type] Argument to `Command.__init__` is incorrect: Expected `str`, found `bool`
+ discord/ext/commands/hybrid.py:651:33 error[unknown-argument] Argument `default_permissions` does not match any known parameter of `Group.__init__`
+ discord/ext/commands/hybrid.py:651:33 error[unknown-argument] Argument `guild_ids` does not match any known parameter of `Group.__init__`
+ discord/ext/commands/hybrid.py:651:33 error[unknown-argument] Argument `guild_only` does not match any known parameter of `Group.__init__`
+ discord/ext/commands/hybrid.py:651:33 error[unknown-argument] Argument `nsfw` does not match any known parameter of `Group.__init__`
+ discord/ext/commands/hybrid.py:651:33 error[unknown-argument] Argument `with_app_command` does not match any known parameter of `Group.__init__`
+ discord/ext/commands/hybrid.py:651:33 error[invalid-argument-type] Argument to `Group.__init__` is incorrect: Expected `MaxConcurrency`, found `str | None`
+ discord/ext/commands/hybrid.py:651:33 error[invalid-argument-type] Argument to `Group.__init__` is incorrect: Expected `bool`, found `MaxConcurrency`
+ discord/ext/commands/hybrid.py:651:33 error[invalid-argument-type] Argument to `Group.__init__` is incorrect: Expected `bool`, found `list[int]`
+ discord/ext/commands/hybrid.py:651:33 error[invalid-argument-type] Argument to `Group.__init__` is incorrect: Expected `bool`, found `str`
+ discord/ext/commands/hybrid.py:651:33 error[invalid-argument-type] Argument to `Group.__init__` is incorrect: Expected `dict[Any, Any]`, found `bool`
+ discord/ext/commands/hybrid.py:651:33 error[invalid-argument-type] Argument to `Group.__init__` is incorrect: Expected `str | None`, found `dict[Any, Any]`
+ discord/ext/commands/hybrid.py:651:33 error[invalid-argument-type] Argument to `Group.__init__` is incorrect: Expected `str`, found `bool`
+ discord/ext/commands/hybrid.py:651:33 error[invalid-argument-type] Argument to `Group.__init__` is incorrect: Expected `str`, found `bool`
+ discord/ext/commands/hybrid.py:844:9 error[invalid-method-override] Invalid override of method `command`: Definition is incompatible with `GroupMixin.command`
+ discord/ext/commands/hybrid.py:868:9 error[invalid-method-override] Invalid override of method `group`: Definition is incompatible with `GroupMixin.group`
hydpy (https://github.com/hydpy-dev/hydpy)
+ hydpy/models/rconc/rconc_control.py:249:23 error[no-matching-overload] No overload of `dict.__init__` matches arguments
pandas (https://github.com/pandas-dev/pandas)
- pandas/io/parsers/readers.py:1604:41 error[invalid-argument-type] Argument to function `len` is incorrect: Expected `Sized`, found `(@Todo & ~Literal[False] & ~_NoDefault) | None`
+ pandas/io/parsers/readers.py:1604:41 error[invalid-argument-type] Argument to function `len` is incorrect: Expected `Sized`, found `Hashable & ~Literal[False] & ~_NoDefault`
+ pandas/tests/io/parser/test_read_fwf.py:986:26 error[invalid-argument-type] Argument to function `read_fwf` is incorrect: Expected `Literal["pyarrow", "numpy_nullable"] | _NoDefault`, found `Literal["numpy"]`
+ pandas/tests/io/parser/test_unsupported.py:43:17 error[no-matching-overload] No overload of function `read_csv` matches arguments
+ pandas/tests/io/test_common.py:442:13 error[no-matching-overload] No overload of function `read_csv` matches arguments
prefect (https://github.com/PrefectHQ/prefect)
+ src/integrations/prefect-dbt/prefect_dbt/core/_orchestrator.py:1916:25 error[invalid-argument-type] Argument to `MaterializingTask.__init__` is incorrect: Expected `list[Asset | str] | None`, found `(list[Asset] & ~AlwaysFalsy) | None`
+ src/integrations/prefect-gitlab/prefect_gitlab/repositories.py:90:32 error[no-matching-overload] No overload of function `Field` matches arguments
+ src/prefect/tasks.py:2218:9 error[invalid-method-override] Invalid override of method `with_options`: Definition is incompatible with `Task.with_options`
pydantic (https://github.com/pydantic/pydantic)
- pydantic/fields.py:239:95 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- pydantic/fields.py:278:57 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- pydantic/fields.py:1278:39 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- pydantic/fields.py:1282:47 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- pydantic/fields.py:1292:47 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- pydantic/fields.py:1302:53 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- pydantic/fields.py:1312:57 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- pydantic/fields.py:1322:39 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- pydantic/fields.py:1335:40 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- pydantic/fields.py:1350:43 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
+ pydantic/fields.py:669:16 error[no-matching-overload] No overload of function `Field` matches arguments
pyinstrument (https://github.com/joerick/pyinstrument)
- pyinstrument/context_manager.py:41:9 error[invalid-assignment] Object of type `dict[str, @Todo]` is not assignable to attribute `options` of type `ProfileContextOptions`
pywin32 (https://github.com/mhammond/pywin32)
+ com/win32comext/shell/demos/servers/folder_view.py:855:9 error[invalid-argument-type] Argument to function `UseCommandLine` is incorrect: Expected `bool`, found `Literal[0]`
+ com/win32comext/shell/demos/servers/shell_view.py:968:9 error[invalid-argument-type] Argument to function `UseCommandLine` is incorrect: Expected `bool`, found `Literal[0]`
rotki (https://github.com/rotki/rotki)
+ rotkehlchen/tests/db/test_db.py:407:20 error[no-matching-overload] No overload of bound method `DBHandler.get_dynamic_cache` matches arguments
+ rotkehlchen/tests/db/test_db.py:447:20 error[no-matching-overload] No overload of bound method `DBHandler.get_dynamic_cache` matches arguments
scipy-stubs (https://github.com/scipy/scipy-stubs)
- tests/stats/test_new_distributions.pyi:15:1 error[type-assertion-failure] Type `Normal[tuple[()], float64]` does not match asserted type `Normal[tuple[int], floating]`
trio (https://github.com/python-trio/trio)
- src/trio/_tests/test_subprocess.py:497:55 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- src/trio/_tests/type_tests/subprocesses.py:15:70 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- src/trio/_tests/type_tests/subprocesses.py:22:60 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- src/trio/_tests/type_tests/subprocesses.py:23:70 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive1b9a9bd to
ffd2dca
Compare
Merging this PR will not alter performance
Comparing Footnotes
|
| has_starred_annotation: bool, | ||
|
|
||
| /// Whether this parameter was declared as `**kwargs: Unpack[TypedDict]`. | ||
| has_unpacked_kwargs_annotation: bool, |
There was a problem hiding this comment.
This lets us distinguish **kwargs: Unpack[TD] from **kwargs: TD. The latter means that every kwarg value is itself of type TD.
| /// Per [PEP 692](https://peps.python.org/pep-0692/#typeddict-unions), unions (for example) are not | ||
| /// allowed in such annotations. |
There was a problem hiding this comment.
Slightly annoying because we already have some logic for extracting these keys in the more general case (see, e.g., extract_unpacked_typed_dict_keys_from_value_type), but PEP 692 explicitly forbids unions.
| /// The argument definitely binds this parameter. | ||
| Definitive, | ||
| /// The argument may bind this parameter at runtime, but does not guarantee its presence. | ||
| Provisional, |
There was a problem hiding this comment.
This is necessary for cases like...
class MaybeX(TypedDict, total=False):
x: str
def takes_x(*, x: int) -> None: ...
takes_x(**maybe_x)Where we need to report both missing-argument and invalid-argument-type.
|
For the ecosystem report...
Based on Codex's analysis, the rest are either true positives or things that are sufficiently dynamic that we shouldn't really expect to model them. But I'll go through a few more on my own. |
ce5fe61 to
8b766df
Compare
|
Also, note that the newly-added false positive on the conformance tests is related to |
|
|
||
| ## `Unpack[TypedDict]` in `**kwargs` | ||
|
|
||
| Using `Unpack[TypedDict]` on a `**kwargs` parameter should expose the `TypedDict` shape both inside |
There was a problem hiding this comment.
I haven't read the mdtest but could we split this test into multiple smaller snippets with some prose between snippets explaining what's being tested and what the expected behavior is?
This is one of my main learnings from maintaining Ruff. The long fixture files are a pain to maintain over time because they lack context of why something has been tested in the first place and if it's even asserting something intentionally or if they just tried to be exhaustive.
There was a problem hiding this comment.
This is awesome! Will be great to have this feature.
I reviewed the tests and some of the implementation; there are enough findings that might change enough of the implementation that I think it makes sense to do an iteration before reviewing more.
One meta-comment is that I think this is a case where the PR might have (understandably) suffered a bit of scope-creep. I think there are really two separable things addressed here. One is TypedDict unpacking on the formal-parameter side using Unpack (which is really just a matter of signature transformation, and a bit of code to infer the right type within the function body). The other is the whole Provisional matched argument thing, which is all about caller-side actual-argument unpacked TypedDict, and doesn't actually care whether the formal parameter is from an Unpack[TD] or just regular keyword arguments.
I think it would clarify the PR and the review if we separated those concerns into separate PRs.
| explicit_ok: ExplicitKwargs = func | ||
| typed_dict_ok: TypedDictKwargs = func |
There was a problem hiding this comment.
This is good; I'd also love to see this:
def _(explicit: ExplicitKwargs, typed_dict: TypedDictKwargs) -> None:
typed_dict_2: TypedDictKwargs = explicit
explicit_2: ExplicitKwargs = typed_dictI think these two lines should both pass, but currently the first one fails. I believe the reason is the same bug causing this to fail:
from typing import Protocol
from typing_extensions import TypedDict, Unpack
class TD(TypedDict, total=False):
a: int
def f(**kwargs: Unpack[TD]) -> None:
pass
class WantsB(Protocol):
def __call__(self, *, b: TD) -> None: ...
# BUG: this PR accepts this assignment, because it treats the retained
# `**kwargs: TD` as accepting arbitrary keyword names.
p: WantsB = f
# But the actual call surface of `f` does not accept `b`.
# ty correctly reports this as an unknown argument.
f(b={})I think the root cause of both is that we retain the **kwargs argument in the signature of a callable with **kwargs: Unpack[TD], when really we should treat that callable as if it did not have **kwargs.
| def func7(*, v1: int, v3: str, v2: str = "") -> None: | ||
| pass | ||
|
|
||
| # error: [invalid-assignment] | ||
| typed_dict_bad: TypedDictKwargs = func7 |
There was a problem hiding this comment.
Why do we expect invalid-assignment here? It looks to me like this assignment should succeed. func7 has the same signature that we should be treating TypedDictKwargs as having.
There was a problem hiding this comment.
Agreed; this should be accepted.
| class TD2(TD1): | ||
| v3: Required[str] | ||
|
|
||
| def func5(v1: int, **kwargs: Unpack[TD2]) -> None: # error: [invalid-type-form] |
There was a problem hiding this comment.
invalid-type-form feels weird for this one, since the type form Unpack[TD2] is just fine, what's invalid is the overall function signature. But I don't know of any better fitting code, and I don't think this is worth its own dedicated code. The non-Unpack version of this is just a syntax error, and this isn't, so that parallel doesn't help either. So I guess this really is our best option. Other type checkers also tend to use the same code for this as for the cases where the Unpack expression itself is malformed, so at least we're in good company.
| ### Regression coverage | ||
|
|
||
| These cases check a few tricky edges: unpacking non-string-keyed mappings, combining explicit | ||
| keyword arguments with unpacked `TypedDict`s, missing required keys from partial `TypedDict`s, and | ||
| legacy dunder-style keyword names. |
There was a problem hiding this comment.
Not to be a pain, but this is kind of a weird catch-all. It would be nicer to split these out into separate tests, each with their own prose...
There was a problem hiding this comment.
Also wording nit: "legacy dunder-style positional-only parameters"
| /// The key is guaranteed to be present at runtime when the mapping is unpacked. | ||
| Guaranteed, | ||
| /// The key may be present at runtime when the mapping is unpacked. | ||
| Potential, |
There was a problem hiding this comment.
Hmm... is there a good reason for us (here and in method names below) to invent new terminology that means the same thing as Required and NotRequired, which is the syntax that is actually used in defining a TypedDict key?
| from typing import Any | ||
| from typing_extensions import TypedDict, Unpack | ||
|
|
||
| class AnyKwargs(TypedDict, total=False): |
There was a problem hiding this comment.
Nit: I find this name confusing, because there is nothing Any related about this typed-dict type.
| if let Some((parameter_index, parameter, _)) = | ||
| self.parameters.unpacked_typed_dict_keyword_variadic(db) | ||
| { | ||
| let permissive_any_mapping = argument_type.is_some_and(|argument_type| { |
There was a problem hiding this comment.
Commented above on the tests -- I don't think it is correct to specially handle dict[str, Any]. All dict[str, ...] types should be forgiving in argument matching (but of course should still require that ... is assignable to each matched formal parameter, which is always true for Any).
We (and all type checkers) have the same forgiving behavior for e.g. * unpacking of list[int] -- we optimistically assume the list is the right length for the available parameters. But we still require that int be assignable to each matched parameter.
| /// Per [PEP 692](https://peps.python.org/pep-0692/#typeddict-unions), this accepts only a concrete | ||
| /// `TypedDict` target, or a type alias resolving to one. |
There was a problem hiding this comment.
I think it is always implied that stringified annotations should be supported too, but this function doesn't support them. All other type checkers support this:
from typing_extensions import TypedDict, Unpack
class TD(TypedDict):
a: int
def f(**kwargs: "Unpack[TD]") -> None:
reveal_type(kwargs) # should be TD
# should be accepted, same as an unquoted `Unpack[TD]`.
f(a=1)| } | ||
| } | ||
|
|
||
| value.push(keywords); |
There was a problem hiding this comment.
I think in order to fix some of the assignability bugs I mentioned in the tests, and remove the need for some special casing in call binding, we should eliminate this line -- the original **kwargs: Unpack[TD] parameter should not stay as part of the signature proper.
This might (not totally sure without trying it) require keeping a bit (or index?) around somewhere in the signature recording that this transformation happened, so that we can still refer to the original kwargs argument in diagnostics, detect arguments duplicated via this unpacking, etc. But I think it's important that we do that in a dedicated way that doesn't affect the signature itself, and is only used for these additional validation/diagnostic purposes.
(Keeping the **kwargs argument around in the signature is not necessary for properly inferring the type of kwargs inside the function. That goes through a totally separate Definition path that leads directly to the annotation on **kwargs, it doesn't go through a callable signature at all.)
There was a problem hiding this comment.
(The normalization is inside Parameters::new, but we now do roughly this.)
|
Great review, thank you. |
9387793 to
7bbef3b
Compare
Unpack[TypedDict]Unpack[TypedDict] in **kwargs signatures
7033e83 to
a7096ef
Compare
|
I pulled the validation changes out into #24710 -- sorry about that. |
|
We no longer emit this error from the conformance suite, looking into it: from typing import Protocol, TypeVar, TypedDict, NotRequired, Required, Unpack, assert_type
class TD1(TypedDict):
v1: Required[int]
v2: NotRequired[str]
class TD2(TD1):
v3: Required[str]
...
class TDProtocol6(Protocol):
def __call__(self, **kwargs: Unpack[TD2]) -> None:
...
...
# > The situation where the destination callable contains **kwargs: Unpack[TypedDict] and
# > the source callable doesn’t contain **kwargs should be disallowed. This is because,
# > we cannot be sure that additional keyword arguments are not being passed in when an instance of a subclass
# > had been assigned to a variable with a base class type and then unpacked in the destination callable invocation
def func7(*, v1: int, v3: str, v2: str = "") -> None:
...
v7: TDProtocol6 = func7 # E: source does not have kwargs |
a7096ef to
6b6ef50
Compare
|
(Fixed.) |
0b571b6 to
f3253e8
Compare
|
Looks like the latest rebase here has some logical conflicts causing it to not compile. |
f3253e8 to
a407396
Compare
|
Fixed, sorry about that. |
| # error: [unknown-argument] | ||
| func(v1=1, v3="ok", v4=1) |
There was a problem hiding this comment.
I think erroring here is wrong, but the conformance suite currently requires it :/
Wrote up python/typing#2272
Not sure if you'd rather just hold off on this PR until we see what the reaction to that is from other typing council members (I'd expect to get some responses in the next day or two), or if you'd rather land this now (either my preferred way, or the conformance suite way), and then possibly update the behavior later depending what happens with my conformance suite PR).
There was a problem hiding this comment.
I agree that this likely shouldn't error. I'd probably err on the side of just merging and updating later if the PR is otherwise ready, but it's also okay if you'd prefer to wait.
Summary
We now support
Unpack[TypedDict]as an annotation on**kwargs, as in the following example: