Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use tuple[object, ...] and dict[str, object] as upper bounds for ParamSpec.args and ParamSpec.kwargs #12668

Merged
merged 11 commits into from
Apr 29, 2022
2 changes: 1 addition & 1 deletion mypy/checkmember.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def _analyze_member_access(name: str,
return analyze_typeddict_access(name, typ, mx, override_info)
elif isinstance(typ, NoneType):
return analyze_none_member_access(name, typ, mx)
elif isinstance(typ, TypeVarType):
elif isinstance(typ, TypeVarLikeType):
return _analyze_member_access(name, typ.upper_bound, mx, override_info)
elif isinstance(typ, DeletedType):
mx.msg.deleted_as_rvalue(typ, mx.context)
Expand Down
50 changes: 47 additions & 3 deletions mypy/semanal_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@

from abc import abstractmethod

from typing import Optional, List, Callable
from typing_extensions import Final
from typing import Optional, List, Callable, Union
from typing_extensions import Final, Protocol
from mypy_extensions import trait

from mypy.nodes import (
Context, SymbolTableNode, FuncDef, Node, TypeInfo, Expression,
SymbolNode, SymbolTable
)
from mypy.types import (
Type, FunctionLike, Instance, TupleType, TPDICT_FB_NAMES, ProperType, get_proper_type
Type, FunctionLike, Instance, TupleType, TPDICT_FB_NAMES, ProperType, get_proper_type,
ParamSpecType, ParamSpecFlavor, Parameters, TypeVarId
)
from mypy.tvar_scope import TypeVarLikeScope
from mypy.errorcodes import ErrorCode
Expand Down Expand Up @@ -212,3 +213,46 @@ def calculate_tuple_fallback(typ: TupleType) -> None:
fallback = typ.partial_fallback
assert fallback.type.fullname == 'builtins.tuple'
fallback.args = (join.join_type_list(list(typ.items)),) + fallback.args[1:]


class _NamedTypeCallback(Protocol):
def __call__(
self, fully_qualified_name: str, args: Optional[List[Type]] = None
) -> Instance: ...


def paramspec_args(
name: str, fullname: str, id: Union[TypeVarId, int], *,
named_type_func: _NamedTypeCallback, line: int = -1, column: int = -1,
prefix: Optional[Parameters] = None
) -> ParamSpecType:
return ParamSpecType(
name,
fullname,
id,
flavor=ParamSpecFlavor.ARGS,
upper_bound=named_type_func('builtins.tuple', [named_type_func('builtins.object')]),
line=line,
column=column,
prefix=prefix
)


def paramspec_kwargs(
name: str, fullname: str, id: Union[TypeVarId, int], *,
named_type_func: _NamedTypeCallback, line: int = -1, column: int = -1,
prefix: Optional[Parameters] = None
) -> ParamSpecType:
return ParamSpecType(
name,
fullname,
id,
flavor=ParamSpecFlavor.KWARGS,
upper_bound=named_type_func(
'builtins.dict',
[named_type_func('builtins.str'), named_type_func('builtins.object')]
),
line=line,
column=column,
prefix=prefix
)
30 changes: 13 additions & 17 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from mypy.tvar_scope import TypeVarLikeScope
from mypy.exprtotype import expr_to_unanalyzed_type, TypeTranslationError
from mypy.plugin import Plugin, TypeAnalyzerPluginInterface, AnalyzeTypeContext
from mypy.semanal_shared import SemanticAnalyzerCoreInterface
from mypy.semanal_shared import SemanticAnalyzerCoreInterface, paramspec_args, paramspec_kwargs
from mypy.errorcodes import ErrorCode
from mypy import nodes, message_registry, errorcodes as codes

Expand Down Expand Up @@ -711,13 +711,13 @@ def anal_star_arg_type(self, t: Type, kind: ArgKind, nested: bool) -> Type:
tvar_def = self.tvar_scope.get_binding(sym)
if isinstance(tvar_def, ParamSpecType):
if kind == ARG_STAR:
flavor = ParamSpecFlavor.ARGS
make_paramspec = paramspec_args
elif kind == ARG_STAR2:
flavor = ParamSpecFlavor.KWARGS
make_paramspec = paramspec_kwargs
else:
assert False, kind
return ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, flavor,
upper_bound=self.named_type('builtins.object'),
return make_paramspec(tvar_def.name, tvar_def.fullname, tvar_def.id,
named_type_func=self.named_type,
line=t.line, column=t.column)
return self.anal_type(t, nested=nested)

Expand Down Expand Up @@ -855,13 +855,11 @@ def analyze_callable_args_for_paramspec(
if not isinstance(tvar_def, ParamSpecType):
return None

# TODO: Use tuple[...] or Mapping[..] instead?
obj = self.named_type('builtins.object')
return CallableType(
[ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.ARGS,
upper_bound=obj),
ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.KWARGS,
upper_bound=obj)],
[paramspec_args(tvar_def.name, tvar_def.fullname, tvar_def.id,
named_type_func=self.named_type),
paramspec_kwargs(tvar_def.name, tvar_def.fullname, tvar_def.id,
named_type_func=self.named_type)],
[nodes.ARG_STAR, nodes.ARG_STAR2],
[None, None],
ret_type=ret_type,
Expand Down Expand Up @@ -891,18 +889,16 @@ def analyze_callable_args_for_concatenate(
if not isinstance(tvar_def, ParamSpecType):
return None

# TODO: Use tuple[...] or Mapping[..] instead?
obj = self.named_type('builtins.object')
# ick, CallableType should take ParamSpecType
prefix = tvar_def.prefix
# we don't set the prefix here as generic arguments will get updated at some point
# in the future. CallableType.param_spec() accounts for this.
return CallableType(
[*prefix.arg_types,
ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.ARGS,
upper_bound=obj),
ParamSpecType(tvar_def.name, tvar_def.fullname, tvar_def.id, ParamSpecFlavor.KWARGS,
upper_bound=obj)],
paramspec_args(tvar_def.name, tvar_def.fullname, tvar_def.id,
named_type_func=self.named_type),
paramspec_kwargs(tvar_def.name, tvar_def.fullname, tvar_def.id,
named_type_func=self.named_type)],
[*prefix.arg_kinds, nodes.ARG_STAR, nodes.ARG_STAR2],
[*prefix.arg_names, None, None],
ret_type=ret_type,
Expand Down
Loading