Exemplo n.º 1
0
def _supports_protocol(
    value: astroid.node_classes.NodeNG, protocol_callback: astroid.FunctionDef
) -> bool:
    if isinstance(value, astroid.ClassDef):
        if not has_known_bases(value):
            return True
        # classobj can only be iterable if it has an iterable metaclass
        meta = value.metaclass()
        if meta is not None:
            if protocol_callback(meta):
                return True
    if isinstance(value, astroid.BaseInstance):
        if not has_known_bases(value):
            return True
        if value.has_dynamic_getattr():
            return True
        if protocol_callback(value):
            return True

    # TODO: this is not needed in astroid 2.0, where we can
    # check the type using a virtual base class instead.
    if (
        isinstance(value, _bases.Proxy)
        and isinstance(value._proxied, astroid.BaseInstance)
        and has_known_bases(value._proxied)
    ):
        value = value._proxied
        return protocol_callback(value)

    return False
Exemplo n.º 2
0
def inherit_from_std_ex(node: astroid.node_classes.NodeNG) -> bool:
    """
    Return true if the given class node is subclass of
    exceptions.Exception.
    """
    if node.name in ('Exception', 'BaseException') \
            and node.root().name == EXCEPTIONS_MODULE:
        return True
    if not hasattr(node, 'ancestors'):
        return False
    return any(inherit_from_std_ex(parent)
               for parent in node.ancestors(recurs=True))
Exemplo n.º 3
0
def overrides_a_method(class_node: astroid.node_classes.NodeNG,
                       name: str) -> bool:
    """return True if <name> is a method overridden from an ancestor"""
    for ancestor in class_node.ancestors():
        if name in ancestor and isinstance(ancestor[name], astroid.FunctionDef):
            return True
    return False
Exemplo n.º 4
0
def is_super(node: astroid.node_classes.NodeNG) -> bool:
    """return True if the node is referencing the "super" builtin function
    """
    if getattr(node, 'name', None) == 'super' and \
           node.root().name == BUILTINS_NAME:
        return True
    return False
Exemplo n.º 5
0
def unimplemented_abstract_methods(
    node: astroid.node_classes.NodeNG, is_abstract_cb: astroid.FunctionDef = None
) -> Dict[str, astroid.node_classes.NodeNG]:
    """
    Get the unimplemented abstract methods for the given *node*.

    A method can be considered abstract if the callback *is_abstract_cb*
    returns a ``True`` value. The check defaults to verifying that
    a method is decorated with abstract methods.
    The function will work only for new-style classes. For old-style
    classes, it will simply return an empty dictionary.
    For the rest of them, it will return a dictionary of abstract method
    names and their inferred objects.
    """
    if is_abstract_cb is None:
        is_abstract_cb = partial(decorated_with, qnames=ABC_METHODS)
    visited = {}  # type: Dict[str, astroid.node_classes.NodeNG]
    try:
        mro = reversed(node.mro())
    except NotImplementedError:
        # Old style class, it will not have a mro.
        return {}
    except astroid.ResolveError:
        # Probably inconsistent hierarchy, don'try
        # to figure this out here.
        return {}
    for ancestor in mro:
        for obj in ancestor.values():
            infered = obj
            if isinstance(obj, astroid.AssignName):
                infered = safe_infer(obj)
                if not infered:
                    # Might be an abstract function,
                    # but since we don't have enough information
                    # in order to take this decision, we're taking
                    # the *safe* decision instead.
                    if obj.name in visited:
                        del visited[obj.name]
                    continue
                if not isinstance(infered, astroid.FunctionDef):
                    if obj.name in visited:
                        del visited[obj.name]
            if isinstance(infered, astroid.FunctionDef):
                # It's critical to use the original name,
                # since after inferring, an object can be something
                # else than expected, as in the case of the
                # following assignment.
                #
                # class A:
                #     def keys(self): pass
                #     __iter__ = keys
                abstract = is_abstract_cb(infered)
                if abstract:
                    visited[obj.name] = infered
                elif not abstract and obj.name in visited:
                    del visited[obj.name]
    return visited
Exemplo n.º 6
0
def is_postponed_evaluation_enabled(node: astroid.node_classes.NodeNG) -> bool:
    """Check if the postponed evaluation of annotations is enabled"""
    name = "annotations"
    module = node.root()
    stmt = module.locals.get(name)
    return (
        stmt
        and isinstance(stmt[0], astroid.ImportFrom)
        and stmt[0].modname == "__future__"
    )
Exemplo n.º 7
0
def _supports_protocol_method(value: astroid.node_classes.NodeNG, attr: str) -> bool:
    try:
        attributes = value.getattr(attr)
    except astroid.NotFoundError:
        return False

    first = attributes[0]
    if isinstance(first, astroid.AssignName):
        if isinstance(first.parent.value, astroid.Const):
            return False
    return True
Exemplo n.º 8
0
def is_default_argument(node: astroid.node_classes.NodeNG) -> bool:
    """return true if the given Name node is used in function or lambda
    default argument's value
    """
    parent = node.scope()
    if isinstance(parent, (astroid.FunctionDef, astroid.Lambda)):
        for default_node in parent.args.defaults:
            for default_name_node in default_node.nodes_of_class(astroid.Name):
                if default_name_node is node:
                    return True
    return False
Exemplo n.º 9
0
def node_frame_class(node: astroid.node_classes.NodeNG) -> Optional[astroid.node_classes.NodeNG]:
    """return klass node for a method node (or a staticmethod or a
    classmethod), return null otherwise
    """
    klass = node.frame()

    while klass is not None and not isinstance(klass, astroid.ClassDef):
        if klass.parent is None:
            klass = None
        else:
            klass = klass.parent.frame()

    return klass
Exemplo n.º 10
0
def is_defined_in_scope(
    var_node: astroid.node_classes.NodeNG,
    varname: str,
    scope: astroid.node_classes.NodeNG,
) -> bool:
    if isinstance(scope, astroid.If):
        for node in scope.body:
            if (
                isinstance(node, astroid.Assign)
                and any(
                    isinstance(target, astroid.AssignName) and target.name == varname
                    for target in node.targets
                )
            ) or (isinstance(node, astroid.Nonlocal) and varname in node.names):
                return True
    elif isinstance(scope, (COMP_NODE_TYPES, astroid.For)):
        for ass_node in scope.nodes_of_class(astroid.AssignName):
            if ass_node.name == varname:
                return True
    elif isinstance(scope, astroid.With):
        for expr, ids in scope.items:
            if expr.parent_of(var_node):
                break
            if ids and isinstance(ids, astroid.AssignName) and ids.name == varname:
                return True
    elif isinstance(scope, (astroid.Lambda, astroid.FunctionDef)):
        if scope.args.is_argument(varname):
            # If the name is found inside a default value
            # of a function, then let the search continue
            # in the parent's tree.
            if scope.args.parent_of(var_node):
                try:
                    scope.args.default_value(varname)
                    scope = scope.parent
                    is_defined_in_scope(var_node, varname, scope)
                except astroid.NoDefault:
                    pass
            return True
        if getattr(scope, "name", None) == varname:
            return True
    elif isinstance(scope, astroid.ExceptHandler):
        if isinstance(scope.name, astroid.AssignName):
            ass_node = scope.name
            if ass_node.name == varname:
                return True
    return False
Exemplo n.º 11
0
def node_type(node: astroid.node_classes.NodeNG) -> Optional[type]:
    """Return the inferred type for `node`

    If there is more than one possible type, or if inferred type is Uninferable or None,
    return None
    """
    # check there is only one possible type for the assign node. Else we
    # don't handle it for now
    types = set()
    try:
        for var_type in node.infer():
            if var_type == astroid.Uninferable or is_none(var_type):
                continue
            types.add(var_type)
            if len(types) > 1:
                return None
    except astroid.InferenceError:
        return None
    return types.pop() if types else None
Exemplo n.º 12
0
def safe_infer(node: astroid.node_classes.NodeNG,
               context=None) -> Optional[astroid.node_classes.NodeNG]:
    """Return the inferred value for the given node.

    Return None if inference failed or if there is some ambiguity (more than
    one node has been inferred).
    """
    try:
        inferit = node.infer(context=context)
        value = next(inferit)
    except astroid.InferenceError:
        return None
    try:
        next(inferit)
        return None # None if there is ambiguity on the inferred node
    except astroid.InferenceError:
        return None # there is some kind of ambiguity
    except StopIteration:
        return value
Exemplo n.º 13
0
def clobber_in_except(node: astroid.node_classes.NodeNG) -> Tuple[bool, Tuple[str, str]]:
    """Checks if an assignment node in an except handler clobbers an existing
    variable.

    Returns (True, args for W0623) if assignment clobbers an existing variable,
    (False, None) otherwise.
    """
    if isinstance(node, astroid.AssignAttr):
        return True, (node.attrname, 'object %r' % (node.expr.as_string(),))
    if isinstance(node, astroid.AssignName):
        name = node.name
        if is_builtin(name):
            return (True, (name, 'builtins'))

        stmts = node.lookup(name)[1]
        if (stmts and not isinstance(stmts[0].assign_type(),
                                     (astroid.Assign, astroid.AugAssign,
                                      astroid.ExceptHandler))):
            return True, (name, 'outer scope (line %s)' % stmts[0].fromlineno)
    return False, None
Exemplo n.º 14
0
def clobber_in_except(
    node: astroid.node_classes.NodeNG,
) -> Tuple[bool, Optional[Tuple[str, str]]]:
    """Checks if an assignment node in an except handler clobbers an existing
    variable.

    Returns (True, args for W0623) if assignment clobbers an existing variable,
    (False, None) otherwise.
    """
    if isinstance(node, astroid.AssignAttr):
        return True, (node.attrname, "object %r" % (node.expr.as_string(),))
    if isinstance(node, astroid.AssignName):
        name = node.name
        if is_builtin(name):
            return True, (name, "builtins")

        stmts = node.lookup(name)[1]
        if stmts and not isinstance(
            stmts[0].assign_type(),
            (astroid.Assign, astroid.AugAssign, astroid.ExceptHandler),
        ):
            return True, (name, "outer scope (line %s)" % stmts[0].fromlineno)
    return False, None
Exemplo n.º 15
0
def node_frame_class(node: astroid.node_classes.NodeNG) -> Optional[astroid.ClassDef]:
    """Return the class that is wrapping the given node

    The function returns a class for a method node (or a staticmethod or a
    classmethod), otherwise it returns `None`.
    """
    klass = node.frame()
    nodes_to_check = (
        astroid.node_classes.NodeNG,
        astroid.UnboundMethod,
        astroid.BaseInstance,
    )
    while (
        klass
        and isinstance(klass, nodes_to_check)
        and not isinstance(klass, astroid.ClassDef)
    ):
        if klass.parent is None:
            klass = None
        else:
            klass = klass.parent.frame()

    return klass
Exemplo n.º 16
0
def is_defined_before(var_node: astroid.node_classes.NodeNG) -> bool:
    """return True if the variable node is defined by a parent node (list,
    set, dict, or generator comprehension, lambda) or in a previous sibling
    node on the same line (statement_defining ; statement_using)
    """
    varname = var_node.name
    _node = var_node.parent
    while _node:
        if is_defined_in_scope(var_node, varname, _node):
            return True
        _node = _node.parent
    # possibly multiple statements on the same line using semi colon separator
    stmt = var_node.statement()
    _node = stmt.previous_sibling()
    lineno = stmt.fromlineno
    while _node and _node.fromlineno == lineno:
        for assign_node in _node.nodes_of_class(astroid.AssignName):
            if assign_node.name == varname:
                return True
        for imp_node in _node.nodes_of_class((astroid.ImportFrom, astroid.Import)):
            if varname in [name[1] or name[0] for name in imp_node.names]:
                return True
        _node = _node.previous_sibling()
    return False
Exemplo n.º 17
0
def is_defined_before(var_node: astroid.node_classes.NodeNG) -> bool:
    """return True if the variable node is defined by a parent node (list,
    set, dict, or generator comprehension, lambda) or in a previous sibling
    node on the same line (statement_defining ; statement_using)
    """
    varname = var_node.name
    _node = var_node.parent
    while _node:
        if is_defined_in_scope(var_node, varname, _node):
            return True
        _node = _node.parent
    # possibly multiple statements on the same line using semi colon separator
    stmt = var_node.statement()
    _node = stmt.previous_sibling()
    lineno = stmt.fromlineno
    while _node and _node.fromlineno == lineno:
        for assign_node in _node.nodes_of_class(astroid.AssignName):
            if assign_node.name == varname:
                return True
        for imp_node in _node.nodes_of_class((astroid.ImportFrom, astroid.Import)):
            if varname in [name[1] or name[0] for name in imp_node.names]:
                return True
        _node = _node.previous_sibling()
    return False
Exemplo n.º 18
0
def is_error(node: astroid.node_classes.NodeNG) -> bool:
    """return true if the function does nothing but raising an exception"""
    for child_node in node.get_children():
        if isinstance(child_node, astroid.Raise):
            return True
    return False
Exemplo n.º 19
0
 def visit_generic(self, node: astroid.node_classes.NodeNG) -> None:
     """Propagate the visit to the children."""
     for child in node.get_children():
         self.visit(child)
Exemplo n.º 20
0
def overrides_a_method(class_node: astroid.node_classes.NodeNG, name: str) -> bool:
    """return True if <name> is a method overridden from an ancestor"""
    for ancestor in class_node.ancestors():
        if name in ancestor and isinstance(ancestor[name], astroid.FunctionDef):
            return True
    return False
Exemplo n.º 21
0
def is_postponed_evaluation_enabled(node: astroid.node_classes.NodeNG) -> bool:
    """Check if the postponed evaluation of annotations is enabled"""
    module = node.root()
    return "annotations" in module.future_imports
Exemplo n.º 22
0
def is_error(node: astroid.node_classes.NodeNG) -> bool:
    """return true if the function does nothing but raising an exception"""
    for child_node in node.get_children():
        if isinstance(child_node, astroid.Raise):
            return True
    return False
Exemplo n.º 23
0
def is_super(node: astroid.node_classes.NodeNG) -> bool:
    """return True if the node is referencing the "super" builtin function"""
    if getattr(node, "name",
               None) == "super" and node.root().name == BUILTINS_NAME:
        return True
    return False
Exemplo n.º 24
0
def is_builtin_object(node: astroid.node_classes.NodeNG) -> bool:
    """Returns True if the given node is an object from the __builtin__ module."""
    return node and node.root().name == BUILTINS_NAME
Exemplo n.º 25
0
def is_builtin_object(node: astroid.node_classes.NodeNG) -> bool:
    """Returns True if the given node is an object from the __builtin__ module."""
    return node and node.root().name == BUILTINS_NAME
Exemplo n.º 26
0
def is_postponed_evaluation_enabled(node: astroid.node_classes.NodeNG) -> bool:
    """Check if the postponed evaluation of annotations is enabled"""
    name = 'annotations'
    module = node.root()
    stmt = module.locals.get(name)
    return stmt and isinstance(stmt[0], astroid.ImportFrom) and stmt[0].modname == '__future__'