Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
Adds a new method to a class.
This can be dropped if/when https://github.com/python/mypy/issues/7301 is merged
"""
info = ctx.cls.info
# First remove any previously generated methods with the same name
# to avoid clashes and problems in the semantic analyzer.
if name in info.names:
sym = info.names[name]
if sym.plugin_generated and isinstance(sym.node, FuncDef):
ctx.cls.defs.body.remove(sym.node)
self_type = self_type or fill_typevars(info)
if is_classmethod or is_new:
first = [Argument(Var('_cls'), TypeType.make_normalized(self_type), None, ARG_POS)]
# elif is_staticmethod:
# first = []
else:
self_type = self_type or fill_typevars(info)
first = [Argument(Var('self'), self_type, None, ARG_POS)]
args = first + args
arg_types, arg_names, arg_kinds = [], [], []
for arg in args:
assert arg.type_annotation, 'All arguments must be fully typed.'
arg_types.append(arg.type_annotation)
arg_names.append(get_name(arg.variable))
arg_kinds.append(arg.kind)
function_type = ctx.api.named_type('__builtins__.function')
signature = CallableType(arg_types, arg_kinds, arg_names, return_type, function_type)
if tvar_def:
def visit_type_type(self, t: TypeType) -> Type:
if isinstance(self.s, TypeType):
return TypeType(self.join(t.item, self.s.item), line=t.line)
elif isinstance(self.s, Instance) and self.s.type.fullname() == 'builtins.type':
return self.s
else:
return self.default(self.s)
self.gs2d = Instance(self.gs2i, [self.d]) # GS2[D]
self.hab = Instance(self.hi, [self.a, self.b]) # H[A, B]
self.haa = Instance(self.hi, [self.a, self.a]) # H[A, A]
self.hbb = Instance(self.hi, [self.b, self.b]) # H[B, B]
self.hts = Instance(self.hi, [self.t, self.s]) # H[T, S]
self.had = Instance(self.hi, [self.a, self.d]) # H[A, D]
self.lsta = Instance(self.std_listi, [self.a]) # List[A]
self.lstb = Instance(self.std_listi, [self.b]) # List[B]
self.type_a = TypeType(self.a)
self.type_b = TypeType(self.b)
self.type_c = TypeType(self.c)
self.type_d = TypeType(self.d)
self.type_t = TypeType(self.t)
self.type_any = TypeType(self.anyt)
def get_specified_form_class(object_type: Instance) -> Optional[TypeType]:
form_class_sym = object_type.type.get('form_class')
if form_class_sym and isinstance(form_class_sym.type, CallableType):
return TypeType(form_class_sym.type.ret_type)
return None
callee = self.infer_function_type_arguments(
callee, args, arg_kinds, formal_to_actual, context)
arg_types = self.infer_arg_types_in_context2(
callee, args, arg_kinds, formal_to_actual)
self.check_argument_count(callee, arg_types, arg_kinds,
arg_names, formal_to_actual, context, self.msg)
self.check_argument_types(arg_types, arg_kinds, callee,
formal_to_actual, context,
messages=arg_messages)
if (callee.is_type_obj() and (len(arg_types) == 1)
and is_equivalent(callee.ret_type, self.named_type('builtins.type'))):
callee = callee.copy_modified(ret_type=TypeType.make_normalized(arg_types[0]))
if callable_node:
# Store the inferred callable type.
self.chk.store_type(callable_node, callee)
if (callable_name
and ((object_type is None and self.plugin.get_function_hook(callable_name))
or (object_type is not None
and self.plugin.get_method_hook(callable_name)))):
ret_type = self.apply_function_plugin(
arg_types, callee.ret_type, arg_kinds, formal_to_actual,
args, len(callee.arg_types), callable_name, object_type, context)
callee = callee.copy_modified(ret_type=ret_type)
return callee.ret_type, callee
elif isinstance(callee, Overloaded):
# Type check arguments in empty context. They will be checked again
def visit_instance(self, t: Instance) -> Type:
if isinstance(self.s, Instance):
return join_instances(t, self.s)
elif isinstance(self.s, FunctionLike):
return join_types(t, self.s.fallback)
elif isinstance(self.s, TypeType):
return join_types(t, self.s)
else:
return self.default(self.s)
def visit_type_type(self, t: TypeType) -> ProperType:
return TypeType.make_normalized(t.item.accept(self), line=t.line)
self.gs2d = Instance(self.gs2i, [self.d]) # GS2[D]
self.hab = Instance(self.hi, [self.a, self.b]) # H[A, B]
self.haa = Instance(self.hi, [self.a, self.a]) # H[A, A]
self.hbb = Instance(self.hi, [self.b, self.b]) # H[B, B]
self.hts = Instance(self.hi, [self.t, self.s]) # H[T, S]
self.had = Instance(self.hi, [self.a, self.d]) # H[A, D]
self.lsta = Instance(self.std_listi, [self.a]) # List[A]
self.lstb = Instance(self.std_listi, [self.b]) # List[B]
self.type_a = TypeType.make_normalized(self.a)
self.type_b = TypeType.make_normalized(self.b)
self.type_c = TypeType.make_normalized(self.c)
self.type_d = TypeType.make_normalized(self.d)
self.type_t = TypeType.make_normalized(self.t)
self.type_any = TypeType.make_normalized(self.anyt)
def visit_type_type(self, t: TypeType) -> ProperType:
if isinstance(self.s, TypeType):
return TypeType.make_normalized(self.join(t.item, self.s.item), line=t.line)
elif isinstance(self.s, Instance) and self.s.type.fullname == 'builtins.type':
return self.s
else:
return self.default(self.s)
self_param_type = get_proper_type(func.arg_types[0])
if func.variables and supported_self_type(self_param_type):
if original_type is None:
# TODO: type check method override (see #7861).
original_type = erase_to_bound(self_param_type)
original_type = get_proper_type(original_type)
all_ids = [x.id for x in func.variables]
typeargs = infer_type_arguments(all_ids, self_param_type, original_type,
is_supertype=True)
if (is_classmethod
# TODO: why do we need the extra guards here?
and any(isinstance(get_proper_type(t), UninhabitedType) for t in typeargs)
and isinstance(original_type, (Instance, TypeVarType, TupleType))):
# In case we call a classmethod through an instance x, fallback to type(x)
typeargs = infer_type_arguments(all_ids, self_param_type, TypeType(original_type),
is_supertype=True)
ids = [tid for tid in all_ids
if any(tid == t.id for t in get_type_vars(self_param_type))]
# Technically, some constrains might be unsolvable, make them .
to_apply = [t if t is not None else UninhabitedType() for t in typeargs]
def expand(target: Type) -> Type:
return expand_type(target, {id: to_apply[all_ids.index(id)] for id in ids})
arg_types = [expand(x) for x in func.arg_types[1:]]
ret_type = expand(func.ret_type)
variables = [v for v in func.variables if v.id not in ids]
else:
arg_types = func.arg_types[1:]