예제 #1
0
    def visit_function(self, node):
        """visit function: update consumption analysis variable and check locals
        """
        self._to_consume.append((copy(node.locals), {}, 'function'))
        if not (self.linter.is_message_enabled('redefined-outer-name')
                or self.linter.is_message_enabled('redefined-builtin')):
            return
        globs = node.root().globals
        for name, stmt in node.items():
            if is_inside_except(stmt):
                continue
            if name in globs and not isinstance(stmt, astroid.Global):
                definition = globs[name][0]
                if (isinstance(definition, astroid.From)
                        and definition.modname == FUTURE):
                    # It is a __future__ directive, not a symbol.
                    continue

                line = definition.fromlineno
                dummy_rgx = self.config.dummy_variables_rgx
                if not dummy_rgx.match(name):
                    self.add_message('redefined-outer-name',
                                     args=(name, line),
                                     node=stmt)
            elif is_builtin(name):
                # do not print Redefining builtin for additional builtins
                self.add_message('redefined-builtin', args=name, node=stmt)
예제 #2
0
 def visit_module(self, node):
     """visit module : update consumption analysis variable
     checks globals doesn't overrides builtins
     """
     self._to_consume = [(copy(node.locals), {}, 'module')]
     for name, stmts in six.iteritems(node.locals):
         if is_builtin(name) and not is_inside_except(stmts[0]):
             # do not print Redefining builtin for additional builtins
             self.add_message('redefined-builtin', args=name, node=stmts[0])
예제 #3
0
 def visit_module(self, node):
     """visit module : update consumption analysis variable
     checks globals doesn't overrides builtins
     """
     self._to_consume = [(copy(node.locals), {}, 'module')]
     for name, stmts in six.iteritems(node.locals):
         if is_builtin(name) and not is_inside_except(stmts[0]):
             # do not print Redefining builtin for additional builtins
             self.add_message('redefined-builtin', args=name, node=stmts[0])
예제 #4
0
파일: variables.py 프로젝트: imcj/pybbs
 def visit_module(self, node):
     """visit module : update consumption analysis variable
     checks globals doesn't overrides builtins
     """
     self._to_consume = [(copy(node.locals), {}, 'module')]
     self._vars = []
     for name, stmts in node.locals.items():
         if is_builtin(name):
             # do not print Redefining builtin for additional builtins
             self.add_message('W0622', args=name, node=stmts[0])
예제 #5
0
 def visit_module(self, node):
     """visit module : update consumption analysis variable
     checks globals doesn't overrides builtins
     """
     self._to_consume = [(copy(node.locals), {}, 'module')]
     self._vars = []
     for name, stmts in node.locals.items():
         if is_builtin(name):
             # do not print Redefining builtin for additional builtins
             self.add_message('W0622', args=name, node=stmts[0])
 def test_is_builtin(self):
     self.assertEqual(utils.is_builtin('min'), True)
     self.assertEqual(utils.is_builtin('__builtins__'), True)
     self.assertEqual(utils.is_builtin('__path__'), False)
     self.assertEqual(utils.is_builtin('__file__'), False)
     self.assertEqual(utils.is_builtin('whatever'), False)
     self.assertEqual(utils.is_builtin('mybuiltin'), False)
 def test_is_builtin(self):
     self.assertEqual(utils.is_builtin('min'), True)
     self.assertEqual(utils.is_builtin('__builtins__'), True)
     self.assertEqual(utils.is_builtin('__path__'), False)
     self.assertEqual(utils.is_builtin('__file__'), False)
     self.assertEqual(utils.is_builtin('whatever'), False)
     self.assertEqual(utils.is_builtin('mybuiltin'), False)
예제 #8
0
파일: variables.py 프로젝트: imcj/pybbs
 def visit_function(self, node):
     """visit function: update consumption analysis variable and check locals
     """
     globs = node.root().globals
     for name, stmt in node.items():
         if name in globs and not isinstance(stmt, astng.Global):
             line = globs[name][0].lineno
             self.add_message('W0621', args=(name, line), node=stmt)
         elif is_builtin(name):
             # do not print Redefining builtin for additional builtins
             self.add_message('W0622', args=name, node=stmt)
     self._to_consume.append((copy(node.locals), {}, 'function'))
     self._vars.append({})
예제 #9
0
 def visit_function(self, node):
     """visit function: update consumption analysis variable and check locals
     """
     globs = node.root().globals
     for name, stmt in node.items():
         if globs.has_key(name) and not isinstance(stmt, astng.Global):
             line = globs[name][0].lineno
             self.add_message('W0621', args=(name, line), node=stmt)
         elif is_builtin(name):
             # do not print Redefining builtin for additional builtins
             self.add_message('W0622', args=name, node=stmt)
     self._to_consume.append((copy(node.locals), {}, 'function'))
     self._vars.append({})
예제 #10
0
    def leave_module(self, node):
        """ Update consumption analysis variable
        for metaclasses.
        """
        module_locals = self._to_consume[0][0]
        module_imports = self._to_consume[0][1]
        consumed = {}

        for klass in node.nodes_of_class(astroid.Class):
            found = metaclass = name = None
            if not klass._metaclass:
                # Skip if this class doesn't use
                # explictly a metaclass, but inherits it from ancestors
                continue

            metaclass = klass.metaclass()

            # Look the name in the already found locals.
            # If it's not found there, look in the module locals
            # and in the imported modules.
            if isinstance(klass._metaclass, astroid.Name):
                name = klass._metaclass.name
            elif metaclass:
                # if it uses a `metaclass=module.Class`
                name = metaclass.root().name

            if name:
                found = consumed.setdefault(
                    name, module_locals.get(name, module_imports.get(name)))

            if found is None and not metaclass:
                name = None
                if isinstance(klass._metaclass, astroid.Name):
                    name = klass._metaclass.name
                elif isinstance(klass._metaclass, astroid.Getattr):
                    name = klass._metaclass.as_string()

                if name is not None:
                    if not (name in astroid.Module.scope_attrs
                            or is_builtin(name)
                            or name in self.config.additional_builtins
                            or name in node.locals):
                        self.add_message('undefined-variable',
                                         node=klass,
                                         args=(name, ))
        # Pop the consumed items, in order to
        # avoid having unused-import false positives
        for name in consumed:
            module_locals.pop(name, None)
        super(VariablesChecker3k, self).leave_module(node)
예제 #11
0
    def leave_module(self, node):
        """ Update consumption analysis variable
        for metaclasses.
        """
        module_locals = self._to_consume[0][0]
        module_imports = self._to_consume[0][1]
        consumed = {}

        for klass in node.nodes_of_class(astroid.Class):
            found = metaclass = name = None
            if not klass._metaclass:
                # Skip if this class doesn't use
                # explictly a metaclass, but inherits it from ancestors
                continue

            metaclass = klass.metaclass()

            # Look the name in the already found locals.
            # If it's not found there, look in the module locals
            # and in the imported modules.
            if isinstance(klass._metaclass, astroid.Name):
                name = klass._metaclass.name
            elif metaclass:
                # if it uses a `metaclass=module.Class`
                name = metaclass.root().name

            if name:
                found = consumed.setdefault(
                    name, module_locals.get(name, module_imports.get(name)))

            if found is None and not metaclass:
                name = None
                if isinstance(klass._metaclass, astroid.Name):
                    name = klass._metaclass.name
                elif isinstance(klass._metaclass, astroid.Getattr):
                    name = klass._metaclass.as_string()

                if name is not None:
                    if not (name in astroid.Module.scope_attrs or
                            is_builtin(name) or
                            name in self.config.additional_builtins or
                            name in node.locals):
                        self.add_message('undefined-variable',
                                         node=klass,
                                         args=(name, ))
        # Pop the consumed items, in order to
        # avoid having unused-import false positives
        for name in consumed:
            module_locals.pop(name, None)
        super(VariablesChecker3k, self).leave_module(node)
예제 #12
0
파일: variables.py 프로젝트: DINKIN/XDM
 def visit_function(self, node):
     """visit function: update consumption analysis variable and check locals
     """
     self._to_consume.append((copy(node.locals), {}, 'function'))
     if not set(('W0621', 'W0622')) & self.active_msgs:
         return
     globs = node.root().globals
     for name, stmt in node.items():
         if is_inside_except(stmt):
             continue
         if name in globs and not isinstance(stmt, astng.Global):
             line = globs[name][0].fromlineno
             self.add_message('W0621', args=(name, line), node=stmt)
         elif is_builtin(name):
             # do not print Redefining builtin for additional builtins
             self.add_message('W0622', args=name, node=stmt)
예제 #13
0
 def visit_function(self, node):
     """visit function: update consumption analysis variable and check locals
     """
     self._to_consume.append((copy(node.locals), {}, 'function'))
     if not set(('W0621', 'W0622')) & self.active_msgs:
         return
     globs = node.root().globals
     for name, stmt in node.items():
         if is_inside_except(stmt):
             continue
         if name in globs and not isinstance(stmt, astng.Global):
             line = globs[name][0].fromlineno
             self.add_message('W0621', args=(name, line), node=stmt)
         elif is_builtin(name):
             # do not print Redefining builtin for additional builtins
             self.add_message('W0622', args=name, node=stmt)
예제 #14
0
 def visit_function(self, node):
     """visit function: update consumption analysis variable and check locals
     """
     self._to_consume.append((copy(node.locals), {}, 'function'))
     if not (self.linter.is_message_enabled('redefined-outer-name') or
             self.linter.is_message_enabled('redefined-builtin')):
         return
     globs = node.root().globals
     for name, stmt in node.items():
         if is_inside_except(stmt):
             continue
         if name in globs and not isinstance(stmt, astroid.Global):
             line = globs[name][0].fromlineno
             dummy_rgx = self.config.dummy_variables_rgx
             if not dummy_rgx.match(name):
                 self.add_message('redefined-outer-name', args=(name, line), node=stmt)
         elif is_builtin(name):
             # do not print Redefining builtin for additional builtins
             self.add_message('redefined-builtin', args=name, node=stmt)
예제 #15
0
 def _transfer(self, block: CFGBlock, in_facts: Set[str],
               local_vars: Set[str]) -> Set[str]:
     gen = in_facts.copy()
     kill = set()
     for statement in block.statements:
         if isinstance(statement, nodes.FunctionDef):
             continue
         for node in self.get_nodes(statement):
             if isinstance(node, nodes.AssignName):
                 gen.add(node.name)
             elif isinstance(node, nodes.DelName):
                 kill.add(node.name)
             else:
                 name = node.name
                 if (not (name in nodes.Module.scope_attrs
                          or utils.is_builtin(name)) and name in local_vars
                         and name not in gen.difference(kill)):
                     self._possibly_undefined.add(node)
                 elif node in self._possibly_undefined:
                     self._possibly_undefined.remove(node)
     return gen.difference(kill)
예제 #16
0
 def visit_call(self, node):
     if isinstance(node.func, astroid.Attribute):
         if node.func.attrname == 'fopen' and self.inside_with_ctx is False:
             msg = (
                 'Please call \'salt.utils.fopen\' using the \'with\' context '
                 'manager, otherwise the file handle won\'t be closed and '
                 'resource leakage will occur.')
             self.add_message('resource-leakage', node=node, args=(msg, ))
     elif isinstance(node.func, astroid.Name):
         if is_builtin(node.func.name) and node.func.name == 'open':
             if self.inside_with_ctx:
                 msg = ('Please use \'with salt.utils.fopen()\' instead of '
                        '\'with open()\'. It assures salt does not leak '
                        'file handles.')
             else:
                 msg = (
                     'Please use \'salt.utils.fopen()\' instead of \'open()\' '
                     'using the \'with\' context manager, otherwise the file '
                     'handle won\'t be closed and resource leakage will occur.'
                 )
             self.add_message('resource-leakage', node=node, args=(msg, ))
예제 #17
0
 def _transfer(self, block: CFGBlock, in_facts: Set[str],
               local_vars: Set[str]) -> Set[str]:
     gen = in_facts.copy()
     kill = set()
     for statement in block.statements:
         if isinstance(statement, astroid.FunctionDef):
             continue
         for node in self.get_nodes(statement):
             if isinstance(node, astroid.AssignName):
                 gen.add(node.name)
             elif isinstance(node, astroid.DelName):
                 kill.add(node.name)
             else:
                 name = node.name
                 # comment out 'self.config....' check when running tests
                 if not (name in astroid.Module.scope_attrs or utils.is_builtin(name)) \
                         and name in local_vars \
                         and name not in gen.difference(kill):
                     self._possibly_undefined.add(node)
                 elif node in self._possibly_undefined:
                     self._possibly_undefined.remove(node)
     return gen.difference(kill)
예제 #18
0
def testIsBuiltin(name, expected):
    assert utils.is_builtin(name) == expected
예제 #19
0
    def visit_name(self, node):
        """check that a name is defined if the current scope and doesn't
        redefine a built-in
        """
        stmt = node.statement()
        if stmt.fromlineno is None:
            # name node from a astroid built from live code, skip
            assert not stmt.root().file.endswith('.py')
            return
        name = node.name
        frame = stmt.scope()
        # if the name node is used as a function default argument's value or as
        # a decorator, then start from the parent frame of the function instead
        # of the function frame - and thus open an inner class scope
        if (is_func_default(node) or is_func_decorator(node)
                or is_ancestor_name(frame, node)):
            start_index = len(self._to_consume) - 2
        else:
            start_index = len(self._to_consume) - 1
        # iterates through parent scopes, from the inner to the outer
        base_scope_type = self._to_consume[start_index][-1]
        for i in range(start_index, -1, -1):
            to_consume, consumed, scope_type = self._to_consume[i]
            # if the current scope is a class scope but it's not the inner
            # scope, ignore it. This prevents to access this scope instead of
            # the globals one in function members when there are some common
            # names. The only exception is when the starting scope is a
            # comprehension and its direct outer scope is a class
            if scope_type == 'class' and i != start_index and not (
                    base_scope_type == 'comprehension' and i == start_index-1):
                # Detect if we are in a local class scope, as an assignment.
                # For example, the following is fair game.
                #
                # class A:
                #    b = 1
                #    c = lambda b=b: b * b
                #
                # class B:
                #    tp = 1
                #    def func(self, arg: tp):
                #        ...

                in_annotation = (
                    PY3K and isinstance(frame, astroid.Function)
                    and node.statement() is frame and
                    (node in frame.args.annotations
                     or node is frame.args.varargannotation
                     or node is frame.args.kwargannotation))
                if in_annotation:
                    frame_locals = frame.parent.scope().locals
                else:
                    frame_locals = frame.locals
                if not ((isinstance(frame, astroid.Class) or in_annotation)
                        and name in frame_locals):
                    continue
            # the name has already been consumed, only check it's not a loop
            # variable used outside the loop
            if name in consumed:
                defnode = assign_parent(consumed[name][0])
                self._check_late_binding_closure(node, defnode)
                self._loopvar_name(node, name)
                break
            # mark the name as consumed if it's defined in this scope
            # (i.e. no KeyError is raised by "to_consume[name]")
            try:
                consumed[name] = to_consume[name]
            except KeyError:
                continue
            # checks for use before assignment
            defnode = assign_parent(to_consume[name][0])
            if defnode is not None:
                self._check_late_binding_closure(node, defnode)
                defstmt = defnode.statement()
                defframe = defstmt.frame()
                maybee0601 = True
                if not frame is defframe:
                    maybee0601 = _detect_global_scope(node, frame, defframe)
                elif defframe.parent is None:
                    # we are at the module level, check the name is not
                    # defined in builtins
                    if name in defframe.scope_attrs or builtin_lookup(name)[1]:
                        maybee0601 = False
                else:
                    # we are in a local scope, check the name is not
                    # defined in global or builtin scope
                    if defframe.root().lookup(name)[1]:
                        maybee0601 = False
                    else:
                        # check if we have a nonlocal
                        if name in defframe.locals:
                            maybee0601 = not any(isinstance(child, astroid.Nonlocal)
                                                 and name in child.names
                                                 for child in defframe.get_children())

                # Handle a couple of class scoping issues.
                annotation_return = False
                # The class reuses itself in the class scope.
                recursive_klass = (frame is defframe and
                                   defframe.parent_of(node) and
                                   isinstance(defframe, astroid.Class) and
                                   node.name == defframe.name)
                if (self._to_consume[-1][-1] == 'lambda' and
                        isinstance(frame, astroid.Class)
                        and name in frame.locals):
                    maybee0601 = True
                elif (isinstance(defframe, astroid.Class) and
                      isinstance(frame, astroid.Function)):
                    # Special rule for function return annotations,
                    # which uses the same name as the class where
                    # the function lives.
                    if (PY3K and node is frame.returns and
                            defframe.parent_of(frame.returns)):
                        maybee0601 = annotation_return = True

                    if (maybee0601 and defframe.name in defframe.locals and
                            defframe.locals[name][0].lineno < frame.lineno):
                        # Detect class assignments with the same
                        # name as the class. In this case, no warning
                        # should be raised.
                        maybee0601 = False
                elif recursive_klass:
                    maybee0601 = True
                else:
                    maybee0601 = maybee0601 and stmt.fromlineno <= defstmt.fromlineno

                if (maybee0601
                        and not is_defined_before(node)
                        and not are_exclusive(stmt, defstmt, ('NameError',
                                                              'Exception',
                                                              'BaseException'))):
                    if recursive_klass or (defstmt is stmt and
                                           isinstance(node, (astroid.DelName,
                                                             astroid.AssName))):
                        self.add_message('undefined-variable', args=name, node=node)
                    elif annotation_return:
                        self.add_message('undefined-variable', args=name, node=node)
                    elif self._to_consume[-1][-1] != 'lambda':
                        # E0601 may *not* occurs in lambda scope.
                        self.add_message('used-before-assignment', args=name, node=node)
                    elif self._to_consume[-1][-1] == 'lambda':
                        # E0601 can occur in class-level scope in lambdas, as in
                        # the following example:
                        #   class A:
                        #      x = lambda attr: f + attr
                        #      f = 42
                        if isinstance(frame, astroid.Class) and name in frame.locals:
                            if isinstance(node.parent, astroid.Arguments):
                                # Doing the following is fine:
                                #   class A:
                                #      x = 42
                                #      y = lambda attr=x: attr
                                if stmt.fromlineno <= defstmt.fromlineno:
                                    self.add_message('used-before-assignment',
                                                     args=name, node=node)
                            else:
                                self.add_message('undefined-variable',
                                                 args=name, node=node)

            if isinstance(node, astroid.AssName): # Aug AssName
                del consumed[name]
            else:
                del to_consume[name]
            # check it's not a loop variable used outside the loop
            self._loopvar_name(node, name)
            break
        else:
            # we have not found the name, if it isn't a builtin, that's an
            # undefined name !
            if not (name in astroid.Module.scope_attrs or is_builtin(name)
                    or name in self.config.additional_builtins):
                self.add_message('undefined-variable', args=name, node=node)
예제 #20
0
 def visit_name(self, node):
     """check that a name is defined if the current scope and doesn't
     redefine a built-in
     """
     name = node.name
     stmt = node.statement()
     # probably "is_statement == True" missing somewhere in astng
     assert stmt.fromlineno, (stmt, node, node.fromlineno)
     frame = stmt.scope()
     # if the name node is used as a function default argument's value or as
     # a decorator, then start from the parent frame of the function instead
     # of the function frame - and thus open an inner class scope
     if (is_func_default(node) or is_func_decorator(node)
         or is_ancestor_name(frame, node)):
         start_index = len(self._to_consume) - 2
     else:
         start_index = len(self._to_consume) - 1
     # iterates through parent scopes, from the inner to the outer
     for i in range(start_index, -1, -1):
         to_consume, consumed, scope_type = self._to_consume[i]
         # if the current scope is a class scope but it's not the inner
         # scope, ignore it. This prevents to access this scope instead of
         # the globals one in function members when there are some common
         # names
         if scope_type == 'class' and i != start_index:
             continue
         # the name has already been consumed, only check it's not a loop
         # variable used outside the loop
         if consumed.has_key(name):
             self._loopvar_name(node, name)
             break
         # mark the name as consumed if it's defined in this scope
         # (i.e. no KeyError is raised by "to_consume[name]")
         try:
             consumed[name] = to_consume[name]
         except KeyError:
             continue
         else:
             # checks for use before assigment
             defnode = assign_parent(to_consume[name][0])
             if defnode is not None:
                 defstmt = defnode.statement()
                 defframe = defstmt.frame()
                 maybee0601 = True
                 if not frame is defframe:
                     maybee0601 = False
                 elif defframe.parent is None:
                     # we are at the module level, check the name is not
                     # defined in builtins
                     if name in defframe.scope_attrs or builtin_lookup(name)[1]:
                         maybee0601 = False
                 else:
                     # we are in a local scope, check the name is not
                     # defined in global or builtin scope
                     if defframe.root().lookup(name)[1]:
                         maybee0601 = False
                 if (maybee0601
                     and stmt.fromlineno <= defstmt.fromlineno
                     and not is_defined_before(node)
                     and not are_exclusive(stmt, defstmt, ('NameError', 'Exception', 'BaseException'))):
                     if defstmt is stmt and isinstance(node, (astng.DelName,
                                                              astng.AssName)):
                         self.add_message('E0602', args=name, node=node)
                     else:
                         self.add_message('E0601', args=name, node=node)
             if not isinstance(node, astng.AssName): # Aug AssName
                 del to_consume[name]
             else:
                 del consumed[name]
             # check it's not a loop variable used outside the loop
             self._loopvar_name(node, name)
             break
     else:
         # we have not found the name, if it isn't a builtin, that's an
         # undefined name !
         if not (name in astng.Module.scope_attrs or is_builtin(name)
                 or name in self.config.additional_builtins):
             self.add_message('E0602', args=name, node=node)
예제 #21
0
 def visit_name(self, node):
     """check that a name is defined if the current scope and doesn't
     redefine a built-in
     """
     stmt = node.statement()
     if stmt.fromlineno is None:
         # name node from a astroid built from live code, skip
         assert not stmt.root().file.endswith('.py')
         return
     name = node.name
     frame = stmt.scope()
     # if the name node is used as a function default argument's value or as
     # a decorator, then start from the parent frame of the function instead
     # of the function frame - and thus open an inner class scope
     if (is_func_default(node) or is_func_decorator(node)
         or is_ancestor_name(frame, node)):
         start_index = len(self._to_consume) - 2
     else:
         start_index = len(self._to_consume) - 1
     # iterates through parent scopes, from the inner to the outer
     base_scope_type = self._to_consume[start_index][-1]
     for i in range(start_index, -1, -1):
         to_consume, consumed, scope_type = self._to_consume[i]
         # if the current scope is a class scope but it's not the inner
         # scope, ignore it. This prevents to access this scope instead of
         # the globals one in function members when there are some common
         # names. The only exception is when the starting scope is a
         # comprehension and its direct outer scope is a class
         if scope_type == 'class' and i != start_index and not (
             base_scope_type == 'comprehension' and i == start_index-1):
             # XXX find a way to handle class scope in a smoother way
             continue
         # the name has already been consumed, only check it's not a loop
         # variable used outside the loop
         if name in consumed:
             defnode = assign_parent(consumed[name][0])
             self._check_late_binding_closure(node, defnode, scope_type)
             self._loopvar_name(node, name)
             break
         # mark the name as consumed if it's defined in this scope
         # (i.e. no KeyError is raised by "to_consume[name]")
         try:
             consumed[name] = to_consume[name]
         except KeyError:
             continue
         # checks for use before assignment
         defnode = assign_parent(to_consume[name][0])
         if defnode is not None:
             self._check_late_binding_closure(node, defnode, scope_type)
             defstmt = defnode.statement()
             defframe = defstmt.frame()
             maybee0601 = True
             if not frame is defframe:
                 maybee0601 = False
             elif defframe.parent is None:
                 # we are at the module level, check the name is not
                 # defined in builtins
                 if name in defframe.scope_attrs or builtin_lookup(name)[1]:
                     maybee0601 = False
             else:
                 # we are in a local scope, check the name is not
                 # defined in global or builtin scope
                 if defframe.root().lookup(name)[1]:
                     maybee0601 = False
                 else:
                     # check if we have a nonlocal
                     if name in defframe.locals:
                         maybee0601 = not any(isinstance(child, astroid.Nonlocal)
                                              and name in child.names
                                              for child in defframe.get_children())
             if (maybee0601
                 and stmt.fromlineno <= defstmt.fromlineno
                 and not is_defined_before(node)
                 and not are_exclusive(stmt, defstmt, ('NameError', 'Exception', 'BaseException'))):
                 if defstmt is stmt and isinstance(node, (astroid.DelName,
                                                          astroid.AssName)):
                     self.add_message('undefined-variable', args=name, node=node)
                 elif self._to_consume[-1][-1] != 'lambda':
                     # E0601 may *not* occurs in lambda scope
                     self.add_message('used-before-assignment', args=name, node=node)
         if isinstance(node, astroid.AssName): # Aug AssName
             del consumed[name]
         else:
             del to_consume[name]
         # check it's not a loop variable used outside the loop
         self._loopvar_name(node, name)
         break
     else:
         # we have not found the name, if it isn't a builtin, that's an
         # undefined name !
         if not (name in astroid.Module.scope_attrs or is_builtin(name)
                 or name in self.config.additional_builtins):
             self.add_message('undefined-variable', args=name, node=node)
def testIsBuiltin(name, expected):
    assert utils.is_builtin(name) == expected
예제 #23
0
 def _is_builtin(self, name):
     """return True if the name is defined in the native builtin or
     in the user specific builtins
     """
     return is_builtin(name) or name in self.config.additional_builtins
예제 #24
0
 def visit_name(self, node):
     """check that a name is defined if the current scope and doesn't
     redefine a built-in
     """
     stmt = node.statement()
     if stmt.fromlineno is None:
         # name node from a astng built from live code, skip
         assert not stmt.root().file.endswith('.py')
         return
     name = node.name
     frame = stmt.scope()
     # if the name node is used as a function default argument's value or as
     # a decorator, then start from the parent frame of the function instead
     # of the function frame - and thus open an inner class scope
     if (is_func_default(node) or is_func_decorator(node)
             or is_ancestor_name(frame, node)):
         start_index = len(self._to_consume) - 2
     else:
         start_index = len(self._to_consume) - 1
     # iterates through parent scopes, from the inner to the outer
     base_scope_type = self._to_consume[start_index][-1]
     for i in range(start_index, -1, -1):
         to_consume, consumed, scope_type = self._to_consume[i]
         # if the current scope is a class scope but it's not the inner
         # scope, ignore it. This prevents to access this scope instead of
         # the globals one in function members when there are some common
         # names. The only exception is when the starting scope is a
         # genexpr and its direct outer scope is a class
         if scope_type == 'class' and i != start_index and not (
                 base_scope_type == 'genexpr' and i == start_index - 1):
             # XXX find a way to handle class scope in a smoother way
             continue
         # the name has already been consumed, only check it's not a loop
         # variable used outside the loop
         if consumed.has_key(name):
             self._loopvar_name(node, name)
             break
         # mark the name as consumed if it's defined in this scope
         # (i.e. no KeyError is raised by "to_consume[name]")
         try:
             consumed[name] = to_consume[name]
         except KeyError:
             continue
         else:
             # checks for use before assignment
             defnode = assign_parent(to_consume[name][0])
             if defnode is not None:
                 defstmt = defnode.statement()
                 defframe = defstmt.frame()
                 maybee0601 = True
                 if not frame is defframe:
                     maybee0601 = False
                 elif defframe.parent is None:
                     # we are at the module level, check the name is not
                     # defined in builtins
                     if name in defframe.scope_attrs or builtin_lookup(
                             name)[1]:
                         maybee0601 = False
                 else:
                     # we are in a local scope, check the name is not
                     # defined in global or builtin scope
                     if defframe.root().lookup(name)[1]:
                         maybee0601 = False
                 if (maybee0601 and stmt.fromlineno <= defstmt.fromlineno
                         and not is_defined_before(node)
                         and not are_exclusive(
                             stmt, defstmt,
                             ('NameError', 'Exception', 'BaseException'))):
                     if defstmt is stmt and isinstance(
                             node, (astng.DelName, astng.AssName)):
                         self.add_message('E0602', args=name, node=node)
                     elif self._to_consume[-1][-1] != 'lambda':
                         # E0601 may *not* occurs in lambda scope
                         self.add_message('E0601', args=name, node=node)
             if not isinstance(node, astng.AssName):  # Aug AssName
                 del to_consume[name]
             else:
                 del consumed[name]
             # check it's not a loop variable used outside the loop
             self._loopvar_name(node, name)
             break
     else:
         # we have not found the name, if it isn't a builtin, that's an
         # undefined name !
         if not (name in astng.Module.scope_attrs or is_builtin(name)
                 or name in self.config.additional_builtins):
             self.add_message('E0602', args=name, node=node)
예제 #25
0
    def visit_name(self, node):
        """check that a name is defined if the current scope and doesn't
        redefine a built-in
        """
        stmt = node.statement()
        if stmt.fromlineno is None:
            # name node from a astroid built from live code, skip
            assert not stmt.root().file.endswith('.py')
            return
        name = node.name
        frame = stmt.scope()
        # if the name node is used as a function default argument's value or as
        # a decorator, then start from the parent frame of the function instead
        # of the function frame - and thus open an inner class scope
        if (is_func_default(node) or is_func_decorator(node)
                or is_ancestor_name(frame, node)):
            start_index = len(self._to_consume) - 2
        else:
            start_index = len(self._to_consume) - 1
        # iterates through parent scopes, from the inner to the outer
        base_scope_type = self._to_consume[start_index][-1]
        for i in range(start_index, -1, -1):
            to_consume, consumed, scope_type = self._to_consume[i]
            # if the current scope is a class scope but it's not the inner
            # scope, ignore it. This prevents to access this scope instead of
            # the globals one in function members when there are some common
            # names. The only exception is when the starting scope is a
            # comprehension and its direct outer scope is a class
            if scope_type == 'class' and i != start_index and not (
                    base_scope_type == 'comprehension'
                    and i == start_index - 1):
                # Detect if we are in a local class scope, as an assignment.
                # For example, the following is fair game.
                # class A:
                #    b = 1
                #    c = lambda b=b: b * b
                class_assignment = (isinstance(frame, astroid.Class)
                                    and name in frame.locals)
                if not class_assignment:
                    continue
            # the name has already been consumed, only check it's not a loop
            # variable used outside the loop
            if name in consumed:
                defnode = assign_parent(consumed[name][0])
                self._check_late_binding_closure(node, defnode, scope_type)
                self._loopvar_name(node, name)
                break
            # mark the name as consumed if it's defined in this scope
            # (i.e. no KeyError is raised by "to_consume[name]")
            try:
                consumed[name] = to_consume[name]
            except KeyError:
                continue
            # checks for use before assignment
            defnode = assign_parent(to_consume[name][0])
            if defnode is not None:
                self._check_late_binding_closure(node, defnode, scope_type)
                defstmt = defnode.statement()
                defframe = defstmt.frame()
                maybee0601 = True
                if not frame is defframe:
                    maybee0601 = _detect_global_scope(node, frame, defframe)
                elif defframe.parent is None:
                    # we are at the module level, check the name is not
                    # defined in builtins
                    if name in defframe.scope_attrs or builtin_lookup(name)[1]:
                        maybee0601 = False
                else:
                    # we are in a local scope, check the name is not
                    # defined in global or builtin scope
                    if defframe.root().lookup(name)[1]:
                        maybee0601 = False
                    else:
                        # check if we have a nonlocal
                        if name in defframe.locals:
                            maybee0601 = not any(
                                isinstance(child, astroid.Nonlocal)
                                and name in child.names
                                for child in defframe.get_children())
                if (self._to_consume[-1][-1] == 'lambda'
                        and isinstance(frame, astroid.Class)
                        and name in frame.locals):
                    maybee0601 = True
                else:
                    maybee0601 = maybee0601 and stmt.fromlineno <= defstmt.fromlineno

                if (maybee0601
                        and not is_defined_before(node) and not are_exclusive(
                            stmt, defstmt,
                            ('NameError', 'Exception', 'BaseException'))):
                    if defstmt is stmt and isinstance(
                            node, (astroid.DelName, astroid.AssName)):
                        self.add_message('undefined-variable',
                                         args=name,
                                         node=node)
                    elif self._to_consume[-1][-1] != 'lambda':
                        # E0601 may *not* occurs in lambda scope.
                        self.add_message('used-before-assignment',
                                         args=name,
                                         node=node)
                    elif self._to_consume[-1][-1] == 'lambda':
                        # E0601 can occur in class-level scope in lambdas, as in
                        # the following example:
                        #   class A:
                        #      x = lambda attr: f + attr
                        #      f = 42
                        if isinstance(frame,
                                      astroid.Class) and name in frame.locals:
                            if isinstance(node.parent, astroid.Arguments):
                                # Doing the following is fine:
                                #   class A:
                                #      x = 42
                                #      y = lambda attr=x: attr
                                if stmt.fromlineno <= defstmt.fromlineno:
                                    self.add_message('used-before-assignment',
                                                     args=name,
                                                     node=node)
                            else:
                                self.add_message('undefined-variable',
                                                 args=name,
                                                 node=node)

            if isinstance(node, astroid.AssName):  # Aug AssName
                del consumed[name]
            else:
                del to_consume[name]
            # check it's not a loop variable used outside the loop
            self._loopvar_name(node, name)
            break
        else:
            # we have not found the name, if it isn't a builtin, that's an
            # undefined name !
            if not (name in astroid.Module.scope_attrs or is_builtin(name)
                    or name in self.config.additional_builtins):
                self.add_message('undefined-variable', args=name, node=node)