|
4 | 4 | from typing_extensions import Final
|
5 | 5 |
|
6 | 6 | from mypy.nodes import (
|
7 |
| - ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_POS, MDEF, Argument, AssignmentStmt, CallExpr, |
8 |
| - Context, Expression, JsonDict, NameExpr, RefExpr, |
9 |
| - SymbolTableNode, TempNode, TypeInfo, Var, TypeVarExpr, PlaceholderNode |
| 7 | + ARG_OPT, ARG_NAMED, ARG_NAMED_OPT, ARG_POS, ARG_STAR, ARG_STAR2, MDEF, |
| 8 | + Argument, AssignmentStmt, CallExpr, Context, Expression, JsonDict, |
| 9 | + NameExpr, RefExpr, SymbolTableNode, TempNode, TypeInfo, Var, TypeVarExpr, |
| 10 | + PlaceholderNode |
10 | 11 | )
|
11 | 12 | from mypy.plugin import ClassDefContext, SemanticAnalyzerPluginInterface
|
12 | 13 | from mypy.plugins.common import (
|
@@ -141,11 +142,28 @@ def transform(self) -> None:
|
141 | 142 | if (decorator_arguments['init'] and
|
142 | 143 | ('__init__' not in info.names or info.names['__init__'].plugin_generated) and
|
143 | 144 | attributes):
|
| 145 | + |
| 146 | + args = [attr.to_argument() for attr in attributes if attr.is_in_init |
| 147 | + and not self._is_kw_only_type(attr.type)] |
| 148 | + |
| 149 | + if info.fallback_to_any: |
| 150 | + # Make positional args optional since we don't know their order. |
| 151 | + # This will at least allow us to typecheck them if they are called |
| 152 | + # as kwargs |
| 153 | + for arg in args: |
| 154 | + if arg.kind == ARG_POS: |
| 155 | + arg.kind = ARG_OPT |
| 156 | + |
| 157 | + nameless_var = Var('') |
| 158 | + args = [Argument(nameless_var, AnyType(TypeOfAny.explicit), None, ARG_STAR), |
| 159 | + *args, |
| 160 | + Argument(nameless_var, AnyType(TypeOfAny.explicit), None, ARG_STAR2), |
| 161 | + ] |
| 162 | + |
144 | 163 | add_method(
|
145 | 164 | ctx,
|
146 | 165 | '__init__',
|
147 |
| - args=[attr.to_argument() for attr in attributes if attr.is_in_init |
148 |
| - and not self._is_kw_only_type(attr.type)], |
| 166 | + args=args, |
149 | 167 | return_type=NoneType(),
|
150 | 168 | )
|
151 | 169 |
|
|
0 commit comments