def visit_functiondef(self, node: astroid.FunctionDef) -> None: node.inf_type = NoType() # Get the inferred type of the function arguments inferred_args = [ self.lookup_inf_type(node, arg) for arg in node.argnames() ] if isinstance(node.parent, astroid.ClassDef) and inferred_args: # first argument is special in these cases if node.type == 'method': self.type_constraints.unify(inferred_args[0], _ForwardRef(node.parent.name), node) elif node.type == 'classmethod': self.type_constraints.unify( inferred_args[0], Type[_ForwardRef(node.parent.name)], node) # Get inferred return type if any(node.nodes_of_class(astroid.Return)): return_node = list(node.nodes_of_class(astroid.Return))[-1] if isinstance(return_node.inf_type, TypeFail): inferred_return = return_node.inf_type else: inferred_return = self.lookup_inf_type(node, 'return') elif node.name == '__init__' and inferred_args: inferred_return = inferred_args[0] else: inferred_return = TypeInfo(type(None)) # Update the environment storing the function's type. polymorphic_tvars = [] for arg in inferred_args + [inferred_return]: arg >> (lambda a: polymorphic_tvars.append(a.__name__) if isinstance(a, TypeVar) else None) # Create function signature func_type = create_Callable_TypeResult(failable_collect(inferred_args), inferred_return, polymorphic_tvars) # Check for optional arguments, create a Union of function signatures if necessary num_defaults = len(node.args.defaults) if num_defaults > 0 and not isinstance(func_type, TypeFail): for i in range(num_defaults): opt_args = inferred_args[:-1 - i] opt_func_type = create_Callable_TypeResult( failable_collect(opt_args), inferred_return, polymorphic_tvars) func_type = func_type >> ( lambda f: opt_func_type >> (lambda opt_f: TypeInfo(Union[f, opt_f]))) # Final type signature unify func_name = self.lookup_inf_type(node.parent, node.name) result = self.type_constraints.unify(func_name, func_type, node) if isinstance(result, TypeFail): node.inf_type = result
def visit_functiondef(self, node: astroid.FunctionDef) -> None: node.inf_type = NoType() # Get the inferred type of the function arguments inferred_args = [self.lookup_inf_type(node, arg) for arg in node.argnames()] if isinstance(node.parent, astroid.ClassDef) and inferred_args: # first argument is special in these cases if node.type == 'method': self.type_constraints.unify(inferred_args[0], ForwardRef(node.parent.name), node) elif node.type == 'classmethod': self.type_constraints.unify(inferred_args[0], Type[ForwardRef(node.parent.name)], node) # Get inferred return type if any(node.nodes_of_class(astroid.Return)): return_node = list(node.nodes_of_class(astroid.Return))[-1] if isinstance(return_node.inf_type, TypeFail): inferred_return = return_node.inf_type else: inferred_return = self.lookup_inf_type(node, 'return') elif node.name == '__init__' and inferred_args: inferred_return = inferred_args[0] else: inferred_return = TypeInfo(type(None)) # Update the environment storing the function's type. polymorphic_tvars = set() for arg in inferred_args + [inferred_return]: arg >> ( lambda a: polymorphic_tvars.add(a.__name__) if isinstance(a, TypeVar) else None) # Create function signature func_type = create_Callable_TypeResult(failable_collect(inferred_args), inferred_return, polymorphic_tvars) # Check for optional arguments, create a Union of function signatures if necessary num_defaults = len(node.args.defaults) if num_defaults > 0 and not isinstance(func_type, TypeFail): for i in range(num_defaults): opt_args = inferred_args[:-1-i] opt_func_type = create_Callable_TypeResult(failable_collect(opt_args), inferred_return, polymorphic_tvars) func_type = func_type >> ( lambda f: opt_func_type >> ( lambda opt_f: TypeInfo(Union[f, opt_f]))) # Final type signature unify func_name = self.lookup_inf_type(node.parent, node.name) result = self.type_constraints.unify(func_name, func_type, node) if isinstance(result, TypeFail): node.inf_type = result
def visit_functiondef(self, node: astroid.FunctionDef) -> None: node.inf_type = TypeInfo(NoType) # Get the inferred type of the function. inferred_args = [ self.lookup_type(node, arg) for arg in node.argnames() ] if isinstance(node.parent, astroid.ClassDef) and isinstance( inferred_args[0], TypeVar): # first argument is special in these cases if node.type == 'method': self.type_constraints.unify(inferred_args[0], _ForwardRef(node.parent.name), node) elif node.type == 'classmethod': self.type_constraints.unify( inferred_args[0], Type[_ForwardRef(node.parent.name)], node) if any(node.nodes_of_class(astroid.Return)): inferred_return = self.type_constraints.resolve( node.type_environment.lookup_in_env('return')).getValue() else: inferred_return = type(None) # Get any function type annotations. if any(annotation is not None for annotation in node.args.annotations): annotated_type = parse_annotations(node) else: annotated_type = None # Combine inferred and annotated types. if annotated_type: combined_args = [] for inferred, annotated in zip(inferred_args, annotated_type.__args__[:-1]): if annotated is None: annotated = type(None) t = self.type_constraints.unify(inferred, annotated, node).getValue() combined_args.append(t) annotated_rtype = annotated_type.__args__[-1] if annotated_rtype is None: annotated_rtype = type(None) combined_return = self.type_constraints.unify( inferred_return, annotated_rtype, node).getValue() else: combined_args, combined_return = inferred_args, inferred_return # Update the environment storing the function's type. polymorphic_tvars = [ arg for arg in combined_args if isinstance(arg, TypeVar) ] func_type = create_Callable(combined_args, combined_return, polymorphic_tvars) num_defaults = len(node.args.defaults) if num_defaults > 0: for i in range(num_defaults): opt_args = inferred_args[:-1 - i] opt_func_type = create_Callable(opt_args, combined_return, polymorphic_tvars) func_type = Union[func_type, opt_func_type] self.type_constraints.unify(self.lookup_type(node.parent, node.name), func_type, node)