예제 #1
0
    def test_try_except(self):
        astng = builder.string_build('''
try:
    def exclusive_func2():
        "docstring"
except TypeError:
    def exclusive_func2():
        "docstring"
except:
    def exclusive_func2():
        "docstring"
else:
    def exclusive_func2():
        "this one redefine the one defined line 42"

        ''')
        f1 = astng.locals['exclusive_func2'][0]
        f2 = astng.locals['exclusive_func2'][1]
        f3 = astng.locals['exclusive_func2'][2]
        f4 = astng.locals['exclusive_func2'][3]
        self.assertEquals(are_exclusive(f1, f2), True)
        self.assertEquals(are_exclusive(f1, f3), True)
        self.assertEquals(are_exclusive(f1, f4), False)
        self.assertEquals(are_exclusive(f2, f4), True)
        self.assertEquals(are_exclusive(f3, f4), True)
        self.assertEquals(are_exclusive(f3, f2), True)
        
        self.assertEquals(are_exclusive(f2, f1), True)
        self.assertEquals(are_exclusive(f4, f1), False)
        self.assertEquals(are_exclusive(f4, f2), True)
예제 #2
0
    def test_not_exclusive(self):
        astng = builder.string_build("""
x = 10
for x in range(5):
    print x
   
if x > 0:
    print '#' * x        
        """, __name__, __file__)
        xass1 = astng.locals['x'][0]
        assert xass1.lineno == 2
        xnames = [n for n in astng.nodes_of_class(nodes.Name) if n.name == 'x']
        assert len(xnames) == 3
        assert xnames[1].lineno == 6
        self.assertEquals(are_exclusive(xass1, xnames[1]), False)
        self.assertEquals(are_exclusive(xass1, xnames[2]), False)
예제 #3
0
 def _check_reimport(self, node, name, basename=None, level=0):
     """check if the import is necessary (i.e. not already done)
     """
     frame = node.frame()
     first = get_first_import(frame, name, basename, level)
     if isinstance(first, (astng.Import, astng.From)) and first is not node \
            and not are_exclusive(first, node):
         self.add_message('W0404', node=node, args=(name, first.fromlineno))
     else:
         root = node.root()
         if root is frame:
             return
         first = get_first_import(root, name, basename)
         if not isinstance(first, (astng.Import, astng.From)):
             return
         if first is not node and not are_exclusive(first, node):
             self.add_message('W0404', node=node,
                              args=(name, first.fromlineno))
예제 #4
0
    def test_if(self):
        astng = builder.string_build('''

if 1:
    a = 1
    a = 2
elif 2:
    a = 12
    a = 13
else:
    a = 3
    a = 4
        ''')
        a1 = astng.locals['a'][0]
        a2 = astng.locals['a'][1]
        a3 = astng.locals['a'][2]
        a4 = astng.locals['a'][3]
        a5 = astng.locals['a'][4]
        a6 = astng.locals['a'][5]
        self.assertEquals(are_exclusive(a1, a2), False)
        self.assertEquals(are_exclusive(a1, a3), True)
        self.assertEquals(are_exclusive(a1, a5), True)
        self.assertEquals(are_exclusive(a3, a5), True)
        self.assertEquals(are_exclusive(a3, a4), False)
        self.assertEquals(are_exclusive(a5, a6), False)
예제 #5
0
 def _check_accessed_members(self, node, accessed):
     """check that accessed members are defined"""
     # XXX refactor, probably much simpler now that E0201 is in type checker
     for attr, nodes in accessed.items():
         # deactivate "except doesn't do anything", that's expected
         # pylint: disable-msg=W0704
         # is it a class attribute ?
         try:
             node.local_attr(attr)
             # yes, stop here
             continue
         except astng.NotFoundError:
             pass
         # is it an instance attribute of a parent class ?
         try:
             node.instance_attr_ancestors(attr).next()
             # yes, stop here
             continue
         except StopIteration:
             pass
         # is it an instance attribute ?
         try:
             defstmts = node.instance_attr(attr) 
         except astng.NotFoundError:
             pass
         else:
             if len(defstmts) == 1:
                 defstmt = defstmts[0]
                 # check that if the node is accessed in the same method as
                 # it's defined, it's accessed after the initial assigment
                 frame = defstmt.frame()
                 lno = defstmt.fromlineno
                 for _node in nodes:
                     if _node.frame() is frame and _node.fromlineno < lno \
                        and not are_exclusive(_node.statement(), defstmt, ('AttributeError', 'Exception', 'BaseException')):
                         self.add_message('E0203', node=_node,
                                          args=(attr, lno))
예제 #6
0
파일: base.py 프로젝트: facuman/environment
 def _check_redefinition(self, redef_type, node):
     """check for redefinition of a function / method / class name"""
     defined_self = node.parent.frame()[node.name]
     if defined_self is not node and not are_exclusive(node, defined_self):
         self.add_message('E0102', node=node,
                          args=(redef_type, defined_self.fromlineno))
예제 #7
0
    def _filter_stmts(self, stmts, frame, offset):
        """filter statements to remove ignorable statements.

        If self is not a frame itself and the name is found in the inner
        frame locals, statements will be filtered to remove ignorable
        statements according to self's location
        """
        # if offset == -1, my actual frame is not the inner frame but its parent
        #
        # class A(B): pass
        #
        # we need this to resolve B correctly
        if offset == -1:
            myframe = self.frame().parent.frame()
        else:
            myframe = self.frame()
        if not myframe is frame or self is frame:
            return stmts
        mystmt = self.statement()
        # line filtering if we are in the same frame
        #
        # take care node may be missing lineno information (this is the case for
        # nodes inserted for living objects)
        if myframe is frame and mystmt.fromlineno is not None:
            assert mystmt.fromlineno is not None, mystmt
            mylineno = mystmt.fromlineno + offset
        else:
            # disabling lineno filtering
            mylineno = 0
        _stmts = []
        _stmt_parents = []
        for node in stmts:
            stmt = node.statement()
            # line filtering is on and we have reached our location, break
            if mylineno > 0 and stmt.fromlineno > mylineno:
                break
            if isinstance(node, nodes.Class) and self in node.bases:
                break
            assert hasattr(node, 'ass_type'), (node, node.scope(),
                                               node.scope().locals)
            ass_type = node.ass_type()
            if ass_type is mystmt and not isinstance(ass_type, (nodes.Class,
                    nodes.Function, nodes.Import, nodes.From, nodes.Lambda)):
                if not isinstance(ass_type, nodes.Comprehension):
                    break
                if isinstance(self, (nodes.Const, nodes.Name)):
                    _stmts = [self]
                    break
            elif ass_type.statement() is mystmt:
                # original node's statement is the assignment, only keeps
                # current node (gen exp, list comp)
                _stmts = [node]
                break        
            optional_assign = isinstance(ass_type, nodes.LOOP_SCOPES)
            if optional_assign and ass_type.parent_of(self):
                # we are inside a loop, loop var assigment is hidding previous
                # assigment
                _stmts = [node]
                _stmt_parents = [stmt.parent]
                continue
            # XXX comment various branches below!!!
            try:
                pindex = _stmt_parents.index(stmt.parent)
            except ValueError:
                pass
            else:
                # we got a parent index, this means the currently visited node
                # is at the same block level as a previously visited node
                if _stmts[pindex].ass_type().parent_of(ass_type):
                    # both statements are not at the same block level
                    continue
                # if currently visited node is following previously considered
                # assignement and both are not exclusive, we can drop the
                # previous one. For instance in the following code ::
                #
                #   if a:
                #     x = 1
                #   else:
                #     x = 2
                #   print x
                #
                # we can't remove neither x = 1 nor x = 2 when looking for 'x'
                # of 'print x'; while in the following ::
                #
                #   x = 1
                #   x = 2
                #   print x
                #
                # we can remove x = 1 when we see x = 2
                #
                # moreover, on loop assignment types, assignment won't
                # necessarily be done if the loop has no iteration, so we don't
                # want to clear previous assigments if any (hence the test on
                # optional_assign)
                if not (optional_assign or are_exclusive(_stmts[pindex], node)):
                    del _stmt_parents[pindex]
                    del _stmts[pindex]
            if isinstance(node, nodes.AssName):
                if not optional_assign and stmt.parent is mystmt.parent:
                    _stmts = []
                    _stmt_parents = []
            elif isinstance(node, nodes.DelName):
                _stmts = []
                _stmt_parents = []
                continue
            if not are_exclusive(self, node):
                _stmts.append(node)
                _stmt_parents.append(stmt.parent)
        return _stmts
예제 #8
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)