diff -Nru astroid-1.0.1/as_string.py astroid-1.3.8/as_string.py
--- astroid-1.0.1/as_string.py 2013-07-29 15:04:24.000000000 +0000
+++ astroid-1.3.8/as_string.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,475 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""This module renders Astroid nodes as string:
-
-* :func:`to_code` function return equivalent (hopefuly valid) python string
-
-* :func:`dump` function return an internal representation of nodes found
- in the tree, useful for debugging or understanding the tree structure
-"""
-
-import sys
-
-INDENT = ' ' # 4 spaces ; keep indentation variable
-
-
-def dump(node, ids=False):
- """print a nice astroid tree representation.
-
- :param ids: if true, we also print the ids (usefull for debugging)
- """
- result = []
- _repr_tree(node, result, ids=ids)
- return "\n".join(result)
-
-def _repr_tree(node, result, indent='', _done=None, ids=False):
- """built a tree representation of a node as a list of lines"""
- if _done is None:
- _done = set()
- if not hasattr(node, '_astroid_fields'): # not a astroid node
- return
- if node in _done:
- result.append( indent + 'loop in tree: %s' % node )
- return
- _done.add(node)
- node_str = str(node)
- if ids:
- node_str += ' . \t%x' % id(node)
- result.append( indent + node_str )
- indent += INDENT
- for field in node._astroid_fields:
- value = getattr(node, field)
- if isinstance(value, (list, tuple) ):
- result.append( indent + field + " = [" )
- for child in value:
- if isinstance(child, (list, tuple) ):
- # special case for Dict # FIXME
- _repr_tree(child[0], result, indent, _done, ids)
- _repr_tree(child[1], result, indent, _done, ids)
- result.append(indent + ',')
- else:
- _repr_tree(child, result, indent, _done, ids)
- result.append( indent + "]" )
- else:
- result.append( indent + field + " = " )
- _repr_tree(value, result, indent, _done, ids)
-
-
-class AsStringVisitor(object):
- """Visitor to render an Astroid node as a valid python code string"""
-
- def __call__(self, node):
- """Makes this visitor behave as a simple function"""
- return node.accept(self)
-
- def _stmt_list(self, stmts):
- """return a list of nodes to string"""
- stmts = '\n'.join([nstr for nstr in [n.accept(self) for n in stmts] if nstr])
- return INDENT + stmts.replace('\n', '\n'+INDENT)
-
-
- ## visit_ methods ###########################################
-
- def visit_arguments(self, node):
- """return an astroid.Function node as string"""
- return node.format_args()
-
- def visit_assattr(self, node):
- """return an astroid.AssAttr node as string"""
- return self.visit_getattr(node)
-
- def visit_assert(self, node):
- """return an astroid.Assert node as string"""
- if node.fail:
- return 'assert %s, %s' % (node.test.accept(self),
- node.fail.accept(self))
- return 'assert %s' % node.test.accept(self)
-
- def visit_assname(self, node):
- """return an astroid.AssName node as string"""
- return node.name
-
- def visit_assign(self, node):
- """return an astroid.Assign node as string"""
- lhs = ' = '.join([n.accept(self) for n in node.targets])
- return '%s = %s' % (lhs, node.value.accept(self))
-
- def visit_augassign(self, node):
- """return an astroid.AugAssign node as string"""
- return '%s %s %s' % (node.target.accept(self), node.op, node.value.accept(self))
-
- def visit_backquote(self, node):
- """return an astroid.Backquote node as string"""
- return '`%s`' % node.value.accept(self)
-
- def visit_binop(self, node):
- """return an astroid.BinOp node as string"""
- return '(%s) %s (%s)' % (node.left.accept(self), node.op, node.right.accept(self))
-
- def visit_boolop(self, node):
- """return an astroid.BoolOp node as string"""
- return (' %s ' % node.op).join(['(%s)' % n.accept(self)
- for n in node.values])
-
- def visit_break(self, node):
- """return an astroid.Break node as string"""
- return 'break'
-
- def visit_callfunc(self, node):
- """return an astroid.CallFunc node as string"""
- expr_str = node.func.accept(self)
- args = [arg.accept(self) for arg in node.args]
- if node.starargs:
- args.append( '*' + node.starargs.accept(self))
- if node.kwargs:
- args.append( '**' + node.kwargs.accept(self))
- return '%s(%s)' % (expr_str, ', '.join(args))
-
- def visit_class(self, node):
- """return an astroid.Class node as string"""
- decorate = node.decorators and node.decorators.accept(self) or ''
- bases = ', '.join([n.accept(self) for n in node.bases])
- bases = bases and '(%s)' % bases or ''
- docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or ''
- return '\n\n%sclass %s%s:%s\n%s\n' % (decorate, node.name, bases, docs,
- self._stmt_list( node.body))
-
- def visit_compare(self, node):
- """return an astroid.Compare node as string"""
- rhs_str = ' '.join(['%s %s' % (op, expr.accept(self))
- for op, expr in node.ops])
- return '%s %s' % (node.left.accept(self), rhs_str)
-
- def visit_comprehension(self, node):
- """return an astroid.Comprehension node as string"""
- ifs = ''.join([ ' if %s' % n.accept(self) for n in node.ifs])
- return 'for %s in %s%s' % (node.target.accept(self),
- node.iter.accept(self), ifs )
-
- def visit_const(self, node):
- """return an astroid.Const node as string"""
- return repr(node.value)
-
- def visit_continue(self, node):
- """return an astroid.Continue node as string"""
- return 'continue'
-
- def visit_delete(self, node): # XXX check if correct
- """return an astroid.Delete node as string"""
- return 'del %s' % ', '.join([child.accept(self)
- for child in node.targets])
-
- def visit_delattr(self, node):
- """return an astroid.DelAttr node as string"""
- return self.visit_getattr(node)
-
- def visit_delname(self, node):
- """return an astroid.DelName node as string"""
- return node.name
-
- def visit_decorators(self, node):
- """return an astroid.Decorators node as string"""
- return '@%s\n' % '\n@'.join([item.accept(self) for item in node.nodes])
-
- def visit_dict(self, node):
- """return an astroid.Dict node as string"""
- return '{%s}' % ', '.join(['%s: %s' % (key.accept(self),
- value.accept(self)) for key, value in node.items])
-
- def visit_dictcomp(self, node):
- """return an astroid.DictComp node as string"""
- return '{%s: %s %s}' % (node.key.accept(self), node.value.accept(self),
- ' '.join([n.accept(self) for n in node.generators]))
-
- def visit_discard(self, node):
- """return an astroid.Discard node as string"""
- return node.value.accept(self)
-
- def visit_emptynode(self, node):
- """dummy method for visiting an Empty node"""
- return ''
-
- def visit_excepthandler(self, node):
- if node.type:
- if node.name:
- excs = 'except %s, %s' % (node.type.accept(self),
- node.name.accept(self))
- else:
- excs = 'except %s' % node.type.accept(self)
- else:
- excs = 'except'
- return '%s:\n%s' % (excs, self._stmt_list(node.body))
-
- def visit_ellipsis(self, node):
- """return an astroid.Ellipsis node as string"""
- return '...'
-
- def visit_empty(self, node):
- """return an Empty node as string"""
- return ''
-
- def visit_exec(self, node):
- """return an astroid.Exec node as string"""
- if node.locals:
- return 'exec %s in %s, %s' % (node.expr.accept(self),
- node.locals.accept(self),
- node.globals.accept(self))
- if node.globals:
- return 'exec %s in %s' % (node.expr.accept(self),
- node.globals.accept(self))
- return 'exec %s' % node.expr.accept(self)
-
- def visit_extslice(self, node):
- """return an astroid.ExtSlice node as string"""
- return ','.join( [dim.accept(self) for dim in node.dims] )
-
- def visit_for(self, node):
- """return an astroid.For node as string"""
- fors = 'for %s in %s:\n%s' % (node.target.accept(self),
- node.iter.accept(self),
- self._stmt_list( node.body))
- if node.orelse:
- fors = '%s\nelse:\n%s' % (fors, self._stmt_list(node.orelse))
- return fors
-
- def visit_from(self, node):
- """return an astroid.From node as string"""
- return 'from %s import %s' % ('.' * (node.level or 0) + node.modname,
- _import_string(node.names))
-
- def visit_function(self, node):
- """return an astroid.Function node as string"""
- decorate = node.decorators and node.decorators.accept(self) or ''
- docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or ''
- return '\n%sdef %s(%s):%s\n%s' % (decorate, node.name, node.args.accept(self),
- docs, self._stmt_list(node.body))
-
- def visit_genexpr(self, node):
- """return an astroid.GenExpr node as string"""
- return '(%s %s)' % (node.elt.accept(self), ' '.join([n.accept(self)
- for n in node.generators]))
-
- def visit_getattr(self, node):
- """return an astroid.Getattr node as string"""
- return '%s.%s' % (node.expr.accept(self), node.attrname)
-
- def visit_global(self, node):
- """return an astroid.Global node as string"""
- return 'global %s' % ', '.join(node.names)
-
- def visit_if(self, node):
- """return an astroid.If node as string"""
- ifs = ['if %s:\n%s' % (node.test.accept(self), self._stmt_list(node.body))]
- if node.orelse:# XXX use elif ???
- ifs.append('else:\n%s' % self._stmt_list(node.orelse))
- return '\n'.join(ifs)
-
- def visit_ifexp(self, node):
- """return an astroid.IfExp node as string"""
- return '%s if %s else %s' % (node.body.accept(self),
- node.test.accept(self), node.orelse.accept(self))
-
- def visit_import(self, node):
- """return an astroid.Import node as string"""
- return 'import %s' % _import_string(node.names)
-
- def visit_keyword(self, node):
- """return an astroid.Keyword node as string"""
- return '%s=%s' % (node.arg, node.value.accept(self))
-
- def visit_lambda(self, node):
- """return an astroid.Lambda node as string"""
- return 'lambda %s: %s' % (node.args.accept(self), node.body.accept(self))
-
- def visit_list(self, node):
- """return an astroid.List node as string"""
- return '[%s]' % ', '.join([child.accept(self) for child in node.elts])
-
- def visit_listcomp(self, node):
- """return an astroid.ListComp node as string"""
- return '[%s %s]' % (node.elt.accept(self), ' '.join([n.accept(self)
- for n in node.generators]))
-
- def visit_module(self, node):
- """return an astroid.Module node as string"""
- docs = node.doc and '"""%s"""\n\n' % node.doc or ''
- return docs + '\n'.join([n.accept(self) for n in node.body]) + '\n\n'
-
- def visit_name(self, node):
- """return an astroid.Name node as string"""
- return node.name
-
- def visit_pass(self, node):
- """return an astroid.Pass node as string"""
- return 'pass'
-
- def visit_print(self, node):
- """return an astroid.Print node as string"""
- nodes = ', '.join([n.accept(self) for n in node.values])
- if not node.nl:
- nodes = '%s,' % nodes
- if node.dest:
- return 'print >> %s, %s' % (node.dest.accept(self), nodes)
- return 'print %s' % nodes
-
- def visit_raise(self, node):
- """return an astroid.Raise node as string"""
- if node.exc:
- if node.inst:
- if node.tback:
- return 'raise %s, %s, %s' % (node.exc.accept(self),
- node.inst.accept(self),
- node.tback.accept(self))
- return 'raise %s, %s' % (node.exc.accept(self),
- node.inst.accept(self))
- return 'raise %s' % node.exc.accept(self)
- return 'raise'
-
- def visit_return(self, node):
- """return an astroid.Return node as string"""
- if node.value:
- return 'return %s' % node.value.accept(self)
- else:
- return 'return'
-
- def visit_index(self, node):
- """return a astroid.Index node as string"""
- return node.value.accept(self)
-
- def visit_set(self, node):
- """return an astroid.Set node as string"""
- return '{%s}' % ', '.join([child.accept(self) for child in node.elts])
-
- def visit_setcomp(self, node):
- """return an astroid.SetComp node as string"""
- return '{%s %s}' % (node.elt.accept(self), ' '.join([n.accept(self)
- for n in node.generators]))
-
- def visit_slice(self, node):
- """return a astroid.Slice node as string"""
- lower = node.lower and node.lower.accept(self) or ''
- upper = node.upper and node.upper.accept(self) or ''
- step = node.step and node.step.accept(self) or ''
- if step:
- return '%s:%s:%s' % (lower, upper, step)
- return '%s:%s' % (lower, upper)
-
- def visit_subscript(self, node):
- """return an astroid.Subscript node as string"""
- return '%s[%s]' % (node.value.accept(self), node.slice.accept(self))
-
- def visit_tryexcept(self, node):
- """return an astroid.TryExcept node as string"""
- trys = ['try:\n%s' % self._stmt_list( node.body)]
- for handler in node.handlers:
- trys.append(handler.accept(self))
- if node.orelse:
- trys.append('else:\n%s' % self._stmt_list(node.orelse))
- return '\n'.join(trys)
-
- def visit_tryfinally(self, node):
- """return an astroid.TryFinally node as string"""
- return 'try:\n%s\nfinally:\n%s' % (self._stmt_list( node.body),
- self._stmt_list(node.finalbody))
-
- def visit_tuple(self, node):
- """return an astroid.Tuple node as string"""
- return '(%s)' % ', '.join([child.accept(self) for child in node.elts])
-
- def visit_unaryop(self, node):
- """return an astroid.UnaryOp node as string"""
- if node.op == 'not':
- operator = 'not '
- else:
- operator = node.op
- return '%s%s' % (operator, node.operand.accept(self))
-
- def visit_while(self, node):
- """return an astroid.While node as string"""
- whiles = 'while %s:\n%s' % (node.test.accept(self),
- self._stmt_list(node.body))
- if node.orelse:
- whiles = '%s\nelse:\n%s' % (whiles, self._stmt_list(node.orelse))
- return whiles
-
- def visit_with(self, node): # 'with' without 'as' is possible
- """return an astroid.With node as string"""
- items = ', '.join(('(%s)' % expr.accept(self)) +
- (vars and ' as (%s)' % (vars.accept(self)) or '')
- for expr, vars in node.items)
- return 'with %s:\n%s' % (items, self._stmt_list( node.body))
-
- def visit_yield(self, node):
- """yield an ast.Yield node as string"""
- yi_val = node.value and (" " + node.value.accept(self)) or ""
- expr = 'yield' + yi_val
- if node.parent.is_statement:
- return expr
- else:
- return "(%s)" % (expr,)
-
-
-class AsStringVisitor3k(AsStringVisitor):
- """AsStringVisitor3k overwrites some AsStringVisitor methods"""
-
- def visit_excepthandler(self, node):
- if node.type:
- if node.name:
- excs = 'except %s as %s' % (node.type.accept(self),
- node.name.accept(self))
- else:
- excs = 'except %s' % node.type.accept(self)
- else:
- excs = 'except'
- return '%s:\n%s' % (excs, self._stmt_list(node.body))
-
- def visit_nonlocal(self, node):
- """return an astroid.Nonlocal node as string"""
- return 'nonlocal %s' % ', '.join(node.names)
-
- def visit_raise(self, node):
- """return an astroid.Raise node as string"""
- if node.exc:
- if node.cause:
- return 'raise %s from %s' % (node.exc.accept(self),
- node.cause.accept(self))
- return 'raise %s' % node.exc.accept(self)
- return 'raise'
-
- def visit_starred(self, node):
- """return Starred node as string"""
- return "*" + node.value.accept(self)
-
-
-def _import_string(names):
- """return a list of (name, asname) formatted as a string"""
- _names = []
- for name, asname in names:
- if asname is not None:
- _names.append('%s as %s' % (name, asname))
- else:
- _names.append(name)
- return ', '.join(_names)
-
-
-if sys.version_info >= (3, 0):
- AsStringVisitor = AsStringVisitor3k
-
-# this visitor is stateless, thus it can be reused
-to_code = AsStringVisitor()
-
diff -Nru astroid-1.0.1/astroid/as_string.py astroid-1.3.8/astroid/as_string.py
--- astroid-1.0.1/astroid/as_string.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/as_string.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,499 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""This module renders Astroid nodes as string:
+
+* :func:`to_code` function return equivalent (hopefuly valid) python string
+
+* :func:`dump` function return an internal representation of nodes found
+ in the tree, useful for debugging or understanding the tree structure
+"""
+
+import sys
+
+INDENT = ' ' # 4 spaces ; keep indentation variable
+
+
+def dump(node, ids=False):
+ """print a nice astroid tree representation.
+
+ :param ids: if true, we also print the ids (usefull for debugging)
+ """
+ result = []
+ _repr_tree(node, result, ids=ids)
+ return "\n".join(result)
+
+def _repr_tree(node, result, indent='', _done=None, ids=False):
+ """built a tree representation of a node as a list of lines"""
+ if _done is None:
+ _done = set()
+ if not hasattr(node, '_astroid_fields'): # not a astroid node
+ return
+ if node in _done:
+ result.append(indent + 'loop in tree: %s' % node)
+ return
+ _done.add(node)
+ node_str = str(node)
+ if ids:
+ node_str += ' . \t%x' % id(node)
+ result.append(indent + node_str)
+ indent += INDENT
+ for field in node._astroid_fields:
+ value = getattr(node, field)
+ if isinstance(value, (list, tuple)):
+ result.append(indent + field + " = [")
+ for child in value:
+ if isinstance(child, (list, tuple)):
+ # special case for Dict # FIXME
+ _repr_tree(child[0], result, indent, _done, ids)
+ _repr_tree(child[1], result, indent, _done, ids)
+ result.append(indent + ',')
+ else:
+ _repr_tree(child, result, indent, _done, ids)
+ result.append(indent + "]")
+ else:
+ result.append(indent + field + " = ")
+ _repr_tree(value, result, indent, _done, ids)
+
+
+class AsStringVisitor(object):
+ """Visitor to render an Astroid node as a valid python code string"""
+
+ def __call__(self, node):
+ """Makes this visitor behave as a simple function"""
+ return node.accept(self)
+
+ def _stmt_list(self, stmts):
+ """return a list of nodes to string"""
+ stmts = '\n'.join([nstr for nstr in [n.accept(self) for n in stmts] if nstr])
+ return INDENT + stmts.replace('\n', '\n'+INDENT)
+
+
+ ## visit_ methods ###########################################
+
+ def visit_arguments(self, node):
+ """return an astroid.Function node as string"""
+ return node.format_args()
+
+ def visit_assattr(self, node):
+ """return an astroid.AssAttr node as string"""
+ return self.visit_getattr(node)
+
+ def visit_assert(self, node):
+ """return an astroid.Assert node as string"""
+ if node.fail:
+ return 'assert %s, %s' % (node.test.accept(self),
+ node.fail.accept(self))
+ return 'assert %s' % node.test.accept(self)
+
+ def visit_assname(self, node):
+ """return an astroid.AssName node as string"""
+ return node.name
+
+ def visit_assign(self, node):
+ """return an astroid.Assign node as string"""
+ lhs = ' = '.join([n.accept(self) for n in node.targets])
+ return '%s = %s' % (lhs, node.value.accept(self))
+
+ def visit_augassign(self, node):
+ """return an astroid.AugAssign node as string"""
+ return '%s %s %s' % (node.target.accept(self), node.op, node.value.accept(self))
+
+ def visit_backquote(self, node):
+ """return an astroid.Backquote node as string"""
+ return '`%s`' % node.value.accept(self)
+
+ def visit_binop(self, node):
+ """return an astroid.BinOp node as string"""
+ return '(%s) %s (%s)' % (node.left.accept(self), node.op, node.right.accept(self))
+
+ def visit_boolop(self, node):
+ """return an astroid.BoolOp node as string"""
+ return (' %s ' % node.op).join(['(%s)' % n.accept(self)
+ for n in node.values])
+
+ def visit_break(self, node):
+ """return an astroid.Break node as string"""
+ return 'break'
+
+ def visit_callfunc(self, node):
+ """return an astroid.CallFunc node as string"""
+ expr_str = node.func.accept(self)
+ args = [arg.accept(self) for arg in node.args]
+ if node.starargs:
+ args.append('*' + node.starargs.accept(self))
+ if node.kwargs:
+ args.append('**' + node.kwargs.accept(self))
+ return '%s(%s)' % (expr_str, ', '.join(args))
+
+ def visit_class(self, node):
+ """return an astroid.Class node as string"""
+ decorate = node.decorators and node.decorators.accept(self) or ''
+ bases = ', '.join([n.accept(self) for n in node.bases])
+ if sys.version_info[0] == 2:
+ bases = bases and '(%s)' % bases or ''
+ else:
+ metaclass = node.metaclass()
+ if metaclass and not node.has_metaclass_hack():
+ if bases:
+ bases = '(%s, metaclass=%s)' % (bases, metaclass.name)
+ else:
+ bases = '(metaclass=%s)' % metaclass.name
+ else:
+ bases = bases and '(%s)' % bases or ''
+ docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or ''
+ return '\n\n%sclass %s%s:%s\n%s\n' % (decorate, node.name, bases, docs,
+ self._stmt_list(node.body))
+
+ def visit_compare(self, node):
+ """return an astroid.Compare node as string"""
+ rhs_str = ' '.join(['%s %s' % (op, expr.accept(self))
+ for op, expr in node.ops])
+ return '%s %s' % (node.left.accept(self), rhs_str)
+
+ def visit_comprehension(self, node):
+ """return an astroid.Comprehension node as string"""
+ ifs = ''.join([' if %s' % n.accept(self) for n in node.ifs])
+ return 'for %s in %s%s' % (node.target.accept(self),
+ node.iter.accept(self), ifs)
+
+ def visit_const(self, node):
+ """return an astroid.Const node as string"""
+ return repr(node.value)
+
+ def visit_continue(self, node):
+ """return an astroid.Continue node as string"""
+ return 'continue'
+
+ def visit_delete(self, node): # XXX check if correct
+ """return an astroid.Delete node as string"""
+ return 'del %s' % ', '.join([child.accept(self)
+ for child in node.targets])
+
+ def visit_delattr(self, node):
+ """return an astroid.DelAttr node as string"""
+ return self.visit_getattr(node)
+
+ def visit_delname(self, node):
+ """return an astroid.DelName node as string"""
+ return node.name
+
+ def visit_decorators(self, node):
+ """return an astroid.Decorators node as string"""
+ return '@%s\n' % '\n@'.join([item.accept(self) for item in node.nodes])
+
+ def visit_dict(self, node):
+ """return an astroid.Dict node as string"""
+ return '{%s}' % ', '.join(['%s: %s' % (key.accept(self),
+ value.accept(self))
+ for key, value in node.items])
+
+ def visit_dictcomp(self, node):
+ """return an astroid.DictComp node as string"""
+ return '{%s: %s %s}' % (node.key.accept(self), node.value.accept(self),
+ ' '.join([n.accept(self) for n in node.generators]))
+
+ def visit_discard(self, node):
+ """return an astroid.Discard node as string"""
+ return node.value.accept(self)
+
+ def visit_emptynode(self, node):
+ """dummy method for visiting an Empty node"""
+ return ''
+
+ def visit_excepthandler(self, node):
+ if node.type:
+ if node.name:
+ excs = 'except %s, %s' % (node.type.accept(self),
+ node.name.accept(self))
+ else:
+ excs = 'except %s' % node.type.accept(self)
+ else:
+ excs = 'except'
+ return '%s:\n%s' % (excs, self._stmt_list(node.body))
+
+ def visit_ellipsis(self, node):
+ """return an astroid.Ellipsis node as string"""
+ return '...'
+
+ def visit_empty(self, node):
+ """return an Empty node as string"""
+ return ''
+
+ def visit_exec(self, node):
+ """return an astroid.Exec node as string"""
+ if node.locals:
+ return 'exec %s in %s, %s' % (node.expr.accept(self),
+ node.locals.accept(self),
+ node.globals.accept(self))
+ if node.globals:
+ return 'exec %s in %s' % (node.expr.accept(self),
+ node.globals.accept(self))
+ return 'exec %s' % node.expr.accept(self)
+
+ def visit_extslice(self, node):
+ """return an astroid.ExtSlice node as string"""
+ return ','.join([dim.accept(self) for dim in node.dims])
+
+ def visit_for(self, node):
+ """return an astroid.For node as string"""
+ fors = 'for %s in %s:\n%s' % (node.target.accept(self),
+ node.iter.accept(self),
+ self._stmt_list(node.body))
+ if node.orelse:
+ fors = '%s\nelse:\n%s' % (fors, self._stmt_list(node.orelse))
+ return fors
+
+ def visit_from(self, node):
+ """return an astroid.From node as string"""
+ return 'from %s import %s' % ('.' * (node.level or 0) + node.modname,
+ _import_string(node.names))
+
+ def visit_function(self, node):
+ """return an astroid.Function node as string"""
+ decorate = node.decorators and node.decorators.accept(self) or ''
+ docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or ''
+ return '\n%sdef %s(%s):%s\n%s' % (decorate, node.name, node.args.accept(self),
+ docs, self._stmt_list(node.body))
+
+ def visit_genexpr(self, node):
+ """return an astroid.GenExpr node as string"""
+ return '(%s %s)' % (node.elt.accept(self),
+ ' '.join([n.accept(self) for n in node.generators]))
+
+ def visit_getattr(self, node):
+ """return an astroid.Getattr node as string"""
+ return '%s.%s' % (node.expr.accept(self), node.attrname)
+
+ def visit_global(self, node):
+ """return an astroid.Global node as string"""
+ return 'global %s' % ', '.join(node.names)
+
+ def visit_if(self, node):
+ """return an astroid.If node as string"""
+ ifs = ['if %s:\n%s' % (node.test.accept(self), self._stmt_list(node.body))]
+ if node.orelse:# XXX use elif ???
+ ifs.append('else:\n%s' % self._stmt_list(node.orelse))
+ return '\n'.join(ifs)
+
+ def visit_ifexp(self, node):
+ """return an astroid.IfExp node as string"""
+ return '%s if %s else %s' % (node.body.accept(self),
+ node.test.accept(self),
+ node.orelse.accept(self))
+
+ def visit_import(self, node):
+ """return an astroid.Import node as string"""
+ return 'import %s' % _import_string(node.names)
+
+ def visit_keyword(self, node):
+ """return an astroid.Keyword node as string"""
+ return '%s=%s' % (node.arg, node.value.accept(self))
+
+ def visit_lambda(self, node):
+ """return an astroid.Lambda node as string"""
+ return 'lambda %s: %s' % (node.args.accept(self),
+ node.body.accept(self))
+
+ def visit_list(self, node):
+ """return an astroid.List node as string"""
+ return '[%s]' % ', '.join([child.accept(self) for child in node.elts])
+
+ def visit_listcomp(self, node):
+ """return an astroid.ListComp node as string"""
+ return '[%s %s]' % (node.elt.accept(self),
+ ' '.join([n.accept(self) for n in node.generators]))
+
+ def visit_module(self, node):
+ """return an astroid.Module node as string"""
+ docs = node.doc and '"""%s"""\n\n' % node.doc or ''
+ return docs + '\n'.join([n.accept(self) for n in node.body]) + '\n\n'
+
+ def visit_name(self, node):
+ """return an astroid.Name node as string"""
+ return node.name
+
+ def visit_pass(self, node):
+ """return an astroid.Pass node as string"""
+ return 'pass'
+
+ def visit_print(self, node):
+ """return an astroid.Print node as string"""
+ nodes = ', '.join([n.accept(self) for n in node.values])
+ if not node.nl:
+ nodes = '%s,' % nodes
+ if node.dest:
+ return 'print >> %s, %s' % (node.dest.accept(self), nodes)
+ return 'print %s' % nodes
+
+ def visit_raise(self, node):
+ """return an astroid.Raise node as string"""
+ if node.exc:
+ if node.inst:
+ if node.tback:
+ return 'raise %s, %s, %s' % (node.exc.accept(self),
+ node.inst.accept(self),
+ node.tback.accept(self))
+ return 'raise %s, %s' % (node.exc.accept(self),
+ node.inst.accept(self))
+ return 'raise %s' % node.exc.accept(self)
+ return 'raise'
+
+ def visit_return(self, node):
+ """return an astroid.Return node as string"""
+ if node.value:
+ return 'return %s' % node.value.accept(self)
+ else:
+ return 'return'
+
+ def visit_index(self, node):
+ """return a astroid.Index node as string"""
+ return node.value.accept(self)
+
+ def visit_set(self, node):
+ """return an astroid.Set node as string"""
+ return '{%s}' % ', '.join([child.accept(self) for child in node.elts])
+
+ def visit_setcomp(self, node):
+ """return an astroid.SetComp node as string"""
+ return '{%s %s}' % (node.elt.accept(self),
+ ' '.join([n.accept(self) for n in node.generators]))
+
+ def visit_slice(self, node):
+ """return a astroid.Slice node as string"""
+ lower = node.lower and node.lower.accept(self) or ''
+ upper = node.upper and node.upper.accept(self) or ''
+ step = node.step and node.step.accept(self) or ''
+ if step:
+ return '%s:%s:%s' % (lower, upper, step)
+ return '%s:%s' % (lower, upper)
+
+ def visit_subscript(self, node):
+ """return an astroid.Subscript node as string"""
+ return '%s[%s]' % (node.value.accept(self), node.slice.accept(self))
+
+ def visit_tryexcept(self, node):
+ """return an astroid.TryExcept node as string"""
+ trys = ['try:\n%s' % self._stmt_list(node.body)]
+ for handler in node.handlers:
+ trys.append(handler.accept(self))
+ if node.orelse:
+ trys.append('else:\n%s' % self._stmt_list(node.orelse))
+ return '\n'.join(trys)
+
+ def visit_tryfinally(self, node):
+ """return an astroid.TryFinally node as string"""
+ return 'try:\n%s\nfinally:\n%s' % (self._stmt_list(node.body),
+ self._stmt_list(node.finalbody))
+
+ def visit_tuple(self, node):
+ """return an astroid.Tuple node as string"""
+ if len(node.elts) == 1:
+ return '(%s, )' % node.elts[0].accept(self)
+ return '(%s)' % ', '.join([child.accept(self) for child in node.elts])
+
+ def visit_unaryop(self, node):
+ """return an astroid.UnaryOp node as string"""
+ if node.op == 'not':
+ operator = 'not '
+ else:
+ operator = node.op
+ return '%s%s' % (operator, node.operand.accept(self))
+
+ def visit_while(self, node):
+ """return an astroid.While node as string"""
+ whiles = 'while %s:\n%s' % (node.test.accept(self),
+ self._stmt_list(node.body))
+ if node.orelse:
+ whiles = '%s\nelse:\n%s' % (whiles, self._stmt_list(node.orelse))
+ return whiles
+
+ def visit_with(self, node): # 'with' without 'as' is possible
+ """return an astroid.With node as string"""
+ items = ', '.join(('(%s)' % expr.accept(self)) +
+ (vars and ' as (%s)' % (vars.accept(self)) or '')
+ for expr, vars in node.items)
+ return 'with %s:\n%s' % (items, self._stmt_list(node.body))
+
+ def visit_yield(self, node):
+ """yield an ast.Yield node as string"""
+ yi_val = node.value and (" " + node.value.accept(self)) or ""
+ expr = 'yield' + yi_val
+ if node.parent.is_statement:
+ return expr
+ else:
+ return "(%s)" % (expr,)
+
+
+class AsStringVisitor3k(AsStringVisitor):
+ """AsStringVisitor3k overwrites some AsStringVisitor methods"""
+
+ def visit_excepthandler(self, node):
+ if node.type:
+ if node.name:
+ excs = 'except %s as %s' % (node.type.accept(self),
+ node.name.accept(self))
+ else:
+ excs = 'except %s' % node.type.accept(self)
+ else:
+ excs = 'except'
+ return '%s:\n%s' % (excs, self._stmt_list(node.body))
+
+ def visit_nonlocal(self, node):
+ """return an astroid.Nonlocal node as string"""
+ return 'nonlocal %s' % ', '.join(node.names)
+
+ def visit_raise(self, node):
+ """return an astroid.Raise node as string"""
+ if node.exc:
+ if node.cause:
+ return 'raise %s from %s' % (node.exc.accept(self),
+ node.cause.accept(self))
+ return 'raise %s' % node.exc.accept(self)
+ return 'raise'
+
+ def visit_starred(self, node):
+ """return Starred node as string"""
+ return "*" + node.value.accept(self)
+
+ def visit_yieldfrom(self, node):
+ """ Return an astroid.YieldFrom node as string. """
+ yi_val = node.value and (" " + node.value.accept(self)) or ""
+ expr = 'yield from' + yi_val
+ if node.parent.is_statement:
+ return expr
+ else:
+ return "(%s)" % (expr,)
+
+
+def _import_string(names):
+ """return a list of (name, asname) formatted as a string"""
+ _names = []
+ for name, asname in names:
+ if asname is not None:
+ _names.append('%s as %s' % (name, asname))
+ else:
+ _names.append(name)
+ return ', '.join(_names)
+
+
+if sys.version_info >= (3, 0):
+ AsStringVisitor = AsStringVisitor3k
+
+# this visitor is stateless, thus it can be reused
+to_code = AsStringVisitor()
+
diff -Nru astroid-1.0.1/astroid/astpeephole.py astroid-1.3.8/astroid/astpeephole.py
--- astroid-1.0.1/astroid/astpeephole.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/astpeephole.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,86 @@
+# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""Small AST optimizations."""
+
+import _ast
+
+from astroid import nodes
+
+
+__all__ = ('ASTPeepholeOptimizer', )
+
+
+try:
+ _TYPES = (_ast.Str, _ast.Bytes)
+except AttributeError:
+ _TYPES = (_ast.Str, )
+
+
+class ASTPeepholeOptimizer(object):
+ """Class for applying small optimizations to generate new AST."""
+
+ def optimize_binop(self, node):
+ """Optimize BinOps with string Const nodes on the lhs.
+
+ This fixes an infinite recursion crash, where multiple
+ strings are joined using the addition operator. With a
+ sufficient number of such strings, astroid will fail
+ with a maximum recursion limit exceeded. The
+ function will return a Const node with all the strings
+ already joined.
+ Return ``None`` if no AST node can be obtained
+ through optimization.
+ """
+ ast_nodes = []
+ current = node
+ while isinstance(current, _ast.BinOp):
+ # lhs must be a BinOp with the addition operand.
+ if not isinstance(current.left, _ast.BinOp):
+ return
+ if (not isinstance(current.left.op, _ast.Add)
+ or not isinstance(current.op, _ast.Add)):
+ return
+
+ # rhs must a str / bytes.
+ if not isinstance(current.right, _TYPES):
+ return
+
+ ast_nodes.append(current.right.s)
+ current = current.left
+
+ if (isinstance(current, _ast.BinOp)
+ and isinstance(current.left, _TYPES)
+ and isinstance(current.right, _TYPES)):
+ # Stop early if we are at the last BinOp in
+ # the operation
+ ast_nodes.append(current.right.s)
+ ast_nodes.append(current.left.s)
+ break
+
+ if not ast_nodes:
+ return
+
+ # If we have inconsistent types, bail out.
+ known = type(ast_nodes[0])
+ if any(type(element) is not known
+ for element in ast_nodes[1:]):
+ return
+
+ value = known().join(reversed(ast_nodes))
+ newnode = nodes.Const(value)
+ return newnode
diff -Nru astroid-1.0.1/astroid/bases.py astroid-1.3.8/astroid/bases.py
--- astroid-1.0.1/astroid/bases.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/bases.py 2015-08-02 19:35:55.000000000 +0000
@@ -0,0 +1,652 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""This module contains base classes and functions for the nodes and some
+inference utils.
+"""
+
+__docformat__ = "restructuredtext en"
+
+import sys
+from contextlib import contextmanager
+
+from logilab.common.decorators import cachedproperty
+
+from astroid.exceptions import (InferenceError, AstroidError, NotFoundError,
+ UnresolvableName, UseInferenceDefault)
+
+
+if sys.version_info >= (3, 0):
+ BUILTINS = 'builtins'
+else:
+ BUILTINS = '__builtin__'
+
+
+class Proxy(object):
+ """a simple proxy object"""
+
+ _proxied = None # proxied object may be set by class or by instance
+
+ def __init__(self, proxied=None):
+ if proxied is not None:
+ self._proxied = proxied
+
+ def __getattr__(self, name):
+ if name == '_proxied':
+ return getattr(self.__class__, '_proxied')
+ if name in self.__dict__:
+ return self.__dict__[name]
+ return getattr(self._proxied, name)
+
+ def infer(self, context=None):
+ yield self
+
+
+# Inference ##################################################################
+
+class InferenceContext(object):
+ __slots__ = ('path', 'lookupname', 'callcontext', 'boundnode', 'infered')
+
+ def __init__(self, path=None, infered=None):
+ self.path = path or set()
+ self.lookupname = None
+ self.callcontext = None
+ self.boundnode = None
+ self.infered = infered or {}
+
+ def push(self, node):
+ name = self.lookupname
+ if (node, name) in self.path:
+ raise StopIteration()
+ self.path.add((node, name))
+
+ def clone(self):
+ # XXX copy lookupname/callcontext ?
+ clone = InferenceContext(self.path, infered=self.infered)
+ clone.callcontext = self.callcontext
+ clone.boundnode = self.boundnode
+ return clone
+
+ def cache_generator(self, key, generator):
+ results = []
+ for result in generator:
+ results.append(result)
+ yield result
+
+ self.infered[key] = tuple(results)
+ return
+
+ @contextmanager
+ def restore_path(self):
+ path = set(self.path)
+ yield
+ self.path = path
+
+def copy_context(context):
+ if context is not None:
+ return context.clone()
+ else:
+ return InferenceContext()
+
+
+def _infer_stmts(stmts, context, frame=None):
+ """return an iterator on statements inferred by each statement in
+ """
+ stmt = None
+ infered = False
+ if context is not None:
+ name = context.lookupname
+ context = context.clone()
+ else:
+ name = None
+ context = InferenceContext()
+ for stmt in stmts:
+ if stmt is YES:
+ yield stmt
+ infered = True
+ continue
+ context.lookupname = stmt._infer_name(frame, name)
+ try:
+ for infered in stmt.infer(context):
+ yield infered
+ infered = True
+ except UnresolvableName:
+ continue
+ except InferenceError:
+ yield YES
+ infered = True
+ if not infered:
+ raise InferenceError(str(stmt))
+
+
+# special inference objects (e.g. may be returned as nodes by .infer()) #######
+
+class _Yes(object):
+ """a yes object"""
+ def __repr__(self):
+ return 'YES'
+ def __getattribute__(self, name):
+ if name == 'next':
+ raise AttributeError('next method should not be called')
+ if name.startswith('__') and name.endswith('__'):
+ # to avoid inspection pb
+ return super(_Yes, self).__getattribute__(name)
+ return self
+ def __call__(self, *args, **kwargs):
+ return self
+
+
+YES = _Yes()
+
+
+class Instance(Proxy):
+ """a special node representing a class instance"""
+ def getattr(self, name, context=None, lookupclass=True):
+ try:
+ values = self._proxied.instance_attr(name, context)
+ except NotFoundError:
+ if name == '__class__':
+ return [self._proxied]
+ if lookupclass:
+ # class attributes not available through the instance
+ # unless they are explicitly defined
+ if name in ('__name__', '__bases__', '__mro__', '__subclasses__'):
+ return self._proxied.local_attr(name)
+ return self._proxied.getattr(name, context)
+ raise NotFoundError(name)
+ # since we've no context information, return matching class members as
+ # well
+ if lookupclass:
+ try:
+ return values + self._proxied.getattr(name, context)
+ except NotFoundError:
+ pass
+ return values
+
+ def igetattr(self, name, context=None):
+ """inferred getattr"""
+ if not context:
+ context = InferenceContext()
+ try:
+ # avoid recursively inferring the same attr on the same class
+
+ context.push((self._proxied, name))
+ # XXX frame should be self._proxied, or not ?
+ get_attr = self.getattr(name, context, lookupclass=False)
+ return _infer_stmts(
+ self._wrap_attr(get_attr, context),
+ context,
+ frame=self,
+ )
+ except NotFoundError:
+ try:
+ # fallback to class'igetattr since it has some logic to handle
+ # descriptors
+ return self._wrap_attr(self._proxied.igetattr(name, context),
+ context)
+ except NotFoundError:
+ raise InferenceError(name)
+
+ def _wrap_attr(self, attrs, context=None):
+ """wrap bound methods of attrs in a InstanceMethod proxies"""
+ for attr in attrs:
+ if isinstance(attr, UnboundMethod):
+ if BUILTINS + '.property' in attr.decoratornames():
+ for infered in attr.infer_call_result(self, context):
+ yield infered
+ else:
+ yield BoundMethod(attr, self)
+ else:
+ yield attr
+
+ def infer_call_result(self, caller, context=None):
+ """infer what a class instance is returning when called"""
+ infered = False
+ for node in self._proxied.igetattr('__call__', context):
+ if node is YES:
+ continue
+ for res in node.infer_call_result(caller, context):
+ infered = True
+ yield res
+ if not infered:
+ raise InferenceError()
+
+ def __repr__(self):
+ return '' % (self._proxied.root().name,
+ self._proxied.name,
+ id(self))
+ def __str__(self):
+ return 'Instance of %s.%s' % (self._proxied.root().name,
+ self._proxied.name)
+
+ def callable(self):
+ try:
+ self._proxied.getattr('__call__')
+ return True
+ except NotFoundError:
+ return False
+
+ def pytype(self):
+ return self._proxied.qname()
+
+ def display_type(self):
+ return 'Instance of'
+
+
+class UnboundMethod(Proxy):
+ """a special node representing a method not bound to an instance"""
+ def __repr__(self):
+ frame = self._proxied.parent.frame()
+ return '<%s %s of %s at 0x%s' % (self.__class__.__name__,
+ self._proxied.name,
+ frame.qname(), id(self))
+
+ def is_bound(self):
+ return False
+
+ def getattr(self, name, context=None):
+ if name == 'im_func':
+ return [self._proxied]
+ return super(UnboundMethod, self).getattr(name, context)
+
+ def igetattr(self, name, context=None):
+ if name == 'im_func':
+ return iter((self._proxied,))
+ return super(UnboundMethod, self).igetattr(name, context)
+
+ def infer_call_result(self, caller, context):
+ # If we're unbound method __new__ of builtin object, the result is an
+ # instance of the class given as first argument.
+ if (self._proxied.name == '__new__' and
+ self._proxied.parent.frame().qname() == '%s.object' % BUILTINS):
+ infer = caller.args[0].infer() if caller.args else []
+ return ((x is YES and x or Instance(x)) for x in infer)
+ return self._proxied.infer_call_result(caller, context)
+
+
+class BoundMethod(UnboundMethod):
+ """a special node representing a method bound to an instance"""
+ def __init__(self, proxy, bound):
+ UnboundMethod.__init__(self, proxy)
+ self.bound = bound
+
+ def is_bound(self):
+ return True
+
+ def infer_call_result(self, caller, context):
+ context = context.clone()
+ context.boundnode = self.bound
+ return self._proxied.infer_call_result(caller, context)
+
+
+class Generator(Instance):
+ """a special node representing a generator.
+
+ Proxied class is set once for all in raw_building.
+ """
+ def callable(self):
+ return False
+
+ def pytype(self):
+ return '%s.generator' % BUILTINS
+
+ def display_type(self):
+ return 'Generator'
+
+ def __repr__(self):
+ return '' % (self._proxied.name, self.lineno, id(self))
+
+ def __str__(self):
+ return 'Generator(%s)' % (self._proxied.name)
+
+
+# decorators ##################################################################
+
+def path_wrapper(func):
+ """return the given infer function wrapped to handle the path"""
+ def wrapped(node, context=None, _func=func, **kwargs):
+ """wrapper function handling context"""
+ if context is None:
+ context = InferenceContext()
+ context.push(node)
+ yielded = set()
+ for res in _func(node, context, **kwargs):
+ # unproxy only true instance, not const, tuple, dict...
+ if res.__class__ is Instance:
+ ares = res._proxied
+ else:
+ ares = res
+ if not ares in yielded:
+ yield res
+ yielded.add(ares)
+ return wrapped
+
+def yes_if_nothing_infered(func):
+ def wrapper(*args, **kwargs):
+ infered = False
+ for node in func(*args, **kwargs):
+ infered = True
+ yield node
+ if not infered:
+ yield YES
+ return wrapper
+
+def raise_if_nothing_infered(func):
+ def wrapper(*args, **kwargs):
+ infered = False
+ for node in func(*args, **kwargs):
+ infered = True
+ yield node
+ if not infered:
+ raise InferenceError()
+ return wrapper
+
+
+# Node ######################################################################
+
+class NodeNG(object):
+ """Base Class for all Astroid node classes.
+
+ It represents a node of the new abstract syntax tree.
+ """
+ is_statement = False
+ optional_assign = False # True for For (and for Comprehension if py <3.0)
+ is_function = False # True for Function nodes
+ # attributes below are set by the builder module or by raw factories
+ lineno = None
+ fromlineno = None
+ tolineno = None
+ col_offset = None
+ # parent node in the tree
+ parent = None
+ # attributes containing child node(s) redefined in most concrete classes:
+ _astroid_fields = ()
+ # instance specific inference function infer(node, context)
+ _explicit_inference = None
+
+ def infer(self, context=None, **kwargs):
+ """main interface to the interface system, return a generator on infered
+ values.
+
+ If the instance has some explicit inference function set, it will be
+ called instead of the default interface.
+ """
+ if self._explicit_inference is not None:
+ # explicit_inference is not bound, give it self explicitly
+ try:
+ return self._explicit_inference(self, context, **kwargs)
+ except UseInferenceDefault:
+ pass
+
+ if not context:
+ return self._infer(context, **kwargs)
+
+ key = (self, context.lookupname,
+ context.callcontext, context.boundnode)
+ if key in context.infered:
+ return iter(context.infered[key])
+
+ return context.cache_generator(key, self._infer(context, **kwargs))
+
+ def _repr_name(self):
+ """return self.name or self.attrname or '' for nice representation"""
+ return getattr(self, 'name', getattr(self, 'attrname', ''))
+
+ def __str__(self):
+ return '%s(%s)' % (self.__class__.__name__, self._repr_name())
+
+ def __repr__(self):
+ return '<%s(%s) l.%s [%s] at 0x%x>' % (self.__class__.__name__,
+ self._repr_name(),
+ self.fromlineno,
+ self.root().name,
+ id(self))
+
+
+ def accept(self, visitor):
+ func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
+ return func(self)
+
+ def get_children(self):
+ for field in self._astroid_fields:
+ attr = getattr(self, field)
+ if attr is None:
+ continue
+ if isinstance(attr, (list, tuple)):
+ for elt in attr:
+ yield elt
+ else:
+ yield attr
+
+ def last_child(self):
+ """an optimized version of list(get_children())[-1]"""
+ for field in self._astroid_fields[::-1]:
+ attr = getattr(self, field)
+ if not attr: # None or empty listy / tuple
+ continue
+ if attr.__class__ in (list, tuple):
+ return attr[-1]
+ else:
+ return attr
+ return None
+
+ def parent_of(self, node):
+ """return true if i'm a parent of the given node"""
+ parent = node.parent
+ while parent is not None:
+ if self is parent:
+ return True
+ parent = parent.parent
+ return False
+
+ def statement(self):
+ """return the first parent node marked as statement node"""
+ if self.is_statement:
+ return self
+ return self.parent.statement()
+
+ def frame(self):
+ """return the first parent frame node (i.e. Module, Function or Class)
+ """
+ return self.parent.frame()
+
+ def scope(self):
+ """return the first node defining a new scope (i.e. Module, Function,
+ Class, Lambda but also GenExpr)
+ """
+ return self.parent.scope()
+
+ def root(self):
+ """return the root node of the tree, (i.e. a Module)"""
+ if self.parent:
+ return self.parent.root()
+ return self
+
+ def child_sequence(self, child):
+ """search for the right sequence where the child lies in"""
+ for field in self._astroid_fields:
+ node_or_sequence = getattr(self, field)
+ if node_or_sequence is child:
+ return [node_or_sequence]
+ # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
+ if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
+ return node_or_sequence
+ else:
+ msg = 'Could not find %s in %s\'s children'
+ raise AstroidError(msg % (repr(child), repr(self)))
+
+ def locate_child(self, child):
+ """return a 2-uple (child attribute name, sequence or node)"""
+ for field in self._astroid_fields:
+ node_or_sequence = getattr(self, field)
+ # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
+ if child is node_or_sequence:
+ return field, child
+ if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
+ return field, node_or_sequence
+ msg = 'Could not find %s in %s\'s children'
+ raise AstroidError(msg % (repr(child), repr(self)))
+ # FIXME : should we merge child_sequence and locate_child ? locate_child
+ # is only used in are_exclusive, child_sequence one time in pylint.
+
+ def next_sibling(self):
+ """return the next sibling statement"""
+ return self.parent.next_sibling()
+
+ def previous_sibling(self):
+ """return the previous sibling statement"""
+ return self.parent.previous_sibling()
+
+ def nearest(self, nodes):
+ """return the node which is the nearest before this one in the
+ given list of nodes
+ """
+ myroot = self.root()
+ mylineno = self.fromlineno
+ nearest = None, 0
+ for node in nodes:
+ assert node.root() is myroot, \
+ 'nodes %s and %s are not from the same module' % (self, node)
+ lineno = node.fromlineno
+ if node.fromlineno > mylineno:
+ break
+ if lineno > nearest[1]:
+ nearest = node, lineno
+ # FIXME: raise an exception if nearest is None ?
+ return nearest[0]
+
+ # these are lazy because they're relatively expensive to compute for every
+ # single node, and they rarely get looked at
+
+ @cachedproperty
+ def fromlineno(self):
+ if self.lineno is None:
+ return self._fixed_source_line()
+ else:
+ return self.lineno
+
+ @cachedproperty
+ def tolineno(self):
+ if not self._astroid_fields:
+ # can't have children
+ lastchild = None
+ else:
+ lastchild = self.last_child()
+ if lastchild is None:
+ return self.fromlineno
+ else:
+ return lastchild.tolineno
+
+ # TODO / FIXME:
+ assert self.fromlineno is not None, self
+ assert self.tolineno is not None, self
+
+ def _fixed_source_line(self):
+ """return the line number where the given node appears
+
+ we need this method since not all nodes have the lineno attribute
+ correctly set...
+ """
+ line = self.lineno
+ _node = self
+ try:
+ while line is None:
+ _node = next(_node.get_children())
+ line = _node.lineno
+ except StopIteration:
+ _node = self.parent
+ while _node and line is None:
+ line = _node.lineno
+ _node = _node.parent
+ return line
+
+ def block_range(self, lineno):
+ """handle block line numbers range for non block opening statements
+ """
+ return lineno, self.tolineno
+
+ def set_local(self, name, stmt):
+ """delegate to a scoped parent handling a locals dictionary"""
+ self.parent.set_local(name, stmt)
+
+ def nodes_of_class(self, klass, skip_klass=None):
+ """return an iterator on nodes which are instance of the given class(es)
+
+ klass may be a class object or a tuple of class objects
+ """
+ if isinstance(self, klass):
+ yield self
+ for child_node in self.get_children():
+ if skip_klass is not None and isinstance(child_node, skip_klass):
+ continue
+ for matching in child_node.nodes_of_class(klass, skip_klass):
+ yield matching
+
+ def _infer_name(self, frame, name):
+ # overridden for From, Import, Global, TryExcept and Arguments
+ return None
+
+ def _infer(self, context=None):
+ """we don't know how to resolve a statement by default"""
+ # this method is overridden by most concrete classes
+ raise InferenceError(self.__class__.__name__)
+
+ def infered(self):
+ '''return list of infered values for a more simple inference usage'''
+ return list(self.infer())
+
+ def instanciate_class(self):
+ """instanciate a node if it is a Class node, else return self"""
+ return self
+
+ def has_base(self, node):
+ return False
+
+ def callable(self):
+ return False
+
+ def eq(self, value):
+ return False
+
+ def as_string(self):
+ from astroid.as_string import to_code
+ return to_code(self)
+
+ def repr_tree(self, ids=False):
+ from astroid.as_string import dump
+ return dump(self)
+
+
+class Statement(NodeNG):
+ """Statement node adding a few attributes"""
+ is_statement = True
+
+ def next_sibling(self):
+ """return the next sibling statement"""
+ stmts = self.parent.child_sequence(self)
+ index = stmts.index(self)
+ try:
+ return stmts[index +1]
+ except IndexError:
+ pass
+
+ def previous_sibling(self):
+ """return the previous sibling statement"""
+ stmts = self.parent.child_sequence(self)
+ index = stmts.index(self)
+ if index >= 1:
+ return stmts[index -1]
diff -Nru astroid-1.0.1/astroid/brain/builtin_inference.py astroid-1.3.8/astroid/brain/builtin_inference.py
--- astroid-1.0.1/astroid/brain/builtin_inference.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/brain/builtin_inference.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,245 @@
+"""Astroid hooks for various builtins."""
+
+import sys
+from functools import partial
+from textwrap import dedent
+
+import six
+from astroid import (MANAGER, UseInferenceDefault,
+ inference_tip, YES, InferenceError, UnresolvableName)
+from astroid import nodes
+from astroid.builder import AstroidBuilder
+
+
+def _extend_str(class_node, rvalue):
+ """function to extend builtin str/unicode class"""
+ # TODO(cpopa): this approach will make astroid to believe
+ # that some arguments can be passed by keyword, but
+ # unfortunately, strings and bytes don't accept keyword arguments.
+ code = dedent('''
+ class whatever(object):
+ def join(self, iterable):
+ return {rvalue}
+ def replace(self, old, new, count=None):
+ return {rvalue}
+ def format(self, *args, **kwargs):
+ return {rvalue}
+ def encode(self, encoding='ascii', errors=None):
+ return ''
+ def decode(self, encoding='ascii', errors=None):
+ return u''
+ def capitalize(self):
+ return {rvalue}
+ def title(self):
+ return {rvalue}
+ def lower(self):
+ return {rvalue}
+ def upper(self):
+ return {rvalue}
+ def swapcase(self):
+ return {rvalue}
+ def index(self, sub, start=None, end=None):
+ return 0
+ def find(self, sub, start=None, end=None):
+ return 0
+ def count(self, sub, start=None, end=None):
+ return 0
+ def strip(self, chars=None):
+ return {rvalue}
+ def lstrip(self, chars=None):
+ return {rvalue}
+ def rstrip(self, chars=None):
+ return {rvalue}
+ def rjust(self, width, fillchar=None):
+ return {rvalue}
+ def center(self, width, fillchar=None):
+ return {rvalue}
+ def ljust(self, width, fillchar=None):
+ return {rvalue}
+ ''')
+ code = code.format(rvalue=rvalue)
+ fake = AstroidBuilder(MANAGER).string_build(code)['whatever']
+ for method in fake.mymethods():
+ class_node.locals[method.name] = [method]
+ method.parent = class_node
+
+def extend_builtins(class_transforms):
+ from astroid.bases import BUILTINS
+ builtin_ast = MANAGER.astroid_cache[BUILTINS]
+ for class_name, transform in class_transforms.items():
+ transform(builtin_ast[class_name])
+
+if sys.version_info > (3, 0):
+ extend_builtins({'bytes': partial(_extend_str, rvalue="b''"),
+ 'str': partial(_extend_str, rvalue="''")})
+else:
+ extend_builtins({'str': partial(_extend_str, rvalue="''"),
+ 'unicode': partial(_extend_str, rvalue="u''")})
+
+
+def register_builtin_transform(transform, builtin_name):
+ """Register a new transform function for the given *builtin_name*.
+
+ The transform function must accept two parameters, a node and
+ an optional context.
+ """
+ def _transform_wrapper(node, context=None):
+ result = transform(node, context=context)
+ if result:
+ result.parent = node
+ result.lineno = node.lineno
+ result.col_offset = node.col_offset
+ return iter([result])
+
+ MANAGER.register_transform(nodes.CallFunc,
+ inference_tip(_transform_wrapper),
+ lambda n: (isinstance(n.func, nodes.Name) and
+ n.func.name == builtin_name))
+
+
+def _generic_inference(node, context, node_type, transform):
+ args = node.args
+ if not args:
+ return node_type()
+ if len(node.args) > 1:
+ raise UseInferenceDefault()
+
+ arg, = args
+ transformed = transform(arg)
+ if not transformed:
+ try:
+ infered = next(arg.infer(context=context))
+ except (InferenceError, StopIteration):
+ raise UseInferenceDefault()
+ if infered is YES:
+ raise UseInferenceDefault()
+ transformed = transform(infered)
+ if not transformed or transformed is YES:
+ raise UseInferenceDefault()
+ return transformed
+
+
+def _generic_transform(arg, klass, iterables, build_elts):
+ if isinstance(arg, klass):
+ return arg
+ elif isinstance(arg, iterables):
+ if not all(isinstance(elt, nodes.Const)
+ for elt in arg.elts):
+ # TODO(cpopa): Don't support heterogenous elements.
+ # Not yet, though.
+ raise UseInferenceDefault()
+ elts = [elt.value for elt in arg.elts]
+ elif isinstance(arg, nodes.Dict):
+ if not all(isinstance(elt[0], nodes.Const)
+ for elt in arg.items):
+ raise UseInferenceDefault()
+ elts = [item[0].value for item in arg.items]
+ elif (isinstance(arg, nodes.Const) and
+ isinstance(arg.value, (six.string_types, six.binary_type))):
+ elts = arg.value
+ else:
+ return
+ return klass(elts=build_elts(elts))
+
+
+def _infer_builtin(node, context,
+ klass=None, iterables=None,
+ build_elts=None):
+ transform_func = partial(
+ _generic_transform,
+ klass=klass,
+ iterables=iterables,
+ build_elts=build_elts)
+
+ return _generic_inference(node, context, klass, transform_func)
+
+# pylint: disable=invalid-name
+infer_tuple = partial(
+ _infer_builtin,
+ klass=nodes.Tuple,
+ iterables=(nodes.List, nodes.Set),
+ build_elts=tuple)
+
+infer_list = partial(
+ _infer_builtin,
+ klass=nodes.List,
+ iterables=(nodes.Tuple, nodes.Set),
+ build_elts=list)
+
+infer_set = partial(
+ _infer_builtin,
+ klass=nodes.Set,
+ iterables=(nodes.List, nodes.Tuple),
+ build_elts=set)
+
+
+def _get_elts(arg, context):
+ is_iterable = lambda n: isinstance(n,
+ (nodes.List, nodes.Tuple, nodes.Set))
+ try:
+ infered = next(arg.infer(context))
+ except (InferenceError, UnresolvableName):
+ raise UseInferenceDefault()
+ if isinstance(infered, nodes.Dict):
+ items = infered.items
+ elif is_iterable(infered):
+ items = []
+ for elt in infered.elts:
+ # If an item is not a pair of two items,
+ # then fallback to the default inference.
+ # Also, take in consideration only hashable items,
+ # tuples and consts. We are choosing Names as well.
+ if not is_iterable(elt):
+ raise UseInferenceDefault()
+ if len(elt.elts) != 2:
+ raise UseInferenceDefault()
+ if not isinstance(elt.elts[0],
+ (nodes.Tuple, nodes.Const, nodes.Name)):
+ raise UseInferenceDefault()
+ items.append(tuple(elt.elts))
+ else:
+ raise UseInferenceDefault()
+ return items
+
+def infer_dict(node, context=None):
+ """Try to infer a dict call to a Dict node.
+
+ The function treats the following cases:
+
+ * dict()
+ * dict(mapping)
+ * dict(iterable)
+ * dict(iterable, **kwargs)
+ * dict(mapping, **kwargs)
+ * dict(**kwargs)
+
+ If a case can't be infered, we'll fallback to default inference.
+ """
+ has_keywords = lambda args: all(isinstance(arg, nodes.Keyword)
+ for arg in args)
+ if not node.args and not node.kwargs:
+ # dict()
+ return nodes.Dict()
+ elif has_keywords(node.args) and node.args:
+ # dict(a=1, b=2, c=4)
+ items = [(nodes.Const(arg.arg), arg.value) for arg in node.args]
+ elif (len(node.args) >= 2 and
+ has_keywords(node.args[1:])):
+ # dict(some_iterable, b=2, c=4)
+ elts = _get_elts(node.args[0], context)
+ keys = [(nodes.Const(arg.arg), arg.value) for arg in node.args[1:]]
+ items = elts + keys
+ elif len(node.args) == 1:
+ items = _get_elts(node.args[0], context)
+ else:
+ raise UseInferenceDefault()
+
+ empty = nodes.Dict()
+ empty.items = items
+ return empty
+
+# Builtins inference
+register_builtin_transform(infer_tuple, 'tuple')
+register_builtin_transform(infer_set, 'set')
+register_builtin_transform(infer_list, 'list')
+register_builtin_transform(infer_dict, 'dict')
diff -Nru astroid-1.0.1/astroid/brain/py2gi.py astroid-1.3.8/astroid/brain/py2gi.py
--- astroid-1.0.1/astroid/brain/py2gi.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/brain/py2gi.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,155 @@
+"""Astroid hooks for the Python 2 GObject introspection bindings.
+
+Helps with understanding everything imported from 'gi.repository'
+"""
+
+import inspect
+import itertools
+import sys
+import re
+
+from astroid import MANAGER, AstroidBuildingException
+from astroid.builder import AstroidBuilder
+
+
+_inspected_modules = {}
+
+_identifier_re = r'^[A-Za-z_]\w*$'
+
+def _gi_build_stub(parent):
+ """
+ Inspect the passed module recursively and build stubs for functions,
+ classes, etc.
+ """
+ classes = {}
+ functions = {}
+ constants = {}
+ methods = {}
+ for name in dir(parent):
+ if name.startswith("__"):
+ continue
+
+ # Check if this is a valid name in python
+ if not re.match(_identifier_re, name):
+ continue
+
+ try:
+ obj = getattr(parent, name)
+ except:
+ continue
+
+ if inspect.isclass(obj):
+ classes[name] = obj
+ elif (inspect.isfunction(obj) or
+ inspect.isbuiltin(obj)):
+ functions[name] = obj
+ elif (inspect.ismethod(obj) or
+ inspect.ismethoddescriptor(obj)):
+ methods[name] = obj
+ elif type(obj) in [int, str]:
+ constants[name] = obj
+ elif (str(obj).startswith(" (3, 0)
+PY33 = sys.version_info >= (3, 3)
+
+# general function
+
+def infer_func_form(node, base_type, context=None, enum=False):
+ """Specific inference function for namedtuple or Python 3 enum. """
+ def infer_first(node):
+ try:
+ value = next(node.infer(context=context))
+ if value is YES:
+ raise UseInferenceDefault()
+ else:
+ return value
+ except StopIteration:
+ raise InferenceError()
+
+ # node is a CallFunc node, class name as first argument and generated class
+ # attributes as second argument
+ if len(node.args) != 2:
+ # something weird here, go back to class implementation
+ raise UseInferenceDefault()
+ # namedtuple or enums list of attributes can be a list of strings or a
+ # whitespace-separate string
+ try:
+ name = infer_first(node.args[0]).value
+ names = infer_first(node.args[1])
+ try:
+ attributes = names.value.replace(',', ' ').split()
+ except AttributeError:
+ if not enum:
+ attributes = [infer_first(const).value for const in names.elts]
+ else:
+ # Enums supports either iterator of (name, value) pairs
+ # or mappings.
+ # TODO: support only list, tuples and mappings.
+ if hasattr(names, 'items') and isinstance(names.items, list):
+ attributes = [infer_first(const[0]).value
+ for const in names.items
+ if isinstance(const[0], nodes.Const)]
+ elif hasattr(names, 'elts'):
+ # Enums can support either ["a", "b", "c"]
+ # or [("a", 1), ("b", 2), ...], but they can't
+ # be mixed.
+ if all(isinstance(const, nodes.Tuple)
+ for const in names.elts):
+ attributes = [infer_first(const.elts[0]).value
+ for const in names.elts
+ if isinstance(const, nodes.Tuple)]
+ else:
+ attributes = [infer_first(const).value
+ for const in names.elts]
+ else:
+ raise AttributeError
+ if not attributes:
+ raise AttributeError
+ except (AttributeError, exceptions.InferenceError) as exc:
+ raise UseInferenceDefault()
+ # we want to return a Class node instance with proper attributes set
+ class_node = nodes.Class(name, 'docstring')
+ class_node.parent = node.parent
+ # set base class=tuple
+ class_node.bases.append(base_type)
+ # XXX add __init__(*attributes) method
+ for attr in attributes:
+ fake_node = nodes.EmptyNode()
+ fake_node.parent = class_node
+ class_node.instance_attrs[attr] = [fake_node]
+ return class_node, name, attributes
+
+
+# module specific transformation functions #####################################
+
+def hashlib_transform():
+ template = '''
+
+class %(name)s(object):
+ def __init__(self, value=''): pass
+ def digest(self):
+ return %(digest)s
+ def copy(self):
+ return self
+ def update(self, value): pass
+ def hexdigest(self):
+ return ''
+ @property
+ def name(self):
+ return %(name)r
+ @property
+ def block_size(self):
+ return 1
+ @property
+ def digest_size(self):
+ return 1
+'''
+ algorithms = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
+ classes = "".join(
+ template % {'name': hashfunc, 'digest': 'b""' if PY3K else '""'}
+ for hashfunc in algorithms)
+ return AstroidBuilder(MANAGER).string_build(classes)
+
+
+def collections_transform():
+ return AstroidBuilder(MANAGER).string_build('''
+
+class defaultdict(dict):
+ default_factory = None
+ def __missing__(self, key): pass
+
+class deque(object):
+ maxlen = 0
+ def __init__(self, iterable=None, maxlen=None): pass
+ def append(self, x): pass
+ def appendleft(self, x): pass
+ def clear(self): pass
+ def count(self, x): return 0
+ def extend(self, iterable): pass
+ def extendleft(self, iterable): pass
+ def pop(self): pass
+ def popleft(self): pass
+ def remove(self, value): pass
+ def reverse(self): pass
+ def rotate(self, n): pass
+ def __iter__(self): return self
+
+''')
+
+
+def pkg_resources_transform():
+ return AstroidBuilder(MANAGER).string_build('''
+
+def resource_exists(package_or_requirement, resource_name):
+ pass
+
+def resource_isdir(package_or_requirement, resource_name):
+ pass
+
+def resource_filename(package_or_requirement, resource_name):
+ pass
+
+def resource_stream(package_or_requirement, resource_name):
+ pass
+
+def resource_string(package_or_requirement, resource_name):
+ pass
+
+def resource_listdir(package_or_requirement, resource_name):
+ pass
+
+def extraction_error():
+ pass
+
+def get_cache_path(archive_name, names=()):
+ pass
+
+def postprocess(tempname, filename):
+ pass
+
+def set_extraction_path(path):
+ pass
+
+def cleanup_resources(force=False):
+ pass
+
+''')
+
+
+def subprocess_transform():
+ if PY3K:
+ communicate = (bytes('string', 'ascii'), bytes('string', 'ascii'))
+ init = """
+ def __init__(self, args, bufsize=0, executable=None,
+ stdin=None, stdout=None, stderr=None,
+ preexec_fn=None, close_fds=False, shell=False,
+ cwd=None, env=None, universal_newlines=False,
+ startupinfo=None, creationflags=0, restore_signals=True,
+ start_new_session=False, pass_fds=()):
+ pass
+ """
+ else:
+ communicate = ('string', 'string')
+ init = """
+ def __init__(self, args, bufsize=0, executable=None,
+ stdin=None, stdout=None, stderr=None,
+ preexec_fn=None, close_fds=False, shell=False,
+ cwd=None, env=None, universal_newlines=False,
+ startupinfo=None, creationflags=0):
+ pass
+ """
+ if PY33:
+ wait_signature = 'def wait(self, timeout=None)'
+ else:
+ wait_signature = 'def wait(self)'
+ return AstroidBuilder(MANAGER).string_build('''
+
+class Popen(object):
+ returncode = pid = 0
+ stdin = stdout = stderr = file()
+
+ %(init)s
+
+ def communicate(self, input=None):
+ return %(communicate)r
+ %(wait_signature)s:
+ return self.returncode
+ def poll(self):
+ return self.returncode
+ def send_signal(self, signal):
+ pass
+ def terminate(self):
+ pass
+ def kill(self):
+ pass
+ ''' % {'init': init,
+ 'communicate': communicate,
+ 'wait_signature': wait_signature})
+
+
+# namedtuple support ###########################################################
+
+def looks_like_namedtuple(node):
+ func = node.func
+ if type(func) is nodes.Getattr:
+ return func.attrname == 'namedtuple'
+ if type(func) is nodes.Name:
+ return func.name == 'namedtuple'
+ return False
+
+def infer_named_tuple(node, context=None):
+ """Specific inference function for namedtuple CallFunc node"""
+ class_node, name, attributes = infer_func_form(node, nodes.Tuple._proxied,
+ context=context)
+ fake = AstroidBuilder(MANAGER).string_build('''
+class %(name)s(tuple):
+ _fields = %(fields)r
+ def _asdict(self):
+ return self.__dict__
+ @classmethod
+ def _make(cls, iterable, new=tuple.__new__, len=len):
+ return new(cls, iterable)
+ def _replace(_self, **kwds):
+ result = _self._make(map(kwds.pop, %(fields)r, _self))
+ if kwds:
+ raise ValueError('Got unexpected field names: %%r' %% list(kwds))
+ return result
+ ''' % {'name': name, 'fields': attributes})
+ class_node.locals['_asdict'] = fake.body[0].locals['_asdict']
+ class_node.locals['_make'] = fake.body[0].locals['_make']
+ class_node.locals['_replace'] = fake.body[0].locals['_replace']
+ class_node.locals['_fields'] = fake.body[0].locals['_fields']
+ # we use UseInferenceDefault, we can't be a generator so return an iterator
+ return iter([class_node])
+
+def infer_enum(node, context=None):
+ """ Specific inference function for enum CallFunc node. """
+ enum_meta = nodes.Class("EnumMeta", 'docstring')
+ class_node = infer_func_form(node, enum_meta,
+ context=context, enum=True)[0]
+ return iter([class_node.instanciate_class()])
+
+def infer_enum_class(node):
+ """ Specific inference for enums. """
+ names = set(('Enum', 'IntEnum', 'enum.Enum', 'enum.IntEnum'))
+ for basename in node.basenames:
+ # TODO: doesn't handle subclasses yet. This implementation
+ # is a hack to support enums.
+ if basename not in names:
+ continue
+ if node.root().name == 'enum':
+ # Skip if the class is directly from enum module.
+ break
+ for local, values in node.locals.items():
+ if any(not isinstance(value, nodes.AssName)
+ for value in values):
+ continue
+
+ stmt = values[0].statement()
+ if isinstance(stmt.targets[0], nodes.Tuple):
+ targets = stmt.targets[0].itered()
+ else:
+ targets = stmt.targets
+
+ new_targets = []
+ for target in targets:
+ # Replace all the assignments with our mocked class.
+ classdef = dedent('''
+ class %(name)s(object):
+ @property
+ def value(self):
+ # Not the best return.
+ return None
+ @property
+ def name(self):
+ return %(name)r
+ ''' % {'name': target.name})
+ fake = AstroidBuilder(MANAGER).string_build(classdef)[target.name]
+ fake.parent = target.parent
+ for method in node.mymethods():
+ fake.locals[method.name] = [method]
+ new_targets.append(fake.instanciate_class())
+ node.locals[local] = new_targets
+ break
+ return node
+
+
+MANAGER.register_transform(nodes.CallFunc, inference_tip(infer_named_tuple),
+ looks_like_namedtuple)
+MANAGER.register_transform(nodes.CallFunc, inference_tip(infer_enum),
+ AsStringRegexpPredicate('Enum', 'func'))
+MANAGER.register_transform(nodes.Class, infer_enum_class)
+register_module_extender(MANAGER, 'hashlib', hashlib_transform)
+register_module_extender(MANAGER, 'collections', collections_transform)
+register_module_extender(MANAGER, 'pkg_resources', pkg_resources_transform)
+register_module_extender(MANAGER, 'subprocess', subprocess_transform)
diff -Nru astroid-1.0.1/astroid/brain/pynose.py astroid-1.3.8/astroid/brain/pynose.py
--- astroid-1.0.1/astroid/brain/pynose.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/brain/pynose.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,79 @@
+# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+
+"""Hooks for nose library."""
+
+import re
+import textwrap
+
+import astroid
+import astroid.builder
+
+_BUILDER = astroid.builder.AstroidBuilder(astroid.MANAGER)
+
+
+def _pep8(name, caps=re.compile('([A-Z])')):
+ return caps.sub(lambda m: '_' + m.groups()[0].lower(), name)
+
+
+def _nose_tools_functions():
+ """Get an iterator of names and bound methods."""
+ module = _BUILDER.string_build(textwrap.dedent('''
+ import unittest
+
+ class Test(unittest.TestCase):
+ pass
+ a = Test()
+ '''))
+ try:
+ case = next(module['a'].infer())
+ except astroid.InferenceError:
+ return
+ for method in case.methods():
+ if method.name.startswith('assert') and '_' not in method.name:
+ pep8_name = _pep8(method.name)
+ yield pep8_name, astroid.BoundMethod(method, case)
+
+
+def _nose_tools_transform(node):
+ for method_name, method in _nose_tools_functions():
+ node.locals[method_name] = [method]
+
+
+def _nose_tools_trivial_transform():
+ """Custom transform for the nose.tools module."""
+ stub = _BUILDER.string_build('''__all__ = []''')
+ all_entries = ['ok_', 'eq_']
+
+ for pep8_name, method in _nose_tools_functions():
+ all_entries.append(pep8_name)
+ stub[pep8_name] = method
+
+ # Update the __all__ variable, since nose.tools
+ # does this manually with .append.
+ all_assign = stub['__all__'].parent
+ all_object = astroid.List(all_entries)
+ all_object.parent = all_assign
+ all_assign.value = all_object
+ return stub
+
+
+astroid.register_module_extender(astroid.MANAGER, 'nose.tools.trivial',
+ _nose_tools_trivial_transform)
+astroid.MANAGER.register_transform(astroid.Module, _nose_tools_transform,
+ lambda n: n.name == 'nose.tools')
diff -Nru astroid-1.0.1/astroid/brain/pysix_moves.py astroid-1.3.8/astroid/brain/pysix_moves.py
--- astroid-1.0.1/astroid/brain/pysix_moves.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/brain/pysix_moves.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,261 @@
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option) any
+# later version.
+#
+# astroid is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+
+"""Astroid hooks for six.moves."""
+
+import sys
+from textwrap import dedent
+
+from astroid import MANAGER, register_module_extender
+from astroid.builder import AstroidBuilder
+from astroid.exceptions import AstroidBuildingException
+
+def _indent(text, prefix, predicate=None):
+ """Adds 'prefix' to the beginning of selected lines in 'text'.
+
+ If 'predicate' is provided, 'prefix' will only be added to the lines
+ where 'predicate(line)' is True. If 'predicate' is not provided,
+ it will default to adding 'prefix' to all non-empty lines that do not
+ consist solely of whitespace characters.
+ """
+ if predicate is None:
+ predicate = lambda line: line.strip()
+
+ def prefixed_lines():
+ for line in text.splitlines(True):
+ yield prefix + line if predicate(line) else line
+ return ''.join(prefixed_lines())
+
+
+if sys.version_info[0] == 2:
+ _IMPORTS_2 = """
+ import BaseHTTPServer
+ import CGIHTTPServer
+ import SimpleHTTPServer
+
+ from StringIO import StringIO
+ from cStringIO import StringIO as cStringIO
+ from UserDict import UserDict
+ from UserList import UserList
+ from UserString import UserString
+
+ import __builtin__ as builtins
+ import thread as _thread
+ import dummy_thread as _dummy_thread
+ import ConfigParser as configparser
+ import copy_reg as copyreg
+ from itertools import (imap as map,
+ ifilter as filter,
+ ifilterfalse as filterfalse,
+ izip_longest as zip_longest,
+ izip as zip)
+ import htmlentitydefs as html_entities
+ import HTMLParser as html_parser
+ import httplib as http_client
+ import cookielib as http_cookiejar
+ import Cookie as http_cookies
+ import Queue as queue
+ import repr as reprlib
+ from pipes import quote as shlex_quote
+ import SocketServer as socketserver
+ import SimpleXMLRPCServer as xmlrpc_server
+ import xmlrpclib as xmlrpc_client
+ import _winreg as winreg
+ import robotparser as urllib_robotparser
+ import Tkinter as tkinter
+ import tkFileDialog as tkinter_tkfiledialog
+
+ input = raw_input
+ intern = intern
+ range = xrange
+ xrange = xrange
+ reduce = reduce
+ reload_module = reload
+
+ class UrllibParse(object):
+ import urlparse as _urlparse
+ import urllib as _urllib
+ ParseResult = _urlparse.ParseResult
+ SplitResult = _urlparse.SplitResult
+ parse_qs = _urlparse.parse_qs
+ parse_qsl = _urlparse.parse_qsl
+ urldefrag = _urlparse.urldefrag
+ urljoin = _urlparse.urljoin
+ urlparse = _urlparse.urlparse
+ urlsplit = _urlparse.urlsplit
+ urlunparse = _urlparse.urlunparse
+ urlunsplit = _urlparse.urlunsplit
+ quote = _urllib.quote
+ quote_plus = _urllib.quote_plus
+ unquote = _urllib.unquote
+ unquote_plus = _urllib.unquote_plus
+ urlencode = _urllib.urlencode
+ splitquery = _urllib.splitquery
+ splittag = _urllib.splittag
+ splituser = _urllib.splituser
+ uses_fragment = _urlparse.uses_fragment
+ uses_netloc = _urlparse.uses_netloc
+ uses_params = _urlparse.uses_params
+ uses_query = _urlparse.uses_query
+ uses_relative = _urlparse.uses_relative
+
+ class UrllibError(object):
+ import urllib2 as _urllib2
+ import urllib as _urllib
+ URLError = _urllib2.URLError
+ HTTPError = _urllib2.HTTPError
+ ContentTooShortError = _urllib.ContentTooShortError
+
+ class DummyModule(object):
+ pass
+
+ class UrllibRequest(object):
+ import urlparse as _urlparse
+ import urllib2 as _urllib2
+ import urllib as _urllib
+ urlopen = _urllib2.urlopen
+ install_opener = _urllib2.install_opener
+ build_opener = _urllib2.build_opener
+ pathname2url = _urllib.pathname2url
+ url2pathname = _urllib.url2pathname
+ getproxies = _urllib.getproxies
+ Request = _urllib2.Request
+ OpenerDirector = _urllib2.OpenerDirector
+ HTTPDefaultErrorHandler = _urllib2.HTTPDefaultErrorHandler
+ HTTPRedirectHandler = _urllib2.HTTPRedirectHandler
+ HTTPCookieProcessor = _urllib2.HTTPCookieProcessor
+ ProxyHandler = _urllib2.ProxyHandler
+ BaseHandler = _urllib2.BaseHandler
+ HTTPPasswordMgr = _urllib2.HTTPPasswordMgr
+ HTTPPasswordMgrWithDefaultRealm = _urllib2.HTTPPasswordMgrWithDefaultRealm
+ AbstractBasicAuthHandler = _urllib2.AbstractBasicAuthHandler
+ HTTPBasicAuthHandler = _urllib2.HTTPBasicAuthHandler
+ ProxyBasicAuthHandler = _urllib2.ProxyBasicAuthHandler
+ AbstractDigestAuthHandler = _urllib2.AbstractDigestAuthHandler
+ HTTPDigestAuthHandler = _urllib2.HTTPDigestAuthHandler
+ ProxyDigestAuthHandler = _urllib2.ProxyDigestAuthHandler
+ HTTPHandler = _urllib2.HTTPHandler
+ HTTPSHandler = _urllib2.HTTPSHandler
+ FileHandler = _urllib2.FileHandler
+ FTPHandler = _urllib2.FTPHandler
+ CacheFTPHandler = _urllib2.CacheFTPHandler
+ UnknownHandler = _urllib2.UnknownHandler
+ HTTPErrorProcessor = _urllib2.HTTPErrorProcessor
+ urlretrieve = _urllib.urlretrieve
+ urlcleanup = _urllib.urlcleanup
+ proxy_bypass = _urllib.proxy_bypass
+
+ urllib_parse = UrllibParse()
+ urllib_error = UrllibError()
+ urllib = DummyModule()
+ urllib.request = UrllibRequest()
+ urllib.parse = UrllibParse()
+ urllib.error = UrllibError()
+ """
+else:
+ _IMPORTS_3 = """
+ import _io
+ cStringIO = _io.StringIO
+ filter = filter
+ from itertools import filterfalse
+ input = input
+ from sys import intern
+ map = map
+ range = range
+ from imp import reload as reload_module
+ from functools import reduce
+ from shlex import quote as shlex_quote
+ from io import StringIO
+ from collections import UserDict, UserList, UserString
+ xrange = range
+ zip = zip
+ from itertools import zip_longest
+ import builtins
+ import configparser
+ import copyreg
+ import _dummy_thread
+ import http.cookiejar as http_cookiejar
+ import http.cookies as http_cookies
+ import html.entities as html_entities
+ import html.parser as html_parser
+ import http.client as http_client
+ import http.server
+ BaseHTTPServer = CGIHTTPServer = SimpleHTTPServer = http.server
+ import pickle as cPickle
+ import queue
+ import reprlib
+ import socketserver
+ import _thread
+ import winreg
+ import xmlrpc.server as xmlrpc_server
+ import xmlrpc.client as xmlrpc_client
+ import urllib.robotparser as urllib_robotparser
+ import email.mime.multipart as email_mime_multipart
+ import email.mime.nonmultipart as email_mime_nonmultipart
+ import email.mime.text as email_mime_text
+ import email.mime.base as email_mime_base
+ import urllib.parse as urllib_parse
+ import urllib.error as urllib_error
+ import tkinter
+ import tkinter.dialog as tkinter_dialog
+ import tkinter.filedialog as tkinter_filedialog
+ import tkinter.scrolledtext as tkinter_scrolledtext
+ import tkinter.simpledialog as tkinder_simpledialog
+ import tkinter.tix as tkinter_tix
+ import tkinter.ttk as tkinter_ttk
+ import tkinter.constants as tkinter_constants
+ import tkinter.dnd as tkinter_dnd
+ import tkinter.colorchooser as tkinter_colorchooser
+ import tkinter.commondialog as tkinter_commondialog
+ import tkinter.filedialog as tkinter_tkfiledialog
+ import tkinter.font as tkinter_font
+ import tkinter.messagebox as tkinter_messagebox
+ import urllib.request
+ import urllib.robotparser as urllib_robotparser
+ import urllib.parse as urllib_parse
+ import urllib.error as urllib_error
+ """
+if sys.version_info[0] == 2:
+ _IMPORTS = dedent(_IMPORTS_2)
+else:
+ _IMPORTS = dedent(_IMPORTS_3)
+
+
+def six_moves_transform():
+ code = dedent('''
+ class Moves(object):
+ {}
+ moves = Moves()
+ ''').format(_indent(_IMPORTS, " "))
+ module = AstroidBuilder(MANAGER).string_build(code)
+ module.name = 'six.moves'
+ return module
+
+
+def _six_fail_hook(modname):
+ if modname != 'six.moves':
+ raise AstroidBuildingException
+ module = AstroidBuilder(MANAGER).string_build(_IMPORTS)
+ module.name = 'six.moves'
+ return module
+
+
+register_module_extender(MANAGER, 'six', six_moves_transform)
+register_module_extender(MANAGER, 'requests.packages.urllib3.packages.six',
+ six_moves_transform)
+MANAGER.register_failed_import_hook(_six_fail_hook)
diff -Nru astroid-1.0.1/astroid/builder.py astroid-1.3.8/astroid/builder.py
--- astroid-1.0.1/astroid/builder.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/builder.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,240 @@
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""The AstroidBuilder makes astroid from living object and / or from _ast
+
+The builder is not thread safe and can't be used to parse different sources
+at the same time.
+"""
+from __future__ import with_statement
+
+__docformat__ = "restructuredtext en"
+
+import sys
+from os.path import splitext, basename, exists, abspath
+
+from astroid.exceptions import AstroidBuildingException, InferenceError
+from astroid.raw_building import InspectBuilder
+from astroid.rebuilder import TreeRebuilder
+from astroid.manager import AstroidManager
+from astroid.bases import YES, Instance
+from astroid.modutils import modpath_from_file
+
+from _ast import PyCF_ONLY_AST
+def parse(string):
+ return compile(string, "", 'exec', PyCF_ONLY_AST)
+
+if sys.version_info >= (3, 0):
+ from tokenize import detect_encoding
+
+ def open_source_file(filename):
+ with open(filename, 'rb') as byte_stream:
+ encoding = detect_encoding(byte_stream.readline)[0]
+ stream = open(filename, 'r', newline=None, encoding=encoding)
+ try:
+ data = stream.read()
+ except UnicodeError: # wrong encodingg
+ # detect_encoding returns utf-8 if no encoding specified
+ msg = 'Wrong (%s) or no encoding specified' % encoding
+ raise AstroidBuildingException(msg)
+ return stream, encoding, data
+
+else:
+ import re
+
+ _ENCODING_RGX = re.compile(r"\s*#+.*coding[:=]\s*([-\w.]+)")
+
+ def _guess_encoding(string):
+ """get encoding from a python file as string or return None if not found
+ """
+ # check for UTF-8 byte-order mark
+ if string.startswith('\xef\xbb\xbf'):
+ return 'UTF-8'
+ for line in string.split('\n', 2)[:2]:
+ # check for encoding declaration
+ match = _ENCODING_RGX.match(line)
+ if match is not None:
+ return match.group(1)
+
+ def open_source_file(filename):
+ """get data for parsing a file"""
+ stream = open(filename, 'U')
+ data = stream.read()
+ encoding = _guess_encoding(data)
+ return stream, encoding, data
+
+# ast NG builder ##############################################################
+
+MANAGER = AstroidManager()
+
+class AstroidBuilder(InspectBuilder):
+ """provide astroid building methods"""
+
+ def __init__(self, manager=None):
+ InspectBuilder.__init__(self)
+ self._manager = manager or MANAGER
+
+ def module_build(self, module, modname=None):
+ """build an astroid from a living module instance
+ """
+ node = None
+ path = getattr(module, '__file__', None)
+ if path is not None:
+ path_, ext = splitext(module.__file__)
+ if ext in ('.py', '.pyc', '.pyo') and exists(path_ + '.py'):
+ node = self.file_build(path_ + '.py', modname)
+ if node is None:
+ # this is a built-in module
+ # get a partial representation by introspection
+ node = self.inspect_build(module, modname=modname, path=path)
+ # we have to handle transformation by ourselves since the rebuilder
+ # isn't called for builtin nodes
+ #
+ # XXX it's then only called for Module nodes, not for underlying
+ # nodes
+ node = self._manager.transform(node)
+ return node
+
+ def file_build(self, path, modname=None):
+ """build astroid from a source code file (i.e. from an ast)
+
+ path is expected to be a python source file
+ """
+ try:
+ stream, encoding, data = open_source_file(path)
+ except IOError as exc:
+ msg = 'Unable to load file %r (%s)' % (path, exc)
+ raise AstroidBuildingException(msg)
+ except SyntaxError as exc: # py3k encoding specification error
+ raise AstroidBuildingException(exc)
+ except LookupError as exc: # unknown encoding
+ raise AstroidBuildingException(exc)
+ with stream:
+ # get module name if necessary
+ if modname is None:
+ try:
+ modname = '.'.join(modpath_from_file(path))
+ except ImportError:
+ modname = splitext(basename(path))[0]
+ # build astroid representation
+ module = self._data_build(data, modname, path)
+ return self._post_build(module, encoding)
+
+ def string_build(self, data, modname='', path=None):
+ """build astroid from source code string and return rebuilded astroid"""
+ module = self._data_build(data, modname, path)
+ module.file_bytes = data.encode('utf-8')
+ return self._post_build(module, 'utf-8')
+
+ def _post_build(self, module, encoding):
+ """handles encoding and delayed nodes
+ after a module has been built
+ """
+ module.file_encoding = encoding
+ self._manager.cache_module(module)
+ # post tree building steps after we stored the module in the cache:
+ for from_node in module._from_nodes:
+ if from_node.modname == '__future__':
+ for symbol, _ in from_node.names:
+ module.future_imports.add(symbol)
+ self.add_from_names_to_locals(from_node)
+ # handle delayed assattr nodes
+ for delayed in module._delayed_assattr:
+ self.delayed_assattr(delayed)
+ return module
+
+ def _data_build(self, data, modname, path):
+ """build tree node from data and add some informations"""
+ # this method could be wrapped with a pickle/cache function
+ try:
+ node = parse(data + '\n')
+ except TypeError as exc:
+ raise AstroidBuildingException(exc)
+ if path is not None:
+ node_file = abspath(path)
+ else:
+ node_file = '>'
+ if modname.endswith('.__init__'):
+ modname = modname[:-9]
+ package = True
+ else:
+ package = path and path.find('__init__.py') > -1 or False
+ rebuilder = TreeRebuilder(self._manager)
+ module = rebuilder.visit_module(node, modname, node_file, package)
+ module._from_nodes = rebuilder._from_nodes
+ module._delayed_assattr = rebuilder._delayed_assattr
+ return module
+
+ def add_from_names_to_locals(self, node):
+ """store imported names to the locals;
+ resort the locals if coming from a delayed node
+ """
+
+ _key_func = lambda node: node.fromlineno
+ def sort_locals(my_list):
+ my_list.sort(key=_key_func)
+ for (name, asname) in node.names:
+ if name == '*':
+ try:
+ imported = node.do_import_module()
+ except InferenceError:
+ continue
+ for name in imported.wildcard_import_names():
+ node.parent.set_local(name, node)
+ sort_locals(node.parent.scope().locals[name])
+ else:
+ node.parent.set_local(asname or name, node)
+ sort_locals(node.parent.scope().locals[asname or name])
+
+ def delayed_assattr(self, node):
+ """visit a AssAttr node -> add name to locals, handle members
+ definition
+ """
+ try:
+ frame = node.frame()
+ for infered in node.expr.infer():
+ if infered is YES:
+ continue
+ try:
+ if infered.__class__ is Instance:
+ infered = infered._proxied
+ iattrs = infered.instance_attrs
+ elif isinstance(infered, Instance):
+ # Const, Tuple, ... we may be wrong, may be not, but
+ # anyway we don't want to pollute builtin's namespace
+ continue
+ elif infered.is_function:
+ iattrs = infered.instance_attrs
+ else:
+ iattrs = infered.locals
+ except AttributeError:
+ # XXX log error
+ #import traceback
+ #traceback.print_exc()
+ continue
+ values = iattrs.setdefault(node.attrname, [])
+ if node in values:
+ continue
+ # get assign in __init__ first XXX useful ?
+ if frame.name == '__init__' and values and not \
+ values[0].frame().name == '__init__':
+ values.insert(0, node)
+ else:
+ values.append(node)
+ except InferenceError:
+ pass
+
diff -Nru astroid-1.0.1/astroid/exceptions.py astroid-1.3.8/astroid/exceptions.py
--- astroid-1.0.1/astroid/exceptions.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/exceptions.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,51 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""this module contains exceptions used in the astroid library
+
+"""
+
+__doctype__ = "restructuredtext en"
+
+class AstroidError(Exception):
+ """base exception class for all astroid related exceptions"""
+
+class AstroidBuildingException(AstroidError):
+ """exception class when we are unable to build an astroid representation"""
+
+class ResolveError(AstroidError):
+ """base class of astroid resolution/inference error"""
+
+class NotFoundError(ResolveError):
+ """raised when we are unable to resolve a name"""
+
+class InferenceError(ResolveError):
+ """raised when we are unable to infer a node"""
+
+class UseInferenceDefault(Exception):
+ """exception to be raised in custom inference function to indicate that it
+ should go back to the default behaviour
+ """
+
+class UnresolvableName(InferenceError):
+ """raised when we are unable to resolve a name"""
+
+class NoDefault(AstroidError):
+ """raised by function's `default_value` method when an argument has
+ no default value
+ """
+
diff -Nru astroid-1.0.1/astroid/inference.py astroid-1.3.8/astroid/inference.py
--- astroid-1.0.1/astroid/inference.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/inference.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,405 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""this module contains a set of functions to handle inference on astroid trees
+"""
+
+__doctype__ = "restructuredtext en"
+
+from itertools import chain
+
+from astroid import nodes
+
+from astroid.manager import AstroidManager
+from astroid.exceptions import (AstroidError, InferenceError, NoDefault,
+ NotFoundError, UnresolvableName)
+from astroid.bases import (YES, Instance, InferenceContext,
+ _infer_stmts, copy_context, path_wrapper,
+ raise_if_nothing_infered)
+from astroid.protocols import (
+ _arguments_infer_argname,
+ BIN_OP_METHOD, UNARY_OP_METHOD)
+
+MANAGER = AstroidManager()
+
+
+class CallContext(object):
+ """when inferring a function call, this class is used to remember values
+ given as argument
+ """
+ def __init__(self, args, starargs, dstarargs):
+ self.args = []
+ self.nargs = {}
+ for arg in args:
+ if isinstance(arg, nodes.Keyword):
+ self.nargs[arg.arg] = arg.value
+ else:
+ self.args.append(arg)
+ self.starargs = starargs
+ self.dstarargs = dstarargs
+
+ def infer_argument(self, funcnode, name, context):
+ """infer a function argument value according to the call context"""
+ # 1. search in named keywords
+ try:
+ return self.nargs[name].infer(context)
+ except KeyError:
+ # Function.args.args can be None in astroid (means that we don't have
+ # information on argnames)
+ argindex = funcnode.args.find_argname(name)[0]
+ if argindex is not None:
+ # 2. first argument of instance/class method
+ if argindex == 0 and funcnode.type in ('method', 'classmethod'):
+ if context.boundnode is not None:
+ boundnode = context.boundnode
+ else:
+ # XXX can do better ?
+ boundnode = funcnode.parent.frame()
+ if funcnode.type == 'method':
+ if not isinstance(boundnode, Instance):
+ boundnode = Instance(boundnode)
+ return iter((boundnode,))
+ if funcnode.type == 'classmethod':
+ return iter((boundnode,))
+ # if we have a method, extract one position
+ # from the index, so we'll take in account
+ # the extra parameter represented by `self` or `cls`
+ if funcnode.type in ('method', 'classmethod'):
+ argindex -= 1
+ # 2. search arg index
+ try:
+ return self.args[argindex].infer(context)
+ except IndexError:
+ pass
+ # 3. search in *args (.starargs)
+ if self.starargs is not None:
+ its = []
+ for infered in self.starargs.infer(context):
+ if infered is YES:
+ its.append((YES,))
+ continue
+ try:
+ its.append(infered.getitem(argindex, context).infer(context))
+ except (InferenceError, AttributeError):
+ its.append((YES,))
+ except (IndexError, TypeError):
+ continue
+ if its:
+ return chain(*its)
+ # 4. XXX search in **kwargs (.dstarargs)
+ if self.dstarargs is not None:
+ its = []
+ for infered in self.dstarargs.infer(context):
+ if infered is YES:
+ its.append((YES,))
+ continue
+ try:
+ its.append(infered.getitem(name, context).infer(context))
+ except (InferenceError, AttributeError):
+ its.append((YES,))
+ except (IndexError, TypeError):
+ continue
+ if its:
+ return chain(*its)
+ # 5. */** argument, (Tuple or Dict)
+ if name == funcnode.args.vararg:
+ return iter((nodes.const_factory(())))
+ if name == funcnode.args.kwarg:
+ return iter((nodes.const_factory({})))
+ # 6. return default value if any
+ try:
+ return funcnode.args.default_value(name).infer(context)
+ except NoDefault:
+ raise InferenceError(name)
+
+
+# .infer method ###############################################################
+
+
+def infer_end(self, context=None):
+ """inference's end for node such as Module, Class, Function, Const...
+ """
+ yield self
+nodes.Module._infer = infer_end
+nodes.Class._infer = infer_end
+nodes.Function._infer = infer_end
+nodes.Lambda._infer = infer_end
+nodes.Const._infer = infer_end
+nodes.List._infer = infer_end
+nodes.Tuple._infer = infer_end
+nodes.Dict._infer = infer_end
+nodes.Set._infer = infer_end
+
+def _higher_function_scope(node):
+ """ Search for the first function which encloses the given
+ scope. This can be used for looking up in that function's
+ scope, in case looking up in a lower scope for a particular
+ name fails.
+
+ :param node: A scope node.
+ :returns:
+ ``None``, if no parent function scope was found,
+ otherwise an instance of :class:`astroid.scoped_nodes.Function`,
+ which encloses the given node.
+ """
+ current = node
+ while current.parent and not isinstance(current.parent, nodes.Function):
+ current = current.parent
+ if current and current.parent:
+ return current.parent
+
+def infer_name(self, context=None):
+ """infer a Name: use name lookup rules"""
+ frame, stmts = self.lookup(self.name)
+ if not stmts:
+ # Try to see if the name is enclosed in a nested function
+ # and use the higher (first function) scope for searching.
+ # TODO: should this be promoted to other nodes as well?
+ parent_function = _higher_function_scope(self.scope())
+ if parent_function:
+ _, stmts = parent_function.lookup(self.name)
+
+ if not stmts:
+ raise UnresolvableName(self.name)
+ context = context.clone()
+ context.lookupname = self.name
+ return _infer_stmts(stmts, context, frame)
+nodes.Name._infer = path_wrapper(infer_name)
+nodes.AssName.infer_lhs = infer_name # won't work with a path wrapper
+
+
+def infer_callfunc(self, context=None):
+ """infer a CallFunc node by trying to guess what the function returns"""
+ callcontext = context.clone()
+ callcontext.callcontext = CallContext(self.args, self.starargs, self.kwargs)
+ callcontext.boundnode = None
+ for callee in self.func.infer(context):
+ if callee is YES:
+ yield callee
+ continue
+ try:
+ if hasattr(callee, 'infer_call_result'):
+ for infered in callee.infer_call_result(self, callcontext):
+ yield infered
+ except InferenceError:
+ ## XXX log error ?
+ continue
+nodes.CallFunc._infer = path_wrapper(raise_if_nothing_infered(infer_callfunc))
+
+
+def infer_import(self, context=None, asname=True):
+ """infer an Import node: return the imported module/object"""
+ name = context.lookupname
+ if name is None:
+ raise InferenceError()
+ if asname:
+ yield self.do_import_module(self.real_name(name))
+ else:
+ yield self.do_import_module(name)
+nodes.Import._infer = path_wrapper(infer_import)
+
+def infer_name_module(self, name):
+ context = InferenceContext()
+ context.lookupname = name
+ return self.infer(context, asname=False)
+nodes.Import.infer_name_module = infer_name_module
+
+
+def infer_from(self, context=None, asname=True):
+ """infer a From nodes: return the imported module/object"""
+ name = context.lookupname
+ if name is None:
+ raise InferenceError()
+ if asname:
+ name = self.real_name(name)
+ module = self.do_import_module()
+ try:
+ context = copy_context(context)
+ context.lookupname = name
+ return _infer_stmts(module.getattr(name, ignore_locals=module is self.root()), context)
+ except NotFoundError:
+ raise InferenceError(name)
+nodes.From._infer = path_wrapper(infer_from)
+
+
+def infer_getattr(self, context=None):
+ """infer a Getattr node by using getattr on the associated object"""
+ for owner in self.expr.infer(context):
+ if owner is YES:
+ yield owner
+ continue
+ try:
+ context.boundnode = owner
+ for obj in owner.igetattr(self.attrname, context):
+ yield obj
+ context.boundnode = None
+ except (NotFoundError, InferenceError):
+ context.boundnode = None
+ except AttributeError:
+ # XXX method / function
+ context.boundnode = None
+nodes.Getattr._infer = path_wrapper(raise_if_nothing_infered(infer_getattr))
+nodes.AssAttr.infer_lhs = raise_if_nothing_infered(infer_getattr) # # won't work with a path wrapper
+
+
+def infer_global(self, context=None):
+ if context.lookupname is None:
+ raise InferenceError()
+ try:
+ return _infer_stmts(self.root().getattr(context.lookupname), context)
+ except NotFoundError:
+ raise InferenceError()
+nodes.Global._infer = path_wrapper(infer_global)
+
+
+def infer_subscript(self, context=None):
+ """infer simple subscription such as [1,2,3][0] or (1,2,3)[-1]"""
+ value = next(self.value.infer(context))
+ if value is YES:
+ yield YES
+ return
+
+ index = next(self.slice.infer(context))
+ if index is YES:
+ yield YES
+ return
+
+ if isinstance(index, nodes.Const):
+ try:
+ assigned = value.getitem(index.value, context)
+ except AttributeError:
+ raise InferenceError()
+ except (IndexError, TypeError):
+ yield YES
+ return
+
+ # Prevent inferring if the infered subscript
+ # is the same as the original subscripted object.
+ if self is assigned:
+ yield YES
+ return
+ for infered in assigned.infer(context):
+ yield infered
+ else:
+ raise InferenceError()
+nodes.Subscript._infer = path_wrapper(infer_subscript)
+nodes.Subscript.infer_lhs = raise_if_nothing_infered(infer_subscript)
+
+def infer_unaryop(self, context=None):
+ for operand in self.operand.infer(context):
+ try:
+ yield operand.infer_unary_op(self.op)
+ except TypeError:
+ continue
+ except AttributeError:
+ meth = UNARY_OP_METHOD[self.op]
+ if meth is None:
+ yield YES
+ else:
+ try:
+ # XXX just suppose if the type implement meth, returned type
+ # will be the same
+ operand.getattr(meth)
+ yield operand
+ except GeneratorExit:
+ raise
+ except:
+ yield YES
+nodes.UnaryOp._infer = path_wrapper(infer_unaryop)
+
+def _infer_binop(operator, operand1, operand2, context, failures=None):
+ if operand1 is YES:
+ yield operand1
+ return
+ try:
+ for valnode in operand1.infer_binary_op(operator, operand2, context):
+ yield valnode
+ except AttributeError:
+ try:
+ # XXX just suppose if the type implement meth, returned type
+ # will be the same
+ operand1.getattr(BIN_OP_METHOD[operator])
+ yield operand1
+ except:
+ if failures is None:
+ yield YES
+ else:
+ failures.append(operand1)
+
+def infer_binop(self, context=None):
+ failures = []
+ for lhs in self.left.infer(context):
+ for val in _infer_binop(self.op, lhs, self.right, context, failures):
+ yield val
+ for lhs in failures:
+ for rhs in self.right.infer(context):
+ for val in _infer_binop(self.op, rhs, lhs, context):
+ yield val
+nodes.BinOp._infer = path_wrapper(infer_binop)
+
+
+def infer_arguments(self, context=None):
+ name = context.lookupname
+ if name is None:
+ raise InferenceError()
+ return _arguments_infer_argname(self, name, context)
+nodes.Arguments._infer = infer_arguments
+
+
+def infer_ass(self, context=None):
+ """infer a AssName/AssAttr: need to inspect the RHS part of the
+ assign node
+ """
+ stmt = self.statement()
+ if isinstance(stmt, nodes.AugAssign):
+ return stmt.infer(context)
+ stmts = list(self.assigned_stmts(context=context))
+ return _infer_stmts(stmts, context)
+nodes.AssName._infer = path_wrapper(infer_ass)
+nodes.AssAttr._infer = path_wrapper(infer_ass)
+
+def infer_augassign(self, context=None):
+ failures = []
+ for lhs in self.target.infer_lhs(context):
+ for val in _infer_binop(self.op, lhs, self.value, context, failures):
+ yield val
+ for lhs in failures:
+ for rhs in self.value.infer(context):
+ for val in _infer_binop(self.op, rhs, lhs, context):
+ yield val
+nodes.AugAssign._infer = path_wrapper(infer_augassign)
+
+
+# no infer method on DelName and DelAttr (expected InferenceError)
+
+
+def infer_empty_node(self, context=None):
+ if not self.has_underlying_object():
+ yield YES
+ else:
+ try:
+ for infered in MANAGER.infer_ast_from_something(self.object,
+ context=context):
+ yield infered
+ except AstroidError:
+ yield YES
+nodes.EmptyNode._infer = path_wrapper(infer_empty_node)
+
+
+def infer_index(self, context=None):
+ return self.value.infer(context)
+nodes.Index._infer = infer_index
diff -Nru astroid-1.0.1/astroid/__init__.py astroid-1.3.8/astroid/__init__.py
--- astroid-1.0.1/astroid/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/__init__.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,131 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""Python Abstract Syntax Tree New Generation
+
+The aim of this module is to provide a common base representation of
+python source code for projects such as pychecker, pyreverse,
+pylint... Well, actually the development of this library is essentially
+governed by pylint's needs.
+
+It extends class defined in the python's _ast module with some
+additional methods and attributes. Instance attributes are added by a
+builder object, which can either generate extended ast (let's call
+them astroid ;) by visiting an existent ast tree or by inspecting living
+object. Methods are added by monkey patching ast classes.
+
+Main modules are:
+
+* nodes and scoped_nodes for more information about methods and
+ attributes added to different node classes
+
+* the manager contains a high level object to get astroid trees from
+ source files and living objects. It maintains a cache of previously
+ constructed tree for quick access
+
+* builder contains the class responsible to build astroid trees
+"""
+__doctype__ = "restructuredtext en"
+
+import sys
+import re
+from operator import attrgetter
+
+# WARNING: internal imports order matters !
+
+# make all exception classes accessible from astroid package
+from astroid.exceptions import *
+
+# make all node classes accessible from astroid package
+from astroid.nodes import *
+
+# trigger extra monkey-patching
+from astroid import inference
+
+# more stuff available
+from astroid import raw_building
+from astroid.bases import YES, Instance, BoundMethod, UnboundMethod
+from astroid.node_classes import are_exclusive, unpack_infer
+from astroid.scoped_nodes import builtin_lookup
+
+# make a manager instance (borg) as well as Project and Package classes
+# accessible from astroid package
+from astroid.manager import AstroidManager, Project
+MANAGER = AstroidManager()
+del AstroidManager
+
+# transform utilities (filters and decorator)
+
+class AsStringRegexpPredicate(object):
+ """Class to be used as predicate that may be given to `register_transform`
+
+ First argument is a regular expression that will be searched against the `as_string`
+ representation of the node onto which it's applied.
+
+ If specified, the second argument is an `attrgetter` expression that will be
+ applied on the node first to get the actual node on which `as_string` should
+ be called.
+
+ WARNING: This can be fairly slow, as it has to convert every AST node back
+ to Python code; you should consider examining the AST directly instead.
+ """
+ def __init__(self, regexp, expression=None):
+ self.regexp = re.compile(regexp)
+ self.expression = expression
+
+ def __call__(self, node):
+ if self.expression is not None:
+ node = attrgetter(self.expression)(node)
+ return self.regexp.search(node.as_string())
+
+def inference_tip(infer_function):
+ """Given an instance specific inference function, return a function to be
+ given to MANAGER.register_transform to set this inference function.
+
+ Typical usage
+
+ .. sourcecode:: python
+
+ MANAGER.register_transform(CallFunc, inference_tip(infer_named_tuple),
+ predicate)
+ """
+ def transform(node, infer_function=infer_function):
+ node._explicit_inference = infer_function
+ return node
+ return transform
+
+
+def register_module_extender(manager, module_name, get_extension_mod):
+ def transform(node):
+ extension_module = get_extension_mod()
+ for name, obj in extension_module.locals.items():
+ node.locals[name] = obj
+
+ manager.register_transform(Module, transform, lambda n: n.name == module_name)
+
+
+# load brain plugins
+from os import listdir
+from os.path import join, dirname
+BRAIN_MODULES_DIR = join(dirname(__file__), 'brain')
+if BRAIN_MODULES_DIR not in sys.path:
+ # add it to the end of the list so user path take precedence
+ sys.path.append(BRAIN_MODULES_DIR)
+# load modules in this directory
+for module in listdir(BRAIN_MODULES_DIR):
+ if module.endswith('.py'):
+ __import__(module[:-3])
diff -Nru astroid-1.0.1/astroid/inspector.py astroid-1.3.8/astroid/inspector.py
--- astroid-1.0.1/astroid/inspector.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/inspector.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,273 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""visitor doing some postprocessing on the astroid tree.
+Try to resolve definitions (namespace) dictionary, relationship...
+
+This module has been imported from pyreverse
+"""
+
+__docformat__ = "restructuredtext en"
+
+from os.path import dirname
+
+import astroid
+from astroid.exceptions import InferenceError
+from astroid.utils import LocalsVisitor
+from astroid.modutils import get_module_part, is_relative, is_standard_module
+
+class IdGeneratorMixIn(object):
+ """
+ Mixin adding the ability to generate integer uid
+ """
+ def __init__(self, start_value=0):
+ self.id_count = start_value
+
+ def init_counter(self, start_value=0):
+ """init the id counter
+ """
+ self.id_count = start_value
+
+ def generate_id(self):
+ """generate a new identifier
+ """
+ self.id_count += 1
+ return self.id_count
+
+
+class Linker(IdGeneratorMixIn, LocalsVisitor):
+ """
+ walk on the project tree and resolve relationships.
+
+ According to options the following attributes may be added to visited nodes:
+
+ * uid,
+ a unique identifier for the node (on astroid.Project, astroid.Module,
+ astroid.Class and astroid.locals_type). Only if the linker has been instantiated
+ with tag=True parameter (False by default).
+
+ * Function
+ a mapping from locals names to their bounded value, which may be a
+ constant like a string or an integer, or an astroid node (on astroid.Module,
+ astroid.Class and astroid.Function).
+
+ * instance_attrs_type
+ as locals_type but for klass member attributes (only on astroid.Class)
+
+ * implements,
+ list of implemented interface _objects_ (only on astroid.Class nodes)
+ """
+
+ def __init__(self, project, inherited_interfaces=0, tag=False):
+ IdGeneratorMixIn.__init__(self)
+ LocalsVisitor.__init__(self)
+ # take inherited interface in consideration or not
+ self.inherited_interfaces = inherited_interfaces
+ # tag nodes or not
+ self.tag = tag
+ # visited project
+ self.project = project
+
+
+ def visit_project(self, node):
+ """visit an astroid.Project node
+
+ * optionally tag the node with a unique id
+ """
+ if self.tag:
+ node.uid = self.generate_id()
+ for module in node.modules:
+ self.visit(module)
+
+ def visit_package(self, node):
+ """visit an astroid.Package node
+
+ * optionally tag the node with a unique id
+ """
+ if self.tag:
+ node.uid = self.generate_id()
+ for subelmt in node.values():
+ self.visit(subelmt)
+
+ def visit_module(self, node):
+ """visit an astroid.Module node
+
+ * set the locals_type mapping
+ * set the depends mapping
+ * optionally tag the node with a unique id
+ """
+ if hasattr(node, 'locals_type'):
+ return
+ node.locals_type = {}
+ node.depends = []
+ if self.tag:
+ node.uid = self.generate_id()
+
+ def visit_class(self, node):
+ """visit an astroid.Class node
+
+ * set the locals_type and instance_attrs_type mappings
+ * set the implements list and build it
+ * optionally tag the node with a unique id
+ """
+ if hasattr(node, 'locals_type'):
+ return
+ node.locals_type = {}
+ if self.tag:
+ node.uid = self.generate_id()
+ # resolve ancestors
+ for baseobj in node.ancestors(recurs=False):
+ specializations = getattr(baseobj, 'specializations', [])
+ specializations.append(node)
+ baseobj.specializations = specializations
+ # resolve instance attributes
+ node.instance_attrs_type = {}
+ for assattrs in node.instance_attrs.values():
+ for assattr in assattrs:
+ self.handle_assattr_type(assattr, node)
+ # resolve implemented interface
+ try:
+ node.implements = list(node.interfaces(self.inherited_interfaces))
+ except InferenceError:
+ node.implements = ()
+
+ def visit_function(self, node):
+ """visit an astroid.Function node
+
+ * set the locals_type mapping
+ * optionally tag the node with a unique id
+ """
+ if hasattr(node, 'locals_type'):
+ return
+ node.locals_type = {}
+ if self.tag:
+ node.uid = self.generate_id()
+
+ link_project = visit_project
+ link_module = visit_module
+ link_class = visit_class
+ link_function = visit_function
+
+ def visit_assname(self, node):
+ """visit an astroid.AssName node
+
+ handle locals_type
+ """
+ # avoid double parsing done by different Linkers.visit
+ # running over the same project:
+ if hasattr(node, '_handled'):
+ return
+ node._handled = True
+ if node.name in node.frame():
+ frame = node.frame()
+ else:
+ # the name has been defined as 'global' in the frame and belongs
+ # there. Btw the frame is not yet visited as the name is in the
+ # root locals; the frame hence has no locals_type attribute
+ frame = node.root()
+ try:
+ values = node.infered()
+ try:
+ already_infered = frame.locals_type[node.name]
+ for valnode in values:
+ if not valnode in already_infered:
+ already_infered.append(valnode)
+ except KeyError:
+ frame.locals_type[node.name] = values
+ except astroid.InferenceError:
+ pass
+
+ def handle_assattr_type(self, node, parent):
+ """handle an astroid.AssAttr node
+
+ handle instance_attrs_type
+ """
+ try:
+ values = list(node.infer())
+ try:
+ already_infered = parent.instance_attrs_type[node.attrname]
+ for valnode in values:
+ if not valnode in already_infered:
+ already_infered.append(valnode)
+ except KeyError:
+ parent.instance_attrs_type[node.attrname] = values
+ except astroid.InferenceError:
+ pass
+
+ def visit_import(self, node):
+ """visit an astroid.Import node
+
+ resolve module dependencies
+ """
+ context_file = node.root().file
+ for name in node.names:
+ relative = is_relative(name[0], context_file)
+ self._imported_module(node, name[0], relative)
+
+
+ def visit_from(self, node):
+ """visit an astroid.From node
+
+ resolve module dependencies
+ """
+ basename = node.modname
+ context_file = node.root().file
+ if context_file is not None:
+ relative = is_relative(basename, context_file)
+ else:
+ relative = False
+ for name in node.names:
+ if name[0] == '*':
+ continue
+ # analyze dependencies
+ fullname = '%s.%s' % (basename, name[0])
+ if fullname.find('.') > -1:
+ try:
+ # XXX: don't use get_module_part, missing package precedence
+ fullname = get_module_part(fullname, context_file)
+ except ImportError:
+ continue
+ if fullname != basename:
+ self._imported_module(node, fullname, relative)
+
+
+ def compute_module(self, context_name, mod_path):
+ """return true if the module should be added to dependencies"""
+ package_dir = dirname(self.project.path)
+ if context_name == mod_path:
+ return 0
+ elif is_standard_module(mod_path, (package_dir,)):
+ return 1
+ return 0
+
+ # protected methods ########################################################
+
+ def _imported_module(self, node, mod_path, relative):
+ """notify an imported module, used to analyze dependencies
+ """
+ module = node.root()
+ context_name = module.name
+ if relative:
+ mod_path = '%s.%s' % ('.'.join(context_name.split('.')[:-1]),
+ mod_path)
+ if self.compute_module(context_name, mod_path):
+ # handle dependencies
+ if not hasattr(module, 'depends'):
+ module.depends = []
+ mod_paths = module.depends
+ if not mod_path in mod_paths:
+ mod_paths.append(mod_path)
diff -Nru astroid-1.0.1/astroid/manager.py astroid-1.3.8/astroid/manager.py
--- astroid-1.0.1/astroid/manager.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/manager.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,391 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""astroid manager: avoid multiple astroid build of a same module when
+possible by providing a class responsible to get astroid representation
+from various source and using a cache of built modules)
+"""
+from __future__ import print_function
+
+__docformat__ = "restructuredtext en"
+
+import collections
+import imp
+import os
+from os.path import dirname, join, isdir, exists
+from warnings import warn
+import zipimport
+
+from logilab.common.configuration import OptionsProviderMixIn
+
+from astroid.exceptions import AstroidBuildingException
+from astroid import modutils
+
+
+def astroid_wrapper(func, modname):
+ """wrapper to give to AstroidManager.project_from_files"""
+ print('parsing %s...' % modname)
+ try:
+ return func(modname)
+ except AstroidBuildingException as exc:
+ print(exc)
+ except Exception as exc:
+ import traceback
+ traceback.print_exc()
+
+def _silent_no_wrap(func, modname):
+ """silent wrapper that doesn't do anything; can be used for tests"""
+ return func(modname)
+
+def safe_repr(obj):
+ try:
+ return repr(obj)
+ except:
+ return '???'
+
+
+
+class AstroidManager(OptionsProviderMixIn):
+ """the astroid manager, responsible to build astroid from files
+ or modules.
+
+ Use the Borg pattern.
+ """
+
+ name = 'astroid loader'
+ options = (("ignore",
+ {'type' : "csv", 'metavar' : "",
+ 'dest' : "black_list", "default" : ('CVS',),
+ 'help' : "add (may be a directory) to the black list\
+. It should be a base name, not a path. You may set this option multiple times\
+."}),
+ ("project",
+ {'default': "No Name", 'type' : 'string', 'short': 'p',
+ 'metavar' : '',
+ 'help' : 'set the project name.'}),
+ )
+ brain = {}
+ def __init__(self):
+ self.__dict__ = AstroidManager.brain
+ if not self.__dict__:
+ OptionsProviderMixIn.__init__(self)
+ self.load_defaults()
+ # NOTE: cache entries are added by the [re]builder
+ self.astroid_cache = {}
+ self._mod_file_cache = {}
+ self.transforms = collections.defaultdict(list)
+ self._failed_import_hooks = []
+ self.always_load_extensions = False
+ self.optimize_ast = False
+ self.extension_package_whitelist = set()
+
+ def ast_from_file(self, filepath, modname=None, fallback=True, source=False):
+ """given a module name, return the astroid object"""
+ try:
+ filepath = modutils.get_source_file(filepath, include_no_ext=True)
+ source = True
+ except modutils.NoSourceFile:
+ pass
+ if modname is None:
+ try:
+ modname = '.'.join(modutils.modpath_from_file(filepath))
+ except ImportError:
+ modname = filepath
+ if modname in self.astroid_cache and self.astroid_cache[modname].file == filepath:
+ return self.astroid_cache[modname]
+ if source:
+ from astroid.builder import AstroidBuilder
+ return AstroidBuilder(self).file_build(filepath, modname)
+ elif fallback and modname:
+ return self.ast_from_module_name(modname)
+ raise AstroidBuildingException('unable to get astroid for file %s' %
+ filepath)
+
+ def _build_stub_module(self, modname):
+ from astroid.builder import AstroidBuilder
+ return AstroidBuilder(self).string_build('', modname)
+
+ def _can_load_extension(self, modname):
+ if self.always_load_extensions:
+ return True
+ if modutils.is_standard_module(modname):
+ return True
+ parts = modname.split('.')
+ return any(
+ '.'.join(parts[:x]) in self.extension_package_whitelist
+ for x in range(1, len(parts) + 1))
+
+ def ast_from_module_name(self, modname, context_file=None):
+ """given a module name, return the astroid object"""
+ if modname in self.astroid_cache:
+ return self.astroid_cache[modname]
+ if modname == '__main__':
+ return self._build_stub_module(modname)
+ old_cwd = os.getcwd()
+ if context_file:
+ os.chdir(dirname(context_file))
+ try:
+ filepath, mp_type = self.file_from_module_name(modname, context_file)
+ if mp_type == modutils.PY_ZIPMODULE:
+ module = self.zip_import_data(filepath)
+ if module is not None:
+ return module
+ elif mp_type in (imp.C_BUILTIN, imp.C_EXTENSION):
+ if mp_type == imp.C_EXTENSION and not self._can_load_extension(modname):
+ return self._build_stub_module(modname)
+ try:
+ module = modutils.load_module_from_name(modname)
+ except Exception as ex:
+ msg = 'Unable to load module %s (%s)' % (modname, ex)
+ raise AstroidBuildingException(msg)
+ return self.ast_from_module(module, modname)
+ elif mp_type == imp.PY_COMPILED:
+ raise AstroidBuildingException("Unable to load compiled module %s" % (modname,))
+ if filepath is None:
+ raise AstroidBuildingException("Unable to load module %s" % (modname,))
+ return self.ast_from_file(filepath, modname, fallback=False)
+ except AstroidBuildingException as e:
+ for hook in self._failed_import_hooks:
+ try:
+ return hook(modname)
+ except AstroidBuildingException:
+ pass
+ raise e
+ finally:
+ os.chdir(old_cwd)
+
+ def zip_import_data(self, filepath):
+ if zipimport is None:
+ return None
+ from astroid.builder import AstroidBuilder
+ builder = AstroidBuilder(self)
+ for ext in ('.zip', '.egg'):
+ try:
+ eggpath, resource = filepath.rsplit(ext + os.path.sep, 1)
+ except ValueError:
+ continue
+ try:
+ importer = zipimport.zipimporter(eggpath + ext)
+ zmodname = resource.replace(os.path.sep, '.')
+ if importer.is_package(resource):
+ zmodname = zmodname + '.__init__'
+ module = builder.string_build(importer.get_source(resource),
+ zmodname, filepath)
+ return module
+ except:
+ continue
+ return None
+
+ def file_from_module_name(self, modname, contextfile):
+ try:
+ value = self._mod_file_cache[(modname, contextfile)]
+ except KeyError:
+ try:
+ value = modutils.file_info_from_modpath(
+ modname.split('.'), context_file=contextfile)
+ except ImportError as ex:
+ msg = 'Unable to load module %s (%s)' % (modname, ex)
+ value = AstroidBuildingException(msg)
+ self._mod_file_cache[(modname, contextfile)] = value
+ if isinstance(value, AstroidBuildingException):
+ raise value
+ return value
+
+ def ast_from_module(self, module, modname=None):
+ """given an imported module, return the astroid object"""
+ modname = modname or module.__name__
+ if modname in self.astroid_cache:
+ return self.astroid_cache[modname]
+ try:
+ # some builtin modules don't have __file__ attribute
+ filepath = module.__file__
+ if modutils.is_python_source(filepath):
+ return self.ast_from_file(filepath, modname)
+ except AttributeError:
+ pass
+ from astroid.builder import AstroidBuilder
+ return AstroidBuilder(self).module_build(module, modname)
+
+ def ast_from_class(self, klass, modname=None):
+ """get astroid for the given class"""
+ if modname is None:
+ try:
+ modname = klass.__module__
+ except AttributeError:
+ raise AstroidBuildingException(
+ 'Unable to get module for class %s' % safe_repr(klass))
+ modastroid = self.ast_from_module_name(modname)
+ return modastroid.getattr(klass.__name__)[0] # XXX
+
+
+ def infer_ast_from_something(self, obj, context=None):
+ """infer astroid for the given class"""
+ if hasattr(obj, '__class__') and not isinstance(obj, type):
+ klass = obj.__class__
+ else:
+ klass = obj
+ try:
+ modname = klass.__module__
+ except AttributeError:
+ raise AstroidBuildingException(
+ 'Unable to get module for %s' % safe_repr(klass))
+ except Exception as ex:
+ raise AstroidBuildingException(
+ 'Unexpected error while retrieving module for %s: %s'
+ % (safe_repr(klass), ex))
+ try:
+ name = klass.__name__
+ except AttributeError:
+ raise AstroidBuildingException(
+ 'Unable to get name for %s' % safe_repr(klass))
+ except Exception as ex:
+ raise AstroidBuildingException(
+ 'Unexpected error while retrieving name for %s: %s'
+ % (safe_repr(klass), ex))
+ # take care, on living object __module__ is regularly wrong :(
+ modastroid = self.ast_from_module_name(modname)
+ if klass is obj:
+ for infered in modastroid.igetattr(name, context):
+ yield infered
+ else:
+ for infered in modastroid.igetattr(name, context):
+ yield infered.instanciate_class()
+
+ def project_from_files(self, files, func_wrapper=astroid_wrapper,
+ project_name=None, black_list=None):
+ """return a Project from a list of files or modules"""
+ # build the project representation
+ project_name = project_name or self.config.project
+ black_list = black_list or self.config.black_list
+ project = Project(project_name)
+ for something in files:
+ if not exists(something):
+ fpath = modutils.file_from_modpath(something.split('.'))
+ elif isdir(something):
+ fpath = join(something, '__init__.py')
+ else:
+ fpath = something
+ astroid = func_wrapper(self.ast_from_file, fpath)
+ if astroid is None:
+ continue
+ # XXX why is first file defining the project.path ?
+ project.path = project.path or astroid.file
+ project.add_module(astroid)
+ base_name = astroid.name
+ # recurse in package except if __init__ was explicitly given
+ if astroid.package and something.find('__init__') == -1:
+ # recurse on others packages / modules if this is a package
+ for fpath in modutils.get_module_files(dirname(astroid.file),
+ black_list):
+ astroid = func_wrapper(self.ast_from_file, fpath)
+ if astroid is None or astroid.name == base_name:
+ continue
+ project.add_module(astroid)
+ return project
+
+ def register_transform(self, node_class, transform, predicate=None):
+ """Register `transform(node)` function to be applied on the given
+ Astroid's `node_class` if `predicate` is None or returns true
+ when called with the node as argument.
+
+ The transform function may return a value which is then used to
+ substitute the original node in the tree.
+ """
+ self.transforms[node_class].append((transform, predicate))
+
+ def unregister_transform(self, node_class, transform, predicate=None):
+ """Unregister the given transform."""
+ self.transforms[node_class].remove((transform, predicate))
+
+ def register_failed_import_hook(self, hook):
+ """Registers a hook to resolve imports that cannot be found otherwise.
+
+ `hook` must be a function that accepts a single argument `modname` which
+ contains the name of the module or package that could not be imported.
+ If `hook` can resolve the import, must return a node of type `astroid.Module`,
+ otherwise, it must raise `AstroidBuildingException`.
+ """
+ self._failed_import_hooks.append(hook)
+
+ def transform(self, node):
+ """Call matching transforms for the given node if any and return the
+ transformed node.
+ """
+ cls = node.__class__
+ if cls not in self.transforms:
+ # no transform registered for this class of node
+ return node
+
+ transforms = self.transforms[cls]
+ orig_node = node # copy the reference
+ for transform_func, predicate in transforms:
+ if predicate is None or predicate(node):
+ ret = transform_func(node)
+ # if the transformation function returns something, it's
+ # expected to be a replacement for the node
+ if ret is not None:
+ if node is not orig_node:
+ # node has already be modified by some previous
+ # transformation, warn about it
+ warn('node %s substituted multiple times' % node)
+ node = ret
+ return node
+
+ def cache_module(self, module):
+ """Cache a module if no module with the same name is known yet."""
+ self.astroid_cache.setdefault(module.name, module)
+
+ def clear_cache(self, astroid_builtin=None):
+ # XXX clear transforms
+ self.astroid_cache.clear()
+ # force bootstrap again, else we may ends up with cache inconsistency
+ # between the manager and CONST_PROXY, making
+ # unittest_lookup.LookupTC.test_builtin_lookup fail depending on the
+ # test order
+ import astroid.raw_building
+ astroid.raw_building._astroid_bootstrapping(
+ astroid_builtin=astroid_builtin)
+
+
+class Project(object):
+ """a project handle a set of modules / packages"""
+ def __init__(self, name=''):
+ self.name = name
+ self.path = None
+ self.modules = []
+ self.locals = {}
+ self.__getitem__ = self.locals.__getitem__
+ self.__iter__ = self.locals.__iter__
+ self.values = self.locals.values
+ self.keys = self.locals.keys
+ self.items = self.locals.items
+
+ def add_module(self, node):
+ self.locals[node.name] = node
+ self.modules.append(node)
+
+ def get_module(self, name):
+ return self.locals[name]
+
+ def get_children(self):
+ return self.modules
+
+ def __repr__(self):
+ return '' % (self.name, id(self),
+ len(self.modules))
+
+
diff -Nru astroid-1.0.1/astroid/mixins.py astroid-1.3.8/astroid/mixins.py
--- astroid-1.0.1/astroid/mixins.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/mixins.py 2015-08-02 19:35:55.000000000 +0000
@@ -0,0 +1,124 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""This module contains some mixins for the different nodes.
+"""
+
+from logilab.common.decorators import cachedproperty
+
+from astroid.exceptions import (AstroidBuildingException, InferenceError,
+ NotFoundError)
+
+
+class BlockRangeMixIn(object):
+ """override block range """
+
+ @cachedproperty
+ def blockstart_tolineno(self):
+ return self.lineno
+
+ def _elsed_block_range(self, lineno, orelse, last=None):
+ """handle block line numbers range for try/finally, for, if and while
+ statements
+ """
+ if lineno == self.fromlineno:
+ return lineno, lineno
+ if orelse:
+ if lineno >= orelse[0].fromlineno:
+ return lineno, orelse[-1].tolineno
+ return lineno, orelse[0].fromlineno - 1
+ return lineno, last or self.tolineno
+
+
+class FilterStmtsMixin(object):
+ """Mixin for statement filtering and assignment type"""
+
+ def _get_filtered_stmts(self, _, node, _stmts, mystmt):
+ """method used in _filter_stmts to get statemtents and trigger break"""
+ if self.statement() is mystmt:
+ # original node's statement is the assignment, only keep
+ # current node (gen exp, list comp)
+ return [node], True
+ return _stmts, False
+
+ def ass_type(self):
+ return self
+
+
+class AssignTypeMixin(object):
+
+ def ass_type(self):
+ return self
+
+ def _get_filtered_stmts(self, lookup_node, node, _stmts, mystmt):
+ """method used in filter_stmts"""
+ if self is mystmt:
+ return _stmts, True
+ if self.statement() is mystmt:
+ # original node's statement is the assignment, only keep
+ # current node (gen exp, list comp)
+ return [node], True
+ return _stmts, False
+
+
+class ParentAssignTypeMixin(AssignTypeMixin):
+
+ def ass_type(self):
+ return self.parent.ass_type()
+
+
+class FromImportMixIn(FilterStmtsMixin):
+ """MixIn for From and Import Nodes"""
+
+ def _infer_name(self, frame, name):
+ return name
+
+ def do_import_module(self, modname=None):
+ """return the ast for a module whose name is imported by
+ """
+ # handle special case where we are on a package node importing a module
+ # using the same name as the package, which may end in an infinite loop
+ # on relative imports
+ # XXX: no more needed ?
+ mymodule = self.root()
+ level = getattr(self, 'level', None) # Import as no level
+ if modname is None:
+ modname = self.modname
+ # XXX we should investigate deeper if we really want to check
+ # importing itself: modname and mymodule.name be relative or absolute
+ if mymodule.relative_to_absolute_name(modname, level) == mymodule.name:
+ # FIXME: we used to raise InferenceError here, but why ?
+ return mymodule
+ try:
+ return mymodule.import_module(modname, level=level)
+ except AstroidBuildingException:
+ raise InferenceError(modname)
+ except SyntaxError as ex:
+ raise InferenceError(str(ex))
+
+ def real_name(self, asname):
+ """get name from 'as' name"""
+ for name, _asname in self.names:
+ if name == '*':
+ return asname
+ if not _asname:
+ name = name.split('.', 1)[0]
+ _asname = name
+ if asname == _asname:
+ return name
+ raise NotFoundError(asname)
+
diff -Nru astroid-1.0.1/astroid/modutils.py astroid-1.3.8/astroid/modutils.py
--- astroid-1.0.1/astroid/modutils.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/modutils.py 2015-08-02 19:35:46.000000000 +0000
@@ -0,0 +1,670 @@
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option) any
+# later version.
+#
+# astroid is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""Python modules manipulation utility functions.
+
+:type PY_SOURCE_EXTS: tuple(str)
+:var PY_SOURCE_EXTS: list of possible python source file extension
+
+:type STD_LIB_DIRS: set of str
+:var STD_LIB_DIRS: directories where standard modules are located
+
+:type BUILTIN_MODULES: dict
+:var BUILTIN_MODULES: dictionary with builtin module names has key
+"""
+from __future__ import with_statement
+
+__docformat__ = "restructuredtext en"
+
+import imp
+import os
+import sys
+from distutils.sysconfig import get_python_lib
+from distutils.errors import DistutilsPlatformError
+import zipimport
+
+try:
+ import pkg_resources
+except ImportError:
+ pkg_resources = None
+
+from logilab.common import _handle_blacklist
+
+PY_ZIPMODULE = object()
+
+if sys.platform.startswith('win'):
+ PY_SOURCE_EXTS = ('py', 'pyw')
+ PY_COMPILED_EXTS = ('dll', 'pyd')
+else:
+ PY_SOURCE_EXTS = ('py',)
+ PY_COMPILED_EXTS = ('so',)
+
+# Notes about STD_LIB_DIRS
+# Consider arch-specific installation for STD_LIB_DIRS definition
+# :mod:`distutils.sysconfig` contains to much hardcoded values to rely on
+#
+# :see: `Problems with /usr/lib64 builds `_
+# :see: `FHS `_
+try:
+ # The explicit sys.prefix is to work around a patch in virtualenv that
+ # replaces the 'real' sys.prefix (i.e. the location of the binary)
+ # with the prefix from which the virtualenv was created. This throws
+ # off the detection logic for standard library modules, thus the
+ # workaround.
+ STD_LIB_DIRS = set([
+ get_python_lib(standard_lib=True, prefix=sys.prefix),
+ # Take care of installations where exec_prefix != prefix.
+ get_python_lib(standard_lib=True, prefix=sys.exec_prefix),
+ get_python_lib(standard_lib=True)])
+ if os.name == 'nt':
+ STD_LIB_DIRS.add(os.path.join(sys.prefix, 'dlls'))
+ try:
+ # real_prefix is defined when running inside virtualenv.
+ STD_LIB_DIRS.add(os.path.join(sys.real_prefix, 'dlls'))
+ except AttributeError:
+ pass
+# get_python_lib(standard_lib=1) is not available on pypy, set STD_LIB_DIR to
+# non-valid path, see https://bugs.pypy.org/issue1164
+except DistutilsPlatformError:
+ STD_LIB_DIRS = set()
+
+EXT_LIB_DIR = get_python_lib()
+
+BUILTIN_MODULES = dict(zip(sys.builtin_module_names,
+ [1]*len(sys.builtin_module_names)))
+
+
+class NoSourceFile(Exception):
+ """exception raised when we are not able to get a python
+ source file for a precompiled file
+ """
+
+def _normalize_path(path):
+ return os.path.normcase(os.path.abspath(path))
+
+
+_NORM_PATH_CACHE = {}
+
+def _cache_normalize_path(path):
+ """abspath with caching"""
+ # _module_file calls abspath on every path in sys.path every time it's
+ # called; on a larger codebase this easily adds up to half a second just
+ # assembling path components. This cache alleviates that.
+ try:
+ return _NORM_PATH_CACHE[path]
+ except KeyError:
+ if not path: # don't cache result for ''
+ return _normalize_path(path)
+ result = _NORM_PATH_CACHE[path] = _normalize_path(path)
+ return result
+
+def load_module_from_name(dotted_name, path=None, use_sys=1):
+ """Load a Python module from its name.
+
+ :type dotted_name: str
+ :param dotted_name: python name of a module or package
+
+ :type path: list or None
+ :param path:
+ optional list of path where the module or package should be
+ searched (use sys.path if nothing or None is given)
+
+ :type use_sys: bool
+ :param use_sys:
+ boolean indicating whether the sys.modules dictionary should be
+ used or not
+
+
+ :raise ImportError: if the module or package is not found
+
+ :rtype: module
+ :return: the loaded module
+ """
+ return load_module_from_modpath(dotted_name.split('.'), path, use_sys)
+
+
+def load_module_from_modpath(parts, path=None, use_sys=1):
+ """Load a python module from its splitted name.
+
+ :type parts: list(str) or tuple(str)
+ :param parts:
+ python name of a module or package splitted on '.'
+
+ :type path: list or None
+ :param path:
+ optional list of path where the module or package should be
+ searched (use sys.path if nothing or None is given)
+
+ :type use_sys: bool
+ :param use_sys:
+ boolean indicating whether the sys.modules dictionary should be used or not
+
+ :raise ImportError: if the module or package is not found
+
+ :rtype: module
+ :return: the loaded module
+ """
+ if use_sys:
+ try:
+ return sys.modules['.'.join(parts)]
+ except KeyError:
+ pass
+ modpath = []
+ prevmodule = None
+ for part in parts:
+ modpath.append(part)
+ curname = '.'.join(modpath)
+ module = None
+ if len(modpath) != len(parts):
+ # even with use_sys=False, should try to get outer packages from sys.modules
+ module = sys.modules.get(curname)
+ elif use_sys:
+ # because it may have been indirectly loaded through a parent
+ module = sys.modules.get(curname)
+ if module is None:
+ mp_file, mp_filename, mp_desc = imp.find_module(part, path)
+ module = imp.load_module(curname, mp_file, mp_filename, mp_desc)
+ # mp_file still needs to be closed.
+ if mp_file:
+ mp_file.close()
+ if prevmodule:
+ setattr(prevmodule, part, module)
+ _file = getattr(module, '__file__', '')
+ if not _file and len(modpath) != len(parts):
+ raise ImportError('no module in %s' % '.'.join(parts[len(modpath):]))
+ path = [os.path.dirname(_file)]
+ prevmodule = module
+ return module
+
+
+def load_module_from_file(filepath, path=None, use_sys=1, extrapath=None):
+ """Load a Python module from it's path.
+
+ :type filepath: str
+ :param filepath: path to the python module or package
+
+ :type path: list or None
+ :param path:
+ optional list of path where the module or package should be
+ searched (use sys.path if nothing or None is given)
+
+ :type use_sys: bool
+ :param use_sys:
+ boolean indicating whether the sys.modules dictionary should be
+ used or not
+
+
+ :raise ImportError: if the module or package is not found
+
+ :rtype: module
+ :return: the loaded module
+ """
+ modpath = modpath_from_file(filepath, extrapath)
+ return load_module_from_modpath(modpath, path, use_sys)
+
+
+def _check_init(path, mod_path):
+ """check there are some __init__.py all along the way"""
+ for part in mod_path:
+ path = os.path.join(path, part)
+ if not _has_init(path):
+ return False
+ return True
+
+
+def modpath_from_file(filename, extrapath=None):
+ """given a file path return the corresponding splitted module's name
+ (i.e name of a module or package splitted on '.')
+
+ :type filename: str
+ :param filename: file's path for which we want the module's name
+
+ :type extrapath: dict
+ :param extrapath:
+ optional extra search path, with path as key and package name for the path
+ as value. This is usually useful to handle package splitted in multiple
+ directories using __path__ trick.
+
+
+ :raise ImportError:
+ if the corresponding module's name has not been found
+
+ :rtype: list(str)
+ :return: the corresponding splitted module's name
+ """
+ base = os.path.splitext(os.path.abspath(filename))[0]
+ if extrapath is not None:
+ for path_ in extrapath:
+ path = os.path.abspath(path_)
+ if path and os.path.normcase(base[:len(path)]) == os.path.normcase(path):
+ submodpath = [pkg for pkg in base[len(path):].split(os.sep)
+ if pkg]
+ if _check_init(path, submodpath[:-1]):
+ return extrapath[path_].split('.') + submodpath
+ for path in sys.path:
+ path = _cache_normalize_path(path)
+ if path and os.path.normcase(base).startswith(path):
+ modpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg]
+ if _check_init(path, modpath[:-1]):
+ return modpath
+ raise ImportError('Unable to find module for %s in %s' % (
+ filename, ', \n'.join(sys.path)))
+
+
+def file_from_modpath(modpath, path=None, context_file=None):
+ return file_info_from_modpath(modpath, path, context_file)[0]
+
+def file_info_from_modpath(modpath, path=None, context_file=None):
+ """given a mod path (i.e. splitted module / package name), return the
+ corresponding file, giving priority to source file over precompiled
+ file if it exists
+
+ :type modpath: list or tuple
+ :param modpath:
+ splitted module's name (i.e name of a module or package splitted
+ on '.')
+ (this means explicit relative imports that start with dots have
+ empty strings in this list!)
+
+ :type path: list or None
+ :param path:
+ optional list of path where the module or package should be
+ searched (use sys.path if nothing or None is given)
+
+ :type context_file: str or None
+ :param context_file:
+ context file to consider, necessary if the identifier has been
+ introduced using a relative import unresolvable in the actual
+ context (i.e. modutils)
+
+ :raise ImportError: if there is no such module in the directory
+
+ :rtype: (str or None, import type)
+ :return:
+ the path to the module's file or None if it's an integrated
+ builtin module such as 'sys'
+ """
+ if context_file is not None:
+ context = os.path.dirname(context_file)
+ else:
+ context = context_file
+ if modpath[0] == 'xml':
+ # handle _xmlplus
+ try:
+ return _file_from_modpath(['_xmlplus'] + modpath[1:], path, context)
+ except ImportError:
+ return _file_from_modpath(modpath, path, context)
+ elif modpath == ['os', 'path']:
+ # FIXME: currently ignoring search_path...
+ return os.path.__file__, imp.PY_SOURCE
+ return _file_from_modpath(modpath, path, context)
+
+
+def get_module_part(dotted_name, context_file=None):
+ """given a dotted name return the module part of the name :
+
+ >>> get_module_part('logilab.common.modutils.get_module_part')
+ 'logilab.common.modutils'
+
+ :type dotted_name: str
+ :param dotted_name: full name of the identifier we are interested in
+
+ :type context_file: str or None
+ :param context_file:
+ context file to consider, necessary if the identifier has been
+ introduced using a relative import unresolvable in the actual
+ context (i.e. modutils)
+
+
+ :raise ImportError: if there is no such module in the directory
+
+ :rtype: str or None
+ :return:
+ the module part of the name or None if we have not been able at
+ all to import the given name
+
+ XXX: deprecated, since it doesn't handle package precedence over module
+ (see #10066)
+ """
+ # os.path trick
+ if dotted_name.startswith('os.path'):
+ return 'os.path'
+ parts = dotted_name.split('.')
+ if context_file is not None:
+ # first check for builtin module which won't be considered latter
+ # in that case (path != None)
+ if parts[0] in BUILTIN_MODULES:
+ if len(parts) > 2:
+ raise ImportError(dotted_name)
+ return parts[0]
+ # don't use += or insert, we want a new list to be created !
+ path = None
+ starti = 0
+ if parts[0] == '':
+ assert context_file is not None, \
+ 'explicit relative import, but no context_file?'
+ path = [] # prevent resolving the import non-relatively
+ starti = 1
+ while parts[starti] == '': # for all further dots: change context
+ starti += 1
+ context_file = os.path.dirname(context_file)
+ for i in range(starti, len(parts)):
+ try:
+ file_from_modpath(parts[starti:i+1], path=path,
+ context_file=context_file)
+ except ImportError:
+ if not i >= max(1, len(parts) - 2):
+ raise
+ return '.'.join(parts[:i])
+ return dotted_name
+
+
+def get_module_files(src_directory, blacklist):
+ """given a package directory return a list of all available python
+ module's files in the package and its subpackages
+
+ :type src_directory: str
+ :param src_directory:
+ path of the directory corresponding to the package
+
+ :type blacklist: list or tuple
+ :param blacklist:
+ optional list of files or directory to ignore, default to the value of
+ `logilab.common.STD_BLACKLIST`
+
+ :rtype: list
+ :return:
+ the list of all available python module's files in the package and
+ its subpackages
+ """
+ files = []
+ for directory, dirnames, filenames in os.walk(src_directory):
+ _handle_blacklist(blacklist, dirnames, filenames)
+ # check for __init__.py
+ if not '__init__.py' in filenames:
+ dirnames[:] = ()
+ continue
+ for filename in filenames:
+ if _is_python_file(filename):
+ src = os.path.join(directory, filename)
+ files.append(src)
+ return files
+
+
+def get_source_file(filename, include_no_ext=False):
+ """given a python module's file name return the matching source file
+ name (the filename will be returned identically if it's a already an
+ absolute path to a python source file...)
+
+ :type filename: str
+ :param filename: python module's file name
+
+
+ :raise NoSourceFile: if no source file exists on the file system
+
+ :rtype: str
+ :return: the absolute path of the source file if it exists
+ """
+ base, orig_ext = os.path.splitext(os.path.abspath(filename))
+ for ext in PY_SOURCE_EXTS:
+ source_path = '%s.%s' % (base, ext)
+ if os.path.exists(source_path):
+ return source_path
+ if include_no_ext and not orig_ext and os.path.exists(base):
+ return base
+ raise NoSourceFile(filename)
+
+
+def is_python_source(filename):
+ """
+ rtype: bool
+ return: True if the filename is a python source file
+ """
+ return os.path.splitext(filename)[1][1:] in PY_SOURCE_EXTS
+
+
+def is_standard_module(modname, std_path=None):
+ """try to guess if a module is a standard python module (by default,
+ see `std_path` parameter's description)
+
+ :type modname: str
+ :param modname: name of the module we are interested in
+
+ :type std_path: list(str) or tuple(str)
+ :param std_path: list of path considered has standard
+
+
+ :rtype: bool
+ :return:
+ true if the module:
+ - is located on the path listed in one of the directory in `std_path`
+ - is a built-in module
+ """
+ modname = modname.split('.')[0]
+ try:
+ filename = file_from_modpath([modname])
+ except ImportError:
+ # import failed, i'm probably not so wrong by supposing it's
+ # not standard...
+ return False
+ # modules which are not living in a file are considered standard
+ # (sys and __builtin__ for instance)
+ if filename is None:
+ return True
+ filename = _normalize_path(filename)
+ if filename.startswith(_cache_normalize_path(EXT_LIB_DIR)):
+ return False
+ if std_path is None:
+ std_path = STD_LIB_DIRS
+ for path in std_path:
+ if filename.startswith(_cache_normalize_path(path)):
+ return True
+ return False
+
+
+
+def is_relative(modname, from_file):
+ """return true if the given module name is relative to the given
+ file name
+
+ :type modname: str
+ :param modname: name of the module we are interested in
+
+ :type from_file: str
+ :param from_file:
+ path of the module from which modname has been imported
+
+ :rtype: bool
+ :return:
+ true if the module has been imported relatively to `from_file`
+ """
+ if not os.path.isdir(from_file):
+ from_file = os.path.dirname(from_file)
+ if from_file in sys.path:
+ return False
+ try:
+ stream, _, _ = imp.find_module(modname.split('.')[0], [from_file])
+
+ # Close the stream to avoid ResourceWarnings.
+ if stream:
+ stream.close()
+ return True
+ except ImportError:
+ return False
+
+
+# internal only functions #####################################################
+
+def _file_from_modpath(modpath, path=None, context=None):
+ """given a mod path (i.e. splitted module / package name), return the
+ corresponding file
+
+ this function is used internally, see `file_from_modpath`'s
+ documentation for more information
+ """
+ assert len(modpath) > 0
+ if context is not None:
+ try:
+ mtype, mp_filename = _module_file(modpath, [context])
+ except ImportError:
+ mtype, mp_filename = _module_file(modpath, path)
+ else:
+ mtype, mp_filename = _module_file(modpath, path)
+ if mtype == imp.PY_COMPILED:
+ try:
+ return get_source_file(mp_filename), imp.PY_SOURCE
+ except NoSourceFile:
+ return mp_filename, imp.PY_COMPILED
+ elif mtype == imp.C_BUILTIN:
+ # integrated builtin module
+ return None, imp.C_BUILTIN
+ elif mtype == imp.PKG_DIRECTORY:
+ mp_filename = _has_init(mp_filename)
+ mtype = imp.PY_SOURCE
+ return mp_filename, mtype
+
+def _search_zip(modpath, pic):
+ for filepath, importer in pic.items():
+ if importer is not None:
+ if importer.find_module(modpath[0]):
+ if not importer.find_module(os.path.sep.join(modpath)):
+ raise ImportError('No module named %s in %s/%s' % (
+ '.'.join(modpath[1:]), filepath, modpath))
+ return PY_ZIPMODULE, os.path.abspath(filepath) + os.path.sep + os.path.sep.join(modpath), filepath
+ raise ImportError('No module named %s' % '.'.join(modpath))
+
+
+def _module_file(modpath, path=None):
+ """get a module type / file path
+
+ :type modpath: list or tuple
+ :param modpath:
+ splitted module's name (i.e name of a module or package splitted
+ on '.'), with leading empty strings for explicit relative import
+
+ :type path: list or None
+ :param path:
+ optional list of path where the module or package should be
+ searched (use sys.path if nothing or None is given)
+
+
+ :rtype: tuple(int, str)
+ :return: the module type flag and the file path for a module
+ """
+ # egg support compat
+ try:
+ pic = sys.path_importer_cache
+ _path = (path is None and sys.path or path)
+ for __path in _path:
+ if not __path in pic:
+ try:
+ pic[__path] = zipimport.zipimporter(__path)
+ except zipimport.ZipImportError:
+ pic[__path] = None
+ checkeggs = True
+ except AttributeError:
+ checkeggs = False
+ # pkg_resources support (aka setuptools namespace packages)
+ if (pkg_resources is not None
+ and modpath[0] in pkg_resources._namespace_packages
+ and modpath[0] in sys.modules
+ and len(modpath) > 1):
+ # setuptools has added into sys.modules a module object with proper
+ # __path__, get back information from there
+ module = sys.modules[modpath.pop(0)]
+ path = module.__path__
+ imported = []
+ while modpath:
+ modname = modpath[0]
+ # take care to changes in find_module implementation wrt builtin modules
+ #
+ # Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23)
+ # >>> imp.find_module('posix')
+ # (None, 'posix', ('', '', 6))
+ #
+ # Python 3.3.1 (default, Apr 26 2013, 12:08:46)
+ # >>> imp.find_module('posix')
+ # (None, None, ('', '', 6))
+ try:
+ stream, mp_filename, mp_desc = imp.find_module(modname, path)
+ except ImportError:
+ if checkeggs:
+ return _search_zip(modpath, pic)[:2]
+ raise
+ else:
+ # Don't forget to close the stream to avoid
+ # spurious ResourceWarnings.
+ if stream:
+ stream.close()
+
+ if checkeggs and mp_filename:
+ fullabspath = [_cache_normalize_path(x) for x in _path]
+ try:
+ pathindex = fullabspath.index(os.path.dirname(_normalize_path(mp_filename)))
+ emtype, emp_filename, zippath = _search_zip(modpath, pic)
+ if pathindex > _path.index(zippath):
+ # an egg takes priority
+ return emtype, emp_filename
+ except ValueError:
+ # XXX not in _path
+ pass
+ except ImportError:
+ pass
+ checkeggs = False
+ imported.append(modpath.pop(0))
+ mtype = mp_desc[2]
+ if modpath:
+ if mtype != imp.PKG_DIRECTORY:
+ raise ImportError('No module %s in %s' % ('.'.join(modpath),
+ '.'.join(imported)))
+ # XXX guess if package is using pkgutil.extend_path by looking for
+ # those keywords in the first four Kbytes
+ try:
+ with open(os.path.join(mp_filename, '__init__.py'), 'rb') as stream:
+ data = stream.read(4096)
+ except IOError:
+ path = [mp_filename]
+ else:
+ if b'pkgutil' in data and b'extend_path' in data:
+ # extend_path is called, search sys.path for module/packages
+ # of this name see pkgutil.extend_path documentation
+ path = [os.path.join(p, *imported) for p in sys.path
+ if os.path.isdir(os.path.join(p, *imported))]
+ else:
+ path = [mp_filename]
+ return mtype, mp_filename
+
+def _is_python_file(filename):
+ """return true if the given filename should be considered as a python file
+
+ .pyc and .pyo are ignored
+ """
+ for ext in ('.py', '.so', '.pyd', '.pyw'):
+ if filename.endswith(ext):
+ return True
+ return False
+
+
+def _has_init(directory):
+ """if the given directory has a valid __init__ file, return its path,
+ else return None
+ """
+ mod_or_pack = os.path.join(directory, '__init__')
+ for ext in PY_SOURCE_EXTS + ('pyc', 'pyo'):
+ if os.path.exists(mod_or_pack + '.' + ext):
+ return mod_or_pack + '.' + ext
+ return None
diff -Nru astroid-1.0.1/astroid/node_classes.py astroid-1.3.8/astroid/node_classes.py
--- astroid-1.0.1/astroid/node_classes.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/node_classes.py 2015-08-02 19:35:55.000000000 +0000
@@ -0,0 +1,966 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""Module for some node classes. More nodes in scoped_nodes.py
+"""
+
+import sys
+
+import six
+from logilab.common.decorators import cachedproperty
+
+from astroid.exceptions import NoDefault
+from astroid.bases import (NodeNG, Statement, Instance, InferenceContext,
+ _infer_stmts, YES, BUILTINS)
+from astroid.mixins import (BlockRangeMixIn, AssignTypeMixin,
+ ParentAssignTypeMixin, FromImportMixIn)
+
+PY3K = sys.version_info >= (3, 0)
+
+
+def unpack_infer(stmt, context=None):
+ """recursively generate nodes inferred by the given statement.
+ If the inferred value is a list or a tuple, recurse on the elements
+ """
+ if isinstance(stmt, (List, Tuple)):
+ for elt in stmt.elts:
+ for infered_elt in unpack_infer(elt, context):
+ yield infered_elt
+ return
+ # if infered is a final node, return it and stop
+ infered = next(stmt.infer(context))
+ if infered is stmt:
+ yield infered
+ return
+ # else, infer recursivly, except YES object that should be returned as is
+ for infered in stmt.infer(context):
+ if infered is YES:
+ yield infered
+ else:
+ for inf_inf in unpack_infer(infered, context):
+ yield inf_inf
+
+
+def are_exclusive(stmt1, stmt2, exceptions=None):
+ """return true if the two given statements are mutually exclusive
+
+ `exceptions` may be a list of exception names. If specified, discard If
+ branches and check one of the statement is in an exception handler catching
+ one of the given exceptions.
+
+ algorithm :
+ 1) index stmt1's parents
+ 2) climb among stmt2's parents until we find a common parent
+ 3) if the common parent is a If or TryExcept statement, look if nodes are
+ in exclusive branches
+ """
+ # index stmt1's parents
+ stmt1_parents = {}
+ children = {}
+ node = stmt1.parent
+ previous = stmt1
+ while node:
+ stmt1_parents[node] = 1
+ children[node] = previous
+ previous = node
+ node = node.parent
+ # climb among stmt2's parents until we find a common parent
+ node = stmt2.parent
+ previous = stmt2
+ while node:
+ if node in stmt1_parents:
+ # if the common parent is a If or TryExcept statement, look if
+ # nodes are in exclusive branches
+ if isinstance(node, If) and exceptions is None:
+ if (node.locate_child(previous)[1]
+ is not node.locate_child(children[node])[1]):
+ return True
+ elif isinstance(node, TryExcept):
+ c2attr, c2node = node.locate_child(previous)
+ c1attr, c1node = node.locate_child(children[node])
+ if c1node is not c2node:
+ if ((c2attr == 'body' and c1attr == 'handlers' and children[node].catch(exceptions)) or
+ (c2attr == 'handlers' and c1attr == 'body' and previous.catch(exceptions)) or
+ (c2attr == 'handlers' and c1attr == 'orelse') or
+ (c2attr == 'orelse' and c1attr == 'handlers')):
+ return True
+ elif c2attr == 'handlers' and c1attr == 'handlers':
+ return previous is not children[node]
+ return False
+ previous = node
+ node = node.parent
+ return False
+
+
+class LookupMixIn(object):
+ """Mixin looking up a name in the right scope
+ """
+
+ def lookup(self, name):
+ """lookup a variable name
+
+ return the scope node and the list of assignments associated to the
+ given name according to the scope where it has been found (locals,
+ globals or builtin)
+
+ The lookup is starting from self's scope. 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
+ """
+ return self.scope().scope_lookup(self, name)
+
+ def ilookup(self, name):
+ """infered lookup
+
+ return an iterator on infered values of the statements returned by
+ the lookup method
+ """
+ frame, stmts = self.lookup(name)
+ context = InferenceContext()
+ return _infer_stmts(stmts, context, frame)
+
+ 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 the frame of this node is the same as the statement
+ # of this node, then the node is part of a class or
+ # a function definition and the frame of this node should be the
+ # the upper frame, not the frame of the definition.
+ # For more information why this is important,
+ # see Pylint issue #295.
+ # For example, for 'b', the statement is the same
+ # as the frame / scope:
+ #
+ # def test(b=1):
+ # ...
+
+ if self.statement() is myframe and myframe.parent:
+ myframe = myframe.parent.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
+ assert hasattr(node, 'ass_type'), (node, node.scope(),
+ node.scope().locals)
+ ass_type = node.ass_type()
+
+ if node.has_base(self):
+ break
+
+ _stmts, done = ass_type._get_filtered_stmts(self, node, _stmts, mystmt)
+ if done:
+ break
+
+ optional_assign = ass_type.optional_assign
+ 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, AssName):
+ if not optional_assign and stmt.parent is mystmt.parent:
+ _stmts = []
+ _stmt_parents = []
+ elif isinstance(node, DelName):
+ _stmts = []
+ _stmt_parents = []
+ continue
+ if not are_exclusive(self, node):
+ _stmts.append(node)
+ _stmt_parents.append(stmt.parent)
+ return _stmts
+
+# Name classes
+
+class AssName(LookupMixIn, ParentAssignTypeMixin, NodeNG):
+ """class representing an AssName node"""
+
+
+class DelName(LookupMixIn, ParentAssignTypeMixin, NodeNG):
+ """class representing a DelName node"""
+
+
+class Name(LookupMixIn, NodeNG):
+ """class representing a Name node"""
+
+
+
+
+##################### node classes ########################################
+
+class Arguments(NodeNG, AssignTypeMixin):
+ """class representing an Arguments node"""
+ if PY3K:
+ # Python 3.4+ uses a different approach regarding annotations,
+ # each argument is a new class, _ast.arg, which exposes an
+ # 'annotation' attribute. In astroid though, arguments are exposed
+ # as is in the Arguments node and the only way to expose annotations
+ # is by using something similar with Python 3.3:
+ # - we expose 'varargannotation' and 'kwargannotation' of annotations
+ # of varargs and kwargs.
+ # - we expose 'annotation', a list with annotations for
+ # for each normal argument. If an argument doesn't have an
+ # annotation, its value will be None.
+
+ _astroid_fields = ('args', 'defaults', 'kwonlyargs',
+ 'kw_defaults', 'annotations',
+ 'varargannotation', 'kwargannotation')
+ annotations = None
+ varargannotation = None
+ kwargannotation = None
+ else:
+ _astroid_fields = ('args', 'defaults', 'kwonlyargs', 'kw_defaults')
+ args = None
+ defaults = None
+ kwonlyargs = None
+ kw_defaults = None
+
+ def __init__(self, vararg=None, kwarg=None):
+ self.vararg = vararg
+ self.kwarg = kwarg
+
+ def _infer_name(self, frame, name):
+ if self.parent is frame:
+ return name
+ return None
+
+ @cachedproperty
+ def fromlineno(self):
+ lineno = super(Arguments, self).fromlineno
+ return max(lineno, self.parent.fromlineno or 0)
+
+ def format_args(self):
+ """return arguments formatted as string"""
+ result = []
+ if self.args:
+ result.append(_format_args(self.args, self.defaults))
+ if self.vararg:
+ result.append('*%s' % self.vararg)
+ if self.kwarg:
+ result.append('**%s' % self.kwarg)
+ if self.kwonlyargs:
+ if not self.vararg:
+ result.append('*')
+ result.append(_format_args(self.kwonlyargs, self.kw_defaults))
+ return ', '.join(result)
+
+ def default_value(self, argname):
+ """return the default value for an argument
+
+ :raise `NoDefault`: if there is no default value defined
+ """
+ i = _find_arg(argname, self.args)[0]
+ if i is not None:
+ idx = i - (len(self.args) - len(self.defaults))
+ if idx >= 0:
+ return self.defaults[idx]
+ i = _find_arg(argname, self.kwonlyargs)[0]
+ if i is not None and self.kw_defaults[i] is not None:
+ return self.kw_defaults[i]
+ raise NoDefault()
+
+ def is_argument(self, name):
+ """return True if the name is defined in arguments"""
+ if name == self.vararg:
+ return True
+ if name == self.kwarg:
+ return True
+ return self.find_argname(name, True)[1] is not None
+
+ def find_argname(self, argname, rec=False):
+ """return index and Name node with given name"""
+ if self.args: # self.args may be None in some cases (builtin function)
+ return _find_arg(argname, self.args, rec)
+ return None, None
+
+ def get_children(self):
+ """override get_children to skip over None elements in kw_defaults"""
+ for child in super(Arguments, self).get_children():
+ if child is not None:
+ yield child
+
+
+def _find_arg(argname, args, rec=False):
+ for i, arg in enumerate(args):
+ if isinstance(arg, Tuple):
+ if rec:
+ found = _find_arg(argname, arg.elts)
+ if found[0] is not None:
+ return found
+ elif arg.name == argname:
+ return i, arg
+ return None, None
+
+
+def _format_args(args, defaults=None):
+ values = []
+ if args is None:
+ return ''
+ if defaults is not None:
+ default_offset = len(args) - len(defaults)
+ for i, arg in enumerate(args):
+ if isinstance(arg, Tuple):
+ values.append('(%s)' % _format_args(arg.elts))
+ else:
+ values.append(arg.name)
+ if defaults is not None and i >= default_offset:
+ if defaults[i-default_offset] is not None:
+ values[-1] += '=' + defaults[i-default_offset].as_string()
+ return ', '.join(values)
+
+
+class AssAttr(NodeNG, ParentAssignTypeMixin):
+ """class representing an AssAttr node"""
+ _astroid_fields = ('expr',)
+ expr = None
+
+class Assert(Statement):
+ """class representing an Assert node"""
+ _astroid_fields = ('test', 'fail',)
+ test = None
+ fail = None
+
+class Assign(Statement, AssignTypeMixin):
+ """class representing an Assign node"""
+ _astroid_fields = ('targets', 'value',)
+ targets = None
+ value = None
+
+class AugAssign(Statement, AssignTypeMixin):
+ """class representing an AugAssign node"""
+ _astroid_fields = ('target', 'value',)
+ target = None
+ value = None
+
+class Backquote(NodeNG):
+ """class representing a Backquote node"""
+ _astroid_fields = ('value',)
+ value = None
+
+class BinOp(NodeNG):
+ """class representing a BinOp node"""
+ _astroid_fields = ('left', 'right',)
+ left = None
+ right = None
+
+class BoolOp(NodeNG):
+ """class representing a BoolOp node"""
+ _astroid_fields = ('values',)
+ values = None
+
+class Break(Statement):
+ """class representing a Break node"""
+
+
+class CallFunc(NodeNG):
+ """class representing a CallFunc node"""
+ _astroid_fields = ('func', 'args', 'starargs', 'kwargs')
+ func = None
+ args = None
+ starargs = None
+ kwargs = None
+
+ def __init__(self):
+ self.starargs = None
+ self.kwargs = None
+
+class Compare(NodeNG):
+ """class representing a Compare node"""
+ _astroid_fields = ('left', 'ops',)
+ left = None
+ ops = None
+
+ def get_children(self):
+ """override get_children for tuple fields"""
+ yield self.left
+ for _, comparator in self.ops:
+ yield comparator # we don't want the 'op'
+
+ def last_child(self):
+ """override last_child"""
+ # XXX maybe if self.ops:
+ return self.ops[-1][1]
+ #return self.left
+
+class Comprehension(NodeNG):
+ """class representing a Comprehension node"""
+ _astroid_fields = ('target', 'iter', 'ifs')
+ target = None
+ iter = None
+ ifs = None
+
+ optional_assign = True
+ def ass_type(self):
+ return self
+
+ def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt):
+ """method used in filter_stmts"""
+ if self is mystmt:
+ if isinstance(lookup_node, (Const, Name)):
+ return [lookup_node], True
+
+ elif self.statement() is mystmt:
+ # original node's statement is the assignment, only keeps
+ # current node (gen exp, list comp)
+
+ return [node], True
+
+ return stmts, False
+
+
+class Const(NodeNG, Instance):
+ """represent a constant node like num, str, bool, None, bytes"""
+
+ def __init__(self, value=None):
+ self.value = value
+
+ def getitem(self, index, context=None):
+ if isinstance(self.value, six.string_types):
+ return Const(self.value[index])
+ raise TypeError('%r (value=%s)' % (self, self.value))
+
+ def has_dynamic_getattr(self):
+ return False
+
+ def itered(self):
+ if isinstance(self.value, six.string_types):
+ return self.value
+ raise TypeError()
+
+ def pytype(self):
+ return self._proxied.qname()
+
+
+class Continue(Statement):
+ """class representing a Continue node"""
+
+
+class Decorators(NodeNG):
+ """class representing a Decorators node"""
+ _astroid_fields = ('nodes',)
+ nodes = None
+
+ def __init__(self, nodes=None):
+ self.nodes = nodes
+
+ def scope(self):
+ # skip the function node to go directly to the upper level scope
+ return self.parent.parent.scope()
+
+class DelAttr(NodeNG, ParentAssignTypeMixin):
+ """class representing a DelAttr node"""
+ _astroid_fields = ('expr',)
+ expr = None
+
+
+class Delete(Statement, AssignTypeMixin):
+ """class representing a Delete node"""
+ _astroid_fields = ('targets',)
+ targets = None
+
+
+class Dict(NodeNG, Instance):
+ """class representing a Dict node"""
+ _astroid_fields = ('items',)
+
+ def __init__(self, items=None):
+ if items is None:
+ self.items = []
+ else:
+ self.items = [(const_factory(k), const_factory(v))
+ for k, v in items.items()]
+
+ def pytype(self):
+ return '%s.dict' % BUILTINS
+
+ def get_children(self):
+ """get children of a Dict node"""
+ # overrides get_children
+ for key, value in self.items:
+ yield key
+ yield value
+
+ def last_child(self):
+ """override last_child"""
+ if self.items:
+ return self.items[-1][1]
+ return None
+
+ def itered(self):
+ return self.items[::2]
+
+ def getitem(self, lookup_key, context=None):
+ for key, value in self.items:
+ for inferedkey in key.infer(context):
+ if inferedkey is YES:
+ continue
+ if isinstance(inferedkey, Const) \
+ and inferedkey.value == lookup_key:
+ return value
+ # This should raise KeyError, but all call sites only catch
+ # IndexError. Let's leave it like that for now.
+ raise IndexError(lookup_key)
+
+
+class Discard(Statement):
+ """class representing a Discard node"""
+ _astroid_fields = ('value',)
+ value = None
+
+
+class Ellipsis(NodeNG):
+ """class representing an Ellipsis node"""
+
+
+class EmptyNode(NodeNG):
+ """class representing an EmptyNode node"""
+
+
+class ExceptHandler(Statement, AssignTypeMixin):
+ """class representing an ExceptHandler node"""
+ _astroid_fields = ('type', 'name', 'body',)
+ type = None
+ name = None
+ body = None
+
+ @cachedproperty
+ def blockstart_tolineno(self):
+ if self.name:
+ return self.name.tolineno
+ elif self.type:
+ return self.type.tolineno
+ else:
+ return self.lineno
+
+ def catch(self, exceptions):
+ if self.type is None or exceptions is None:
+ return True
+ for node in self.type.nodes_of_class(Name):
+ if node.name in exceptions:
+ return True
+
+
+class Exec(Statement):
+ """class representing an Exec node"""
+ _astroid_fields = ('expr', 'globals', 'locals',)
+ expr = None
+ globals = None
+ locals = None
+
+
+class ExtSlice(NodeNG):
+ """class representing an ExtSlice node"""
+ _astroid_fields = ('dims',)
+ dims = None
+
+class For(BlockRangeMixIn, AssignTypeMixin, Statement):
+ """class representing a For node"""
+ _astroid_fields = ('target', 'iter', 'body', 'orelse',)
+ target = None
+ iter = None
+ body = None
+ orelse = None
+
+ optional_assign = True
+ @cachedproperty
+ def blockstart_tolineno(self):
+ return self.iter.tolineno
+
+
+class From(FromImportMixIn, Statement):
+ """class representing a From node"""
+
+ def __init__(self, fromname, names, level=0):
+ self.modname = fromname
+ self.names = names
+ self.level = level
+
+class Getattr(NodeNG):
+ """class representing a Getattr node"""
+ _astroid_fields = ('expr',)
+ expr = None
+
+
+class Global(Statement):
+ """class representing a Global node"""
+
+ def __init__(self, names):
+ self.names = names
+
+ def _infer_name(self, frame, name):
+ return name
+
+
+class If(BlockRangeMixIn, Statement):
+ """class representing an If node"""
+ _astroid_fields = ('test', 'body', 'orelse')
+ test = None
+ body = None
+ orelse = None
+
+ @cachedproperty
+ def blockstart_tolineno(self):
+ return self.test.tolineno
+
+ def block_range(self, lineno):
+ """handle block line numbers range for if statements"""
+ if lineno == self.body[0].fromlineno:
+ return lineno, lineno
+ if lineno <= self.body[-1].tolineno:
+ return lineno, self.body[-1].tolineno
+ return self._elsed_block_range(lineno, self.orelse,
+ self.body[0].fromlineno - 1)
+
+
+class IfExp(NodeNG):
+ """class representing an IfExp node"""
+ _astroid_fields = ('test', 'body', 'orelse')
+ test = None
+ body = None
+ orelse = None
+
+
+class Import(FromImportMixIn, Statement):
+ """class representing an Import node"""
+
+
+class Index(NodeNG):
+ """class representing an Index node"""
+ _astroid_fields = ('value',)
+ value = None
+
+
+class Keyword(NodeNG):
+ """class representing a Keyword node"""
+ _astroid_fields = ('value',)
+ value = None
+
+
+class List(NodeNG, Instance, ParentAssignTypeMixin):
+ """class representing a List node"""
+ _astroid_fields = ('elts',)
+
+ def __init__(self, elts=None):
+ if elts is None:
+ self.elts = []
+ else:
+ self.elts = [const_factory(e) for e in elts]
+
+ def pytype(self):
+ return '%s.list' % BUILTINS
+
+ def getitem(self, index, context=None):
+ return self.elts[index]
+
+ def itered(self):
+ return self.elts
+
+
+class Nonlocal(Statement):
+ """class representing a Nonlocal node"""
+
+ def __init__(self, names):
+ self.names = names
+
+ def _infer_name(self, frame, name):
+ return name
+
+
+class Pass(Statement):
+ """class representing a Pass node"""
+
+
+class Print(Statement):
+ """class representing a Print node"""
+ _astroid_fields = ('dest', 'values',)
+ dest = None
+ values = None
+
+
+class Raise(Statement):
+ """class representing a Raise node"""
+ exc = None
+ if sys.version_info < (3, 0):
+ _astroid_fields = ('exc', 'inst', 'tback')
+ inst = None
+ tback = None
+ else:
+ _astroid_fields = ('exc', 'cause')
+ exc = None
+ cause = None
+
+ def raises_not_implemented(self):
+ if not self.exc:
+ return
+ for name in self.exc.nodes_of_class(Name):
+ if name.name == 'NotImplementedError':
+ return True
+
+
+class Return(Statement):
+ """class representing a Return node"""
+ _astroid_fields = ('value',)
+ value = None
+
+
+class Set(NodeNG, Instance, ParentAssignTypeMixin):
+ """class representing a Set node"""
+ _astroid_fields = ('elts',)
+
+ def __init__(self, elts=None):
+ if elts is None:
+ self.elts = []
+ else:
+ self.elts = [const_factory(e) for e in elts]
+
+ def pytype(self):
+ return '%s.set' % BUILTINS
+
+ def itered(self):
+ return self.elts
+
+
+class Slice(NodeNG):
+ """class representing a Slice node"""
+ _astroid_fields = ('lower', 'upper', 'step')
+ lower = None
+ upper = None
+ step = None
+
+class Starred(NodeNG, ParentAssignTypeMixin):
+ """class representing a Starred node"""
+ _astroid_fields = ('value',)
+ value = None
+
+
+class Subscript(NodeNG):
+ """class representing a Subscript node"""
+ _astroid_fields = ('value', 'slice')
+ value = None
+ slice = None
+
+
+class TryExcept(BlockRangeMixIn, Statement):
+ """class representing a TryExcept node"""
+ _astroid_fields = ('body', 'handlers', 'orelse',)
+ body = None
+ handlers = None
+ orelse = None
+
+ def _infer_name(self, frame, name):
+ return name
+
+ def block_range(self, lineno):
+ """handle block line numbers range for try/except statements"""
+ last = None
+ for exhandler in self.handlers:
+ if exhandler.type and lineno == exhandler.type.fromlineno:
+ return lineno, lineno
+ if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:
+ return lineno, exhandler.body[-1].tolineno
+ if last is None:
+ last = exhandler.body[0].fromlineno - 1
+ return self._elsed_block_range(lineno, self.orelse, last)
+
+
+class TryFinally(BlockRangeMixIn, Statement):
+ """class representing a TryFinally node"""
+ _astroid_fields = ('body', 'finalbody',)
+ body = None
+ finalbody = None
+
+ def block_range(self, lineno):
+ """handle block line numbers range for try/finally statements"""
+ child = self.body[0]
+ # py2.5 try: except: finally:
+ if (isinstance(child, TryExcept) and child.fromlineno == self.fromlineno
+ and lineno > self.fromlineno and lineno <= child.tolineno):
+ return child.block_range(lineno)
+ return self._elsed_block_range(lineno, self.finalbody)
+
+
+class Tuple(NodeNG, Instance, ParentAssignTypeMixin):
+ """class representing a Tuple node"""
+ _astroid_fields = ('elts',)
+
+ def __init__(self, elts=None):
+ if elts is None:
+ self.elts = []
+ else:
+ self.elts = [const_factory(e) for e in elts]
+
+ def pytype(self):
+ return '%s.tuple' % BUILTINS
+
+ def getitem(self, index, context=None):
+ return self.elts[index]
+
+ def itered(self):
+ return self.elts
+
+
+class UnaryOp(NodeNG):
+ """class representing an UnaryOp node"""
+ _astroid_fields = ('operand',)
+ operand = None
+
+
+class While(BlockRangeMixIn, Statement):
+ """class representing a While node"""
+ _astroid_fields = ('test', 'body', 'orelse',)
+ test = None
+ body = None
+ orelse = None
+
+ @cachedproperty
+ def blockstart_tolineno(self):
+ return self.test.tolineno
+
+ def block_range(self, lineno):
+ """handle block line numbers range for for and while statements"""
+ return self. _elsed_block_range(lineno, self.orelse)
+
+
+class With(BlockRangeMixIn, AssignTypeMixin, Statement):
+ """class representing a With node"""
+ _astroid_fields = ('items', 'body')
+ items = None
+ body = None
+
+ @cachedproperty
+ def blockstart_tolineno(self):
+ return self.items[-1][0].tolineno
+
+ def get_children(self):
+ for expr, var in self.items:
+ yield expr
+ if var:
+ yield var
+ for elt in self.body:
+ yield elt
+
+class Yield(NodeNG):
+ """class representing a Yield node"""
+ _astroid_fields = ('value',)
+ value = None
+
+class YieldFrom(Yield):
+ """ Class representing a YieldFrom node. """
+
+# constants ##############################################################
+
+CONST_CLS = {
+ list: List,
+ tuple: Tuple,
+ dict: Dict,
+ set: Set,
+ type(None): Const,
+ }
+
+def _update_const_classes():
+ """update constant classes, so the keys of CONST_CLS can be reused"""
+ klasses = (bool, int, float, complex, str)
+ if sys.version_info < (3, 0):
+ klasses += (unicode, long)
+ if sys.version_info >= (2, 6):
+ klasses += (bytes,)
+ for kls in klasses:
+ CONST_CLS[kls] = Const
+_update_const_classes()
+
+def const_factory(value):
+ """return an astroid node for a python value"""
+ # XXX we should probably be stricter here and only consider stuff in
+ # CONST_CLS or do better treatment: in case where value is not in CONST_CLS,
+ # we should rather recall the builder on this value than returning an empty
+ # node (another option being that const_factory shouldn't be called with something
+ # not in CONST_CLS)
+ assert not isinstance(value, NodeNG)
+ try:
+ return CONST_CLS[value.__class__](value)
+ except (KeyError, AttributeError):
+ node = EmptyNode()
+ node.object = value
+ return node
diff -Nru astroid-1.0.1/astroid/nodes.py astroid-1.3.8/astroid/nodes.py
--- astroid-1.0.1/astroid/nodes.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/nodes.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,74 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""
+on all nodes :
+ .is_statement, returning true if the node should be considered as a
+ statement node
+ .root(), returning the root node of the tree (i.e. a Module)
+ .previous_sibling(), returning previous sibling statement node
+ .next_sibling(), returning next sibling statement node
+ .statement(), returning the first parent node marked as statement node
+ .frame(), returning the first node defining a new local scope (i.e.
+ Module, Function or Class)
+ .set_local(name, node), define an identifier on the first parent frame,
+ with the node defining it. This is used by the astroid builder and should not
+ be used from out there.
+
+on From and Import :
+ .real_name(name),
+
+
+"""
+# pylint: disable=unused-import
+
+__docformat__ = "restructuredtext en"
+
+from astroid.node_classes import Arguments, AssAttr, Assert, Assign, \
+ AssName, AugAssign, Backquote, BinOp, BoolOp, Break, CallFunc, Compare, \
+ Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete, \
+ Dict, Discard, Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, For, \
+ From, Getattr, Global, If, IfExp, Import, Index, Keyword, \
+ List, Name, Nonlocal, Pass, Print, Raise, Return, Set, Slice, Starred, Subscript, \
+ TryExcept, TryFinally, Tuple, UnaryOp, While, With, Yield, YieldFrom, \
+ const_factory
+from astroid.scoped_nodes import Module, GenExpr, Lambda, DictComp, \
+ ListComp, SetComp, Function, Class
+
+ALL_NODE_CLASSES = (
+ Arguments, AssAttr, Assert, Assign, AssName, AugAssign,
+ Backquote, BinOp, BoolOp, Break,
+ CallFunc, Class, Compare, Comprehension, Const, Continue,
+ Decorators, DelAttr, DelName, Delete,
+ Dict, DictComp, Discard,
+ Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice,
+ For, From, Function,
+ Getattr, GenExpr, Global,
+ If, IfExp, Import, Index,
+ Keyword,
+ Lambda, List, ListComp,
+ Name, Nonlocal,
+ Module,
+ Pass, Print,
+ Raise, Return,
+ Set, SetComp, Slice, Starred, Subscript,
+ TryExcept, TryFinally, Tuple,
+ UnaryOp,
+ While, With,
+ Yield, YieldFrom
+ )
+
diff -Nru astroid-1.0.1/astroid/__pkginfo__.py astroid-1.3.8/astroid/__pkginfo__.py
--- astroid-1.0.1/astroid/__pkginfo__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/__pkginfo__.py 2015-08-02 19:37:10.000000000 +0000
@@ -0,0 +1,42 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""astroid packaging information"""
+distname = 'astroid'
+
+modname = 'astroid'
+
+numversion = (1, 3, 8)
+version = '.'.join([str(num) for num in numversion])
+
+install_requires = ['logilab-common>=0.63.0', 'six']
+
+license = 'LGPL'
+
+author = 'Logilab'
+author_email = 'pylint-dev@lists.logilab.org'
+mailinglist = "mailto://%s" % author_email
+web = 'http://bitbucket.org/logilab/astroid'
+
+description = "A abstract syntax tree for Python with inference support."
+
+classifiers = ["Topic :: Software Development :: Libraries :: Python Modules",
+ "Topic :: Software Development :: Quality Assurance",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 3",
+ ]
diff -Nru astroid-1.0.1/astroid/protocols.py astroid-1.3.8/astroid/protocols.py
--- astroid-1.0.1/astroid/protocols.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/protocols.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,415 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""this module contains a set of functions to handle python protocols for nodes
+where it makes sense.
+"""
+
+__doctype__ = "restructuredtext en"
+import collections
+
+from astroid.exceptions import InferenceError, NoDefault, NotFoundError
+from astroid.node_classes import unpack_infer
+from astroid.bases import InferenceContext, copy_context, \
+ raise_if_nothing_infered, yes_if_nothing_infered, Instance, YES
+from astroid.nodes import const_factory
+from astroid import nodes
+
+BIN_OP_METHOD = {'+': '__add__',
+ '-': '__sub__',
+ '/': '__div__',
+ '//': '__floordiv__',
+ '*': '__mul__',
+ '**': '__power__',
+ '%': '__mod__',
+ '&': '__and__',
+ '|': '__or__',
+ '^': '__xor__',
+ '<<': '__lshift__',
+ '>>': '__rshift__',
+ }
+
+UNARY_OP_METHOD = {'+': '__pos__',
+ '-': '__neg__',
+ '~': '__invert__',
+ 'not': None, # XXX not '__nonzero__'
+ }
+
+# unary operations ############################################################
+
+def tl_infer_unary_op(self, operator):
+ if operator == 'not':
+ return const_factory(not bool(self.elts))
+ raise TypeError() # XXX log unsupported operation
+nodes.Tuple.infer_unary_op = tl_infer_unary_op
+nodes.List.infer_unary_op = tl_infer_unary_op
+
+
+def dict_infer_unary_op(self, operator):
+ if operator == 'not':
+ return const_factory(not bool(self.items))
+ raise TypeError() # XXX log unsupported operation
+nodes.Dict.infer_unary_op = dict_infer_unary_op
+
+
+def const_infer_unary_op(self, operator):
+ if operator == 'not':
+ return const_factory(not self.value)
+ # XXX log potentially raised TypeError
+ elif operator == '+':
+ return const_factory(+self.value)
+ else: # operator == '-':
+ return const_factory(-self.value)
+nodes.Const.infer_unary_op = const_infer_unary_op
+
+
+# binary operations ###########################################################
+
+BIN_OP_IMPL = {'+': lambda a, b: a + b,
+ '-': lambda a, b: a - b,
+ '/': lambda a, b: a / b,
+ '//': lambda a, b: a // b,
+ '*': lambda a, b: a * b,
+ '**': lambda a, b: a ** b,
+ '%': lambda a, b: a % b,
+ '&': lambda a, b: a & b,
+ '|': lambda a, b: a | b,
+ '^': lambda a, b: a ^ b,
+ '<<': lambda a, b: a << b,
+ '>>': lambda a, b: a >> b,
+ }
+for key, impl in list(BIN_OP_IMPL.items()):
+ BIN_OP_IMPL[key+'='] = impl
+
+def const_infer_binary_op(self, operator, other, context):
+ for other in other.infer(context):
+ if isinstance(other, nodes.Const):
+ try:
+ impl = BIN_OP_IMPL[operator]
+
+ try:
+ yield const_factory(impl(self.value, other.value))
+ except Exception:
+ # ArithmeticError is not enough: float >> float is a TypeError
+ # TODO : let pylint know about the problem
+ pass
+ except TypeError:
+ # XXX log TypeError
+ continue
+ elif other is YES:
+ yield other
+ else:
+ try:
+ for val in other.infer_binary_op(operator, self, context):
+ yield val
+ except AttributeError:
+ yield YES
+nodes.Const.infer_binary_op = yes_if_nothing_infered(const_infer_binary_op)
+
+
+def tl_infer_binary_op(self, operator, other, context):
+ for other in other.infer(context):
+ if isinstance(other, self.__class__) and operator == '+':
+ node = self.__class__()
+ elts = [n for elt in self.elts for n in elt.infer(context)
+ if not n is YES]
+ elts += [n for elt in other.elts for n in elt.infer(context)
+ if not n is YES]
+ node.elts = elts
+ yield node
+ elif isinstance(other, nodes.Const) and operator == '*':
+ if not isinstance(other.value, int):
+ yield YES
+ continue
+ node = self.__class__()
+ elts = [n for elt in self.elts for n in elt.infer(context)
+ if not n is YES] * other.value
+ node.elts = elts
+ yield node
+ elif isinstance(other, Instance) and not isinstance(other, nodes.Const):
+ yield YES
+ # XXX else log TypeError
+nodes.Tuple.infer_binary_op = yes_if_nothing_infered(tl_infer_binary_op)
+nodes.List.infer_binary_op = yes_if_nothing_infered(tl_infer_binary_op)
+
+
+def dict_infer_binary_op(self, operator, other, context):
+ for other in other.infer(context):
+ if isinstance(other, Instance) and isinstance(other._proxied, nodes.Class):
+ yield YES
+ # XXX else log TypeError
+nodes.Dict.infer_binary_op = yes_if_nothing_infered(dict_infer_binary_op)
+
+def instance_infer_binary_op(self, operator, other, context):
+ try:
+ methods = self.getattr(BIN_OP_METHOD[operator])
+ except (NotFoundError, KeyError):
+ # Unknown operator
+ yield YES
+ else:
+ for method in methods:
+ if not isinstance(method, nodes.Function):
+ continue
+ for result in method.infer_call_result(self, context):
+ if result is not YES:
+ yield result
+ # We are interested only in the first infered method,
+ # don't go looking in the rest of the methods of the ancestors.
+ break
+
+Instance.infer_binary_op = yes_if_nothing_infered(instance_infer_binary_op)
+
+
+# assignment ##################################################################
+
+"""the assigned_stmts method is responsible to return the assigned statement
+(e.g. not inferred) according to the assignment type.
+
+The `asspath` argument is used to record the lhs path of the original node.
+For instance if we want assigned statements for 'c' in 'a, (b,c)', asspath
+will be [1, 1] once arrived to the Assign node.
+
+The `context` argument is the current inference context which should be given
+to any intermediary inference necessary.
+"""
+
+def _resolve_looppart(parts, asspath, context):
+ """recursive function to resolve multiple assignments on loops"""
+ asspath = asspath[:]
+ index = asspath.pop(0)
+ for part in parts:
+ if part is YES:
+ continue
+ # XXX handle __iter__ and log potentially detected errors
+ if not hasattr(part, 'itered'):
+ continue
+ try:
+ itered = part.itered()
+ except TypeError:
+ continue # XXX log error
+ for stmt in itered:
+ try:
+ assigned = stmt.getitem(index, context)
+ except (AttributeError, IndexError):
+ continue
+ except TypeError: # stmt is unsubscriptable Const
+ continue
+ if not asspath:
+ # we achieved to resolved the assignment path,
+ # don't infer the last part
+ yield assigned
+ elif assigned is YES:
+ break
+ else:
+ # we are not yet on the last part of the path
+ # search on each possibly inferred value
+ try:
+ for infered in _resolve_looppart(assigned.infer(context),
+ asspath, context):
+ yield infered
+ except InferenceError:
+ break
+
+
+def for_assigned_stmts(self, node, context=None, asspath=None):
+ if asspath is None:
+ for lst in self.iter.infer(context):
+ if isinstance(lst, (nodes.Tuple, nodes.List)):
+ for item in lst.elts:
+ yield item
+ else:
+ for infered in _resolve_looppart(self.iter.infer(context),
+ asspath, context):
+ yield infered
+
+nodes.For.assigned_stmts = raise_if_nothing_infered(for_assigned_stmts)
+nodes.Comprehension.assigned_stmts = raise_if_nothing_infered(for_assigned_stmts)
+
+
+def mulass_assigned_stmts(self, node, context=None, asspath=None):
+ if asspath is None:
+ asspath = []
+ asspath.insert(0, self.elts.index(node))
+ return self.parent.assigned_stmts(self, context, asspath)
+nodes.Tuple.assigned_stmts = mulass_assigned_stmts
+nodes.List.assigned_stmts = mulass_assigned_stmts
+
+
+def assend_assigned_stmts(self, context=None):
+ return self.parent.assigned_stmts(self, context=context)
+nodes.AssName.assigned_stmts = assend_assigned_stmts
+nodes.AssAttr.assigned_stmts = assend_assigned_stmts
+
+
+def _arguments_infer_argname(self, name, context):
+ # arguments information may be missing, in which case we can't do anything
+ # more
+ if not (self.args or self.vararg or self.kwarg):
+ yield YES
+ return
+ # first argument of instance/class method
+ if self.args and getattr(self.args[0], 'name', None) == name:
+ functype = self.parent.type
+ if functype == 'method':
+ yield Instance(self.parent.parent.frame())
+ return
+ if functype == 'classmethod':
+ yield self.parent.parent.frame()
+ return
+ if name == self.vararg:
+ vararg = const_factory(())
+ vararg.parent = self
+ yield vararg
+ return
+ if name == self.kwarg:
+ kwarg = const_factory({})
+ kwarg.parent = self
+ yield kwarg
+ return
+ # if there is a default value, yield it. And then yield YES to reflect
+ # we can't guess given argument value
+ try:
+ context = copy_context(context)
+ for infered in self.default_value(name).infer(context):
+ yield infered
+ yield YES
+ except NoDefault:
+ yield YES
+
+
+def arguments_assigned_stmts(self, node, context, asspath=None):
+ if context.callcontext:
+ # reset call context/name
+ callcontext = context.callcontext
+ context = copy_context(context)
+ context.callcontext = None
+ return callcontext.infer_argument(self.parent, node.name, context)
+ return _arguments_infer_argname(self, node.name, context)
+nodes.Arguments.assigned_stmts = arguments_assigned_stmts
+
+
+def assign_assigned_stmts(self, node, context=None, asspath=None):
+ if not asspath:
+ yield self.value
+ return
+ for infered in _resolve_asspart(self.value.infer(context), asspath, context):
+ yield infered
+nodes.Assign.assigned_stmts = raise_if_nothing_infered(assign_assigned_stmts)
+nodes.AugAssign.assigned_stmts = raise_if_nothing_infered(assign_assigned_stmts)
+
+
+def _resolve_asspart(parts, asspath, context):
+ """recursive function to resolve multiple assignments"""
+ asspath = asspath[:]
+ index = asspath.pop(0)
+ for part in parts:
+ if hasattr(part, 'getitem'):
+ try:
+ assigned = part.getitem(index, context)
+ # XXX raise a specific exception to avoid potential hiding of
+ # unexpected exception ?
+ except (TypeError, IndexError):
+ return
+ if not asspath:
+ # we achieved to resolved the assignment path, don't infer the
+ # last part
+ yield assigned
+ elif assigned is YES:
+ return
+ else:
+ # we are not yet on the last part of the path search on each
+ # possibly inferred value
+ try:
+ for infered in _resolve_asspart(assigned.infer(context),
+ asspath, context):
+ yield infered
+ except InferenceError:
+ return
+
+
+def excepthandler_assigned_stmts(self, node, context=None, asspath=None):
+ for assigned in unpack_infer(self.type):
+ if isinstance(assigned, nodes.Class):
+ assigned = Instance(assigned)
+ yield assigned
+nodes.ExceptHandler.assigned_stmts = raise_if_nothing_infered(excepthandler_assigned_stmts)
+
+
+def with_assigned_stmts(self, node, context=None, asspath=None):
+ if asspath is None:
+ for _, vars in self.items:
+ if vars is None:
+ continue
+ for lst in vars.infer(context):
+ if isinstance(lst, (nodes.Tuple, nodes.List)):
+ for item in lst.nodes:
+ yield item
+nodes.With.assigned_stmts = raise_if_nothing_infered(with_assigned_stmts)
+
+
+def starred_assigned_stmts(self, node=None, context=None, asspath=None):
+ stmt = self.statement()
+ if not isinstance(stmt, (nodes.Assign, nodes.For)):
+ raise InferenceError()
+
+ if isinstance(stmt, nodes.Assign):
+ value = stmt.value
+ lhs = stmt.targets[0]
+
+ if sum(1 for node in lhs.nodes_of_class(nodes.Starred)) > 1:
+ # Too many starred arguments in the expression.
+ raise InferenceError()
+
+ if context is None:
+ context = InferenceContext()
+ try:
+ rhs = next(value.infer(context))
+ except InferenceError:
+ yield YES
+ return
+ if rhs is YES or not hasattr(rhs, 'elts'):
+ # Not interested in inferred values without elts.
+ yield YES
+ return
+
+ elts = collections.deque(rhs.elts[:])
+ if len(lhs.elts) > len(rhs.elts):
+ # a, *b, c = (1, 2)
+ raise InferenceError()
+
+ # Unpack iteratively the values from the rhs of the assignment,
+ # until the find the starred node. What will remain will
+ # be the list of values which the Starred node will represent
+ # This is done in two steps, from left to right to remove
+ # anything before the starred node and from right to left
+ # to remvoe anything after the starred node.
+
+ for index, node in enumerate(lhs.elts):
+ if not isinstance(node, nodes.Starred):
+ elts.popleft()
+ continue
+ lhs_elts = collections.deque(reversed(lhs.elts[index:]))
+ for node in lhs_elts:
+ if not isinstance(node, nodes.Starred):
+ elts.pop()
+ continue
+ # We're done
+ for elt in elts:
+ yield elt
+ break
+
+nodes.Starred.assigned_stmts = starred_assigned_stmts
diff -Nru astroid-1.0.1/astroid/raw_building.py astroid-1.3.8/astroid/raw_building.py
--- astroid-1.0.1/astroid/raw_building.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/raw_building.py 2015-08-02 19:35:46.000000000 +0000
@@ -0,0 +1,366 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""this module contains a set of functions to create astroid trees from scratch
+(build_* functions) or from living object (object_build_* functions)
+"""
+
+__docformat__ = "restructuredtext en"
+
+import sys
+from os.path import abspath
+from inspect import (getargspec, isdatadescriptor, isfunction, ismethod,
+ ismethoddescriptor, isclass, isbuiltin, ismodule)
+import six
+
+from astroid.node_classes import CONST_CLS
+from astroid.nodes import (Module, Class, Const, const_factory, From,
+ Function, EmptyNode, Name, Arguments)
+from astroid.bases import BUILTINS, Generator
+from astroid.manager import AstroidManager
+MANAGER = AstroidManager()
+
+_CONSTANTS = tuple(CONST_CLS) # the keys of CONST_CLS eg python builtin types
+
+def _io_discrepancy(member):
+ # _io module names itself `io`: http://bugs.python.org/issue18602
+ member_self = getattr(member, '__self__', None)
+ return (member_self and
+ ismodule(member_self) and
+ member_self.__name__ == '_io' and
+ member.__module__ == 'io')
+
+def _attach_local_node(parent, node, name):
+ node.name = name # needed by add_local_node
+ parent.add_local_node(node)
+
+_marker = object()
+
+def attach_dummy_node(node, name, object=_marker):
+ """create a dummy node and register it in the locals of the given
+ node with the specified name
+ """
+ enode = EmptyNode()
+ enode.object = object
+ _attach_local_node(node, enode, name)
+
+def _has_underlying_object(self):
+ return hasattr(self, 'object') and self.object is not _marker
+
+EmptyNode.has_underlying_object = _has_underlying_object
+
+def attach_const_node(node, name, value):
+ """create a Const node and register it in the locals of the given
+ node with the specified name
+ """
+ if not name in node.special_attributes:
+ _attach_local_node(node, const_factory(value), name)
+
+def attach_import_node(node, modname, membername):
+ """create a From node and register it in the locals of the given
+ node with the specified name
+ """
+ from_node = From(modname, [(membername, None)])
+ _attach_local_node(node, from_node, membername)
+
+
+def build_module(name, doc=None):
+ """create and initialize a astroid Module node"""
+ node = Module(name, doc, pure_python=False)
+ node.package = False
+ node.parent = None
+ return node
+
+def build_class(name, basenames=(), doc=None):
+ """create and initialize a astroid Class node"""
+ node = Class(name, doc)
+ for base in basenames:
+ basenode = Name()
+ basenode.name = base
+ node.bases.append(basenode)
+ basenode.parent = node
+ return node
+
+def build_function(name, args=None, defaults=None, flag=0, doc=None):
+ """create and initialize a astroid Function node"""
+ args, defaults = args or [], defaults or []
+ # first argument is now a list of decorators
+ func = Function(name, doc)
+ func.args = argsnode = Arguments()
+ argsnode.args = []
+ for arg in args:
+ argsnode.args.append(Name())
+ argsnode.args[-1].name = arg
+ argsnode.args[-1].parent = argsnode
+ argsnode.defaults = []
+ for default in defaults:
+ argsnode.defaults.append(const_factory(default))
+ argsnode.defaults[-1].parent = argsnode
+ argsnode.kwarg = None
+ argsnode.vararg = None
+ argsnode.parent = func
+ if args:
+ register_arguments(func)
+ return func
+
+
+def build_from_import(fromname, names):
+ """create and initialize an astroid From import statement"""
+ return From(fromname, [(name, None) for name in names])
+
+def register_arguments(func, args=None):
+ """add given arguments to local
+
+ args is a list that may contains nested lists
+ (i.e. def func(a, (b, c, d)): ...)
+ """
+ if args is None:
+ args = func.args.args
+ if func.args.vararg:
+ func.set_local(func.args.vararg, func.args)
+ if func.args.kwarg:
+ func.set_local(func.args.kwarg, func.args)
+ for arg in args:
+ if isinstance(arg, Name):
+ func.set_local(arg.name, arg)
+ else:
+ register_arguments(func, arg.elts)
+
+def object_build_class(node, member, localname):
+ """create astroid for a living class object"""
+ basenames = [base.__name__ for base in member.__bases__]
+ return _base_class_object_build(node, member, basenames,
+ localname=localname)
+
+def object_build_function(node, member, localname):
+ """create astroid for a living function object"""
+ args, varargs, varkw, defaults = getargspec(member)
+ if varargs is not None:
+ args.append(varargs)
+ if varkw is not None:
+ args.append(varkw)
+ func = build_function(getattr(member, '__name__', None) or localname, args,
+ defaults, six.get_function_code(member).co_flags, member.__doc__)
+ node.add_local_node(func, localname)
+
+def object_build_datadescriptor(node, member, name):
+ """create astroid for a living data descriptor object"""
+ return _base_class_object_build(node, member, [], name)
+
+def object_build_methoddescriptor(node, member, localname):
+ """create astroid for a living method descriptor object"""
+ # FIXME get arguments ?
+ func = build_function(getattr(member, '__name__', None) or localname,
+ doc=member.__doc__)
+ # set node's arguments to None to notice that we have no information, not
+ # and empty argument list
+ func.args.args = None
+ node.add_local_node(func, localname)
+
+def _base_class_object_build(node, member, basenames, name=None, localname=None):
+ """create astroid for a living class object, with a given set of base names
+ (e.g. ancestors)
+ """
+ klass = build_class(name or getattr(member, '__name__', None) or localname,
+ basenames, member.__doc__)
+ klass._newstyle = isinstance(member, type)
+ node.add_local_node(klass, localname)
+ try:
+ # limit the instantiation trick since it's too dangerous
+ # (such as infinite test execution...)
+ # this at least resolves common case such as Exception.args,
+ # OSError.errno
+ if issubclass(member, Exception):
+ instdict = member().__dict__
+ else:
+ raise TypeError
+ except:
+ pass
+ else:
+ for name, obj in instdict.items():
+ valnode = EmptyNode()
+ valnode.object = obj
+ valnode.parent = klass
+ valnode.lineno = 1
+ klass.instance_attrs[name] = [valnode]
+ return klass
+
+
+
+
+class InspectBuilder(object):
+ """class for building nodes from living object
+
+ this is actually a really minimal representation, including only Module,
+ Function and Class nodes and some others as guessed.
+ """
+
+ # astroid from living objects ###############################################
+
+ def __init__(self):
+ self._done = {}
+ self._module = None
+
+ def inspect_build(self, module, modname=None, path=None):
+ """build astroid from a living module (i.e. using inspect)
+ this is used when there is no python source code available (either
+ because it's a built-in module or because the .py is not available)
+ """
+ self._module = module
+ if modname is None:
+ modname = module.__name__
+ try:
+ node = build_module(modname, module.__doc__)
+ except AttributeError:
+ # in jython, java modules have no __doc__ (see #109562)
+ node = build_module(modname)
+ node.file = node.path = path and abspath(path) or path
+ node.name = modname
+ MANAGER.cache_module(node)
+ node.package = hasattr(module, '__path__')
+ self._done = {}
+ self.object_build(node, module)
+ return node
+
+ def object_build(self, node, obj):
+ """recursive method which create a partial ast from real objects
+ (only function, class, and method are handled)
+ """
+ if obj in self._done:
+ return self._done[obj]
+ self._done[obj] = node
+ for name in dir(obj):
+ try:
+ member = getattr(obj, name)
+ except AttributeError:
+ # damned ExtensionClass.Base, I know you're there !
+ attach_dummy_node(node, name)
+ continue
+ if ismethod(member):
+ member = six.get_method_function(member)
+ if isfunction(member):
+ # verify this is not an imported function
+ filename = getattr(six.get_function_code(member),
+ 'co_filename', None)
+ if filename is None:
+ assert isinstance(member, object)
+ object_build_methoddescriptor(node, member, name)
+ elif filename != getattr(self._module, '__file__', None):
+ attach_dummy_node(node, name, member)
+ else:
+ object_build_function(node, member, name)
+ elif isbuiltin(member):
+ if (not _io_discrepancy(member) and
+ self.imported_member(node, member, name)):
+ continue
+ object_build_methoddescriptor(node, member, name)
+ elif isclass(member):
+ if self.imported_member(node, member, name):
+ continue
+ if member in self._done:
+ class_node = self._done[member]
+ if not class_node in node.locals.get(name, ()):
+ node.add_local_node(class_node, name)
+ else:
+ class_node = object_build_class(node, member, name)
+ # recursion
+ self.object_build(class_node, member)
+ if name == '__class__' and class_node.parent is None:
+ class_node.parent = self._done[self._module]
+ elif ismethoddescriptor(member):
+ assert isinstance(member, object)
+ object_build_methoddescriptor(node, member, name)
+ elif isdatadescriptor(member):
+ assert isinstance(member, object)
+ object_build_datadescriptor(node, member, name)
+ elif type(member) in _CONSTANTS:
+ attach_const_node(node, name, member)
+ else:
+ # create an empty node so that the name is actually defined
+ attach_dummy_node(node, name, member)
+
+ def imported_member(self, node, member, name):
+ """verify this is not an imported class or handle it"""
+ # /!\ some classes like ExtensionClass doesn't have a __module__
+ # attribute ! Also, this may trigger an exception on badly built module
+ # (see http://www.logilab.org/ticket/57299 for instance)
+ try:
+ modname = getattr(member, '__module__', None)
+ except:
+ # XXX use logging
+ print('unexpected error while building astroid from living object')
+ import traceback
+ traceback.print_exc()
+ modname = None
+ if modname is None:
+ if name in ('__new__', '__subclasshook__'):
+ # Python 2.5.1 (r251:54863, Sep 1 2010, 22:03:14)
+ # >>> print object.__new__.__module__
+ # None
+ modname = BUILTINS
+ else:
+ attach_dummy_node(node, name, member)
+ return True
+ if {'gtk': 'gtk._gtk'}.get(modname, modname) != self._module.__name__:
+ # check if it sounds valid and then add an import node, else use a
+ # dummy node
+ try:
+ getattr(sys.modules[modname], name)
+ except (KeyError, AttributeError):
+ attach_dummy_node(node, name, member)
+ else:
+ attach_import_node(node, modname, name)
+ return True
+ return False
+
+
+### astroid bootstrapping ######################################################
+Astroid_BUILDER = InspectBuilder()
+
+_CONST_PROXY = {}
+def _astroid_bootstrapping(astroid_builtin=None):
+ """astroid boot strapping the builtins module"""
+ # this boot strapping is necessary since we need the Const nodes to
+ # inspect_build builtins, and then we can proxy Const
+ if astroid_builtin is None:
+ from logilab.common.compat import builtins
+ astroid_builtin = Astroid_BUILDER.inspect_build(builtins)
+
+ for cls, node_cls in CONST_CLS.items():
+ if cls is type(None):
+ proxy = build_class('NoneType')
+ proxy.parent = astroid_builtin
+ else:
+ proxy = astroid_builtin.getattr(cls.__name__)[0]
+ if cls in (dict, list, set, tuple):
+ node_cls._proxied = proxy
+ else:
+ _CONST_PROXY[cls] = proxy
+
+_astroid_bootstrapping()
+
+# TODO : find a nicer way to handle this situation;
+# However __proxied introduced an
+# infinite recursion (see https://bugs.launchpad.net/pylint/+bug/456870)
+def _set_proxied(const):
+ return _CONST_PROXY[const.value.__class__]
+Const._proxied = property(_set_proxied)
+
+from types import GeneratorType
+Generator._proxied = Class(GeneratorType.__name__, GeneratorType.__doc__)
+Astroid_BUILDER.object_build(Generator._proxied, GeneratorType)
+
diff -Nru astroid-1.0.1/astroid/rebuilder.py astroid-1.3.8/astroid/rebuilder.py
--- astroid-1.0.1/astroid/rebuilder.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/rebuilder.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,926 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""this module contains utilities for rebuilding a _ast tree in
+order to get a single Astroid representation
+"""
+
+import sys
+from _ast import (
+ Expr as Discard, Str,
+ # binary operators
+ Add, BinOp, Div, FloorDiv, Mod, Mult, Pow, Sub, BitAnd, BitOr, BitXor,
+ LShift, RShift,
+ # logical operators
+ And, Or,
+ # unary operators
+ UAdd, USub, Not, Invert,
+ # comparison operators
+ Eq, Gt, GtE, In, Is, IsNot, Lt, LtE, NotEq, NotIn,
+ )
+
+from astroid import nodes as new
+from astroid import astpeephole
+
+
+_BIN_OP_CLASSES = {Add: '+',
+ BitAnd: '&',
+ BitOr: '|',
+ BitXor: '^',
+ Div: '/',
+ FloorDiv: '//',
+ Mod: '%',
+ Mult: '*',
+ Pow: '**',
+ Sub: '-',
+ LShift: '<<',
+ RShift: '>>',
+ }
+
+_BOOL_OP_CLASSES = {And: 'and',
+ Or: 'or',
+ }
+
+_UNARY_OP_CLASSES = {UAdd: '+',
+ USub: '-',
+ Not: 'not',
+ Invert: '~',
+ }
+
+_CMP_OP_CLASSES = {Eq: '==',
+ Gt: '>',
+ GtE: '>=',
+ In: 'in',
+ Is: 'is',
+ IsNot: 'is not',
+ Lt: '<',
+ LtE: '<=',
+ NotEq: '!=',
+ NotIn: 'not in',
+ }
+
+CONST_NAME_TRANSFORMS = {'None': None,
+ 'True': True,
+ 'False': False,
+ }
+
+REDIRECT = {'arguments': 'Arguments',
+ 'Attribute': 'Getattr',
+ 'comprehension': 'Comprehension',
+ 'Call': 'CallFunc',
+ 'ClassDef': 'Class',
+ "ListCompFor": 'Comprehension',
+ "GenExprFor": 'Comprehension',
+ 'excepthandler': 'ExceptHandler',
+ 'Expr': 'Discard',
+ 'FunctionDef': 'Function',
+ 'GeneratorExp': 'GenExpr',
+ 'ImportFrom': 'From',
+ 'keyword': 'Keyword',
+ 'Repr': 'Backquote',
+ }
+PY3K = sys.version_info >= (3, 0)
+PY34 = sys.version_info >= (3, 4)
+
+def _init_set_doc(node, newnode):
+ newnode.doc = None
+ try:
+ if isinstance(node.body[0], Discard) and isinstance(node.body[0].value, Str):
+ newnode.doc = node.body[0].value.s
+ node.body = node.body[1:]
+
+ except IndexError:
+ pass # ast built from scratch
+
+def _lineno_parent(oldnode, newnode, parent):
+ newnode.parent = parent
+ newnode.lineno = oldnode.lineno
+ newnode.col_offset = oldnode.col_offset
+
+def _set_infos(oldnode, newnode, parent):
+ newnode.parent = parent
+ if hasattr(oldnode, 'lineno'):
+ newnode.lineno = oldnode.lineno
+ if hasattr(oldnode, 'col_offset'):
+ newnode.col_offset = oldnode.col_offset
+
+def _create_yield_node(node, parent, rebuilder, factory):
+ newnode = factory()
+ _lineno_parent(node, newnode, parent)
+ if node.value is not None:
+ newnode.value = rebuilder.visit(node.value, newnode)
+ return newnode
+
+
+class TreeRebuilder(object):
+ """Rebuilds the _ast tree to become an Astroid tree"""
+
+ def __init__(self, manager):
+ self._manager = manager
+ self.asscontext = None
+ self._global_names = []
+ self._from_nodes = []
+ self._delayed_assattr = []
+ self._visit_meths = {}
+ self._transform = manager.transform
+ self._peepholer = astpeephole.ASTPeepholeOptimizer()
+
+ def visit_module(self, node, modname, modpath, package):
+ """visit a Module node by returning a fresh instance of it"""
+ newnode = new.Module(modname, None)
+ newnode.package = package
+ newnode.parent = None
+ _init_set_doc(node, newnode)
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ newnode.file = newnode.path = modpath
+ return self._transform(newnode)
+
+ def visit(self, node, parent):
+ cls = node.__class__
+ if cls in self._visit_meths:
+ visit_method = self._visit_meths[cls]
+ else:
+ cls_name = cls.__name__
+ visit_name = 'visit_' + REDIRECT.get(cls_name, cls_name).lower()
+ visit_method = getattr(self, visit_name)
+ self._visit_meths[cls] = visit_method
+ return self._transform(visit_method(node, parent))
+
+ def _save_assignment(self, node, name=None):
+ """save assignement situation since node.parent is not available yet"""
+ if self._global_names and node.name in self._global_names[-1]:
+ node.root().set_local(node.name, node)
+ else:
+ node.parent.set_local(node.name, node)
+
+
+ def visit_arguments(self, node, parent):
+ """visit a Arguments node by returning a fresh instance of it"""
+ newnode = new.Arguments()
+ newnode.parent = parent
+ self.asscontext = "Ass"
+ newnode.args = [self.visit(child, newnode) for child in node.args]
+ self.asscontext = None
+ newnode.defaults = [self.visit(child, newnode) for child in node.defaults]
+ newnode.kwonlyargs = []
+ newnode.kw_defaults = []
+ vararg, kwarg = node.vararg, node.kwarg
+ # change added in 82732 (7c5c678e4164), vararg and kwarg
+ # are instances of `_ast.arg`, not strings
+ if vararg:
+ if PY34:
+ if vararg.annotation:
+ newnode.varargannotation = self.visit(vararg.annotation,
+ newnode)
+ vararg = vararg.arg
+ elif PY3K and node.varargannotation:
+ newnode.varargannotation = self.visit(node.varargannotation,
+ newnode)
+ if kwarg:
+ if PY34:
+ if kwarg.annotation:
+ newnode.kwargannotation = self.visit(kwarg.annotation,
+ newnode)
+ kwarg = kwarg.arg
+ elif PY3K:
+ if node.kwargannotation:
+ newnode.kwargannotation = self.visit(node.kwargannotation,
+ newnode)
+ newnode.vararg = vararg
+ newnode.kwarg = kwarg
+ # save argument names in locals:
+ if vararg:
+ newnode.parent.set_local(vararg, newnode)
+ if kwarg:
+ newnode.parent.set_local(kwarg, newnode)
+ return newnode
+
+ def visit_assattr(self, node, parent):
+ """visit a AssAttr node by returning a fresh instance of it"""
+ assc, self.asscontext = self.asscontext, None
+ newnode = new.AssAttr()
+ _lineno_parent(node, newnode, parent)
+ newnode.expr = self.visit(node.expr, newnode)
+ self.asscontext = assc
+ self._delayed_assattr.append(newnode)
+ return newnode
+
+ def visit_assert(self, node, parent):
+ """visit a Assert node by returning a fresh instance of it"""
+ newnode = new.Assert()
+ _lineno_parent(node, newnode, parent)
+ newnode.test = self.visit(node.test, newnode)
+ if node.msg is not None:
+ newnode.fail = self.visit(node.msg, newnode)
+ return newnode
+
+ def visit_assign(self, node, parent):
+ """visit a Assign node by returning a fresh instance of it"""
+ newnode = new.Assign()
+ _lineno_parent(node, newnode, parent)
+ self.asscontext = "Ass"
+ newnode.targets = [self.visit(child, newnode) for child in node.targets]
+ self.asscontext = None
+ newnode.value = self.visit(node.value, newnode)
+ # set some function or metaclass infos XXX explain ?
+ klass = newnode.parent.frame()
+ if (isinstance(klass, new.Class)
+ and isinstance(newnode.value, new.CallFunc)
+ and isinstance(newnode.value.func, new.Name)):
+ func_name = newnode.value.func.name
+ for ass_node in newnode.targets:
+ try:
+ meth = klass[ass_node.name]
+ if isinstance(meth, new.Function):
+ if func_name in ('classmethod', 'staticmethod'):
+ meth.type = func_name
+ elif func_name == 'classproperty': # see lgc.decorators
+ meth.type = 'classmethod'
+ meth.extra_decorators.append(newnode.value)
+ except (AttributeError, KeyError):
+ continue
+ return newnode
+
+ def visit_assname(self, node, parent, node_name=None):
+ '''visit a node and return a AssName node'''
+ newnode = new.AssName()
+ _set_infos(node, newnode, parent)
+ newnode.name = node_name
+ self._save_assignment(newnode)
+ return newnode
+
+ def visit_augassign(self, node, parent):
+ """visit a AugAssign node by returning a fresh instance of it"""
+ newnode = new.AugAssign()
+ _lineno_parent(node, newnode, parent)
+ newnode.op = _BIN_OP_CLASSES[node.op.__class__] + "="
+ self.asscontext = "Ass"
+ newnode.target = self.visit(node.target, newnode)
+ self.asscontext = None
+ newnode.value = self.visit(node.value, newnode)
+ return newnode
+
+ def visit_backquote(self, node, parent):
+ """visit a Backquote node by returning a fresh instance of it"""
+ newnode = new.Backquote()
+ _lineno_parent(node, newnode, parent)
+ newnode.value = self.visit(node.value, newnode)
+ return newnode
+
+ def visit_binop(self, node, parent):
+ """visit a BinOp node by returning a fresh instance of it"""
+ if isinstance(node.left, BinOp) and self._manager.optimize_ast:
+ # Optimize BinOp operations in order to remove
+ # redundant recursion. For instance, if the
+ # following code is parsed in order to obtain
+ # its ast, then the rebuilder will fail with an
+ # infinite recursion, the same will happen with the
+ # inference engine as well. There's no need to hold
+ # so many objects for the BinOp if they can be reduced
+ # to something else (also, the optimization
+ # might handle only Const binops, which isn't a big
+ # problem for the correctness of the program).
+ #
+ # ("a" + "b" + # one thousand more + "c")
+ newnode = self._peepholer.optimize_binop(node)
+ if newnode:
+ _lineno_parent(node, newnode, parent)
+ return newnode
+
+ newnode = new.BinOp()
+ _lineno_parent(node, newnode, parent)
+ newnode.left = self.visit(node.left, newnode)
+ newnode.right = self.visit(node.right, newnode)
+ newnode.op = _BIN_OP_CLASSES[node.op.__class__]
+ return newnode
+
+ def visit_boolop(self, node, parent):
+ """visit a BoolOp node by returning a fresh instance of it"""
+ newnode = new.BoolOp()
+ _lineno_parent(node, newnode, parent)
+ newnode.values = [self.visit(child, newnode) for child in node.values]
+ newnode.op = _BOOL_OP_CLASSES[node.op.__class__]
+ return newnode
+
+ def visit_break(self, node, parent):
+ """visit a Break node by returning a fresh instance of it"""
+ newnode = new.Break()
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_callfunc(self, node, parent):
+ """visit a CallFunc node by returning a fresh instance of it"""
+ newnode = new.CallFunc()
+ _lineno_parent(node, newnode, parent)
+ newnode.func = self.visit(node.func, newnode)
+ newnode.args = [self.visit(child, newnode) for child in node.args]
+ if node.starargs is not None:
+ newnode.starargs = self.visit(node.starargs, newnode)
+ if node.kwargs is not None:
+ newnode.kwargs = self.visit(node.kwargs, newnode)
+ for child in node.keywords:
+ newnode.args.append(self.visit(child, newnode))
+ return newnode
+
+ def visit_class(self, node, parent):
+ """visit a Class node to become astroid"""
+ newnode = new.Class(node.name, None)
+ _lineno_parent(node, newnode, parent)
+ _init_set_doc(node, newnode)
+ newnode.bases = [self.visit(child, newnode) for child in node.bases]
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ if 'decorator_list' in node._fields and node.decorator_list:# py >= 2.6
+ newnode.decorators = self.visit_decorators(node, newnode)
+ newnode.parent.frame().set_local(newnode.name, newnode)
+ return newnode
+
+ def visit_const(self, node, parent):
+ """visit a Const node by returning a fresh instance of it"""
+ newnode = new.Const(node.value)
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_continue(self, node, parent):
+ """visit a Continue node by returning a fresh instance of it"""
+ newnode = new.Continue()
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_compare(self, node, parent):
+ """visit a Compare node by returning a fresh instance of it"""
+ newnode = new.Compare()
+ _lineno_parent(node, newnode, parent)
+ newnode.left = self.visit(node.left, newnode)
+ newnode.ops = [(_CMP_OP_CLASSES[op.__class__], self.visit(expr, newnode))
+ for (op, expr) in zip(node.ops, node.comparators)]
+ return newnode
+
+ def visit_comprehension(self, node, parent):
+ """visit a Comprehension node by returning a fresh instance of it"""
+ newnode = new.Comprehension()
+ newnode.parent = parent
+ self.asscontext = "Ass"
+ newnode.target = self.visit(node.target, newnode)
+ self.asscontext = None
+ newnode.iter = self.visit(node.iter, newnode)
+ newnode.ifs = [self.visit(child, newnode) for child in node.ifs]
+ return newnode
+
+ def visit_decorators(self, node, parent):
+ """visit a Decorators node by returning a fresh instance of it"""
+ # /!\ node is actually a _ast.Function node while
+ # parent is a astroid.nodes.Function node
+ newnode = new.Decorators()
+ _lineno_parent(node, newnode, parent)
+ if 'decorators' in node._fields: # py < 2.6, i.e. 2.5
+ decorators = node.decorators
+ else:
+ decorators = node.decorator_list
+ newnode.nodes = [self.visit(child, newnode) for child in decorators]
+ return newnode
+
+ def visit_delete(self, node, parent):
+ """visit a Delete node by returning a fresh instance of it"""
+ newnode = new.Delete()
+ _lineno_parent(node, newnode, parent)
+ self.asscontext = "Del"
+ newnode.targets = [self.visit(child, newnode) for child in node.targets]
+ self.asscontext = None
+ return newnode
+
+ def visit_dict(self, node, parent):
+ """visit a Dict node by returning a fresh instance of it"""
+ newnode = new.Dict()
+ _lineno_parent(node, newnode, parent)
+ newnode.items = [(self.visit(key, newnode), self.visit(value, newnode))
+ for key, value in zip(node.keys, node.values)]
+ return newnode
+
+ def visit_dictcomp(self, node, parent):
+ """visit a DictComp node by returning a fresh instance of it"""
+ newnode = new.DictComp()
+ _lineno_parent(node, newnode, parent)
+ newnode.key = self.visit(node.key, newnode)
+ newnode.value = self.visit(node.value, newnode)
+ newnode.generators = [self.visit(child, newnode)
+ for child in node.generators]
+ return newnode
+
+ def visit_discard(self, node, parent):
+ """visit a Discard node by returning a fresh instance of it"""
+ newnode = new.Discard()
+ _lineno_parent(node, newnode, parent)
+ newnode.value = self.visit(node.value, newnode)
+ return newnode
+
+ def visit_ellipsis(self, node, parent):
+ """visit an Ellipsis node by returning a fresh instance of it"""
+ newnode = new.Ellipsis()
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_emptynode(self, node, parent):
+ """visit an EmptyNode node by returning a fresh instance of it"""
+ newnode = new.EmptyNode()
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_excepthandler(self, node, parent):
+ """visit an ExceptHandler node by returning a fresh instance of it"""
+ newnode = new.ExceptHandler()
+ _lineno_parent(node, newnode, parent)
+ if node.type is not None:
+ newnode.type = self.visit(node.type, newnode)
+ if node.name is not None:
+ # /!\ node.name can be a tuple
+ self.asscontext = "Ass"
+ newnode.name = self.visit(node.name, newnode)
+ self.asscontext = None
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ return newnode
+
+ def visit_exec(self, node, parent):
+ """visit an Exec node by returning a fresh instance of it"""
+ newnode = new.Exec()
+ _lineno_parent(node, newnode, parent)
+ newnode.expr = self.visit(node.body, newnode)
+ if node.globals is not None:
+ newnode.globals = self.visit(node.globals, newnode)
+ if node.locals is not None:
+ newnode.locals = self.visit(node.locals, newnode)
+ return newnode
+
+ def visit_extslice(self, node, parent):
+ """visit an ExtSlice node by returning a fresh instance of it"""
+ newnode = new.ExtSlice()
+ newnode.parent = parent
+ newnode.dims = [self.visit(dim, newnode) for dim in node.dims]
+ return newnode
+
+ def visit_for(self, node, parent):
+ """visit a For node by returning a fresh instance of it"""
+ newnode = new.For()
+ _lineno_parent(node, newnode, parent)
+ self.asscontext = "Ass"
+ newnode.target = self.visit(node.target, newnode)
+ self.asscontext = None
+ newnode.iter = self.visit(node.iter, newnode)
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
+ return newnode
+
+ def visit_from(self, node, parent):
+ """visit a From node by returning a fresh instance of it"""
+ names = [(alias.name, alias.asname) for alias in node.names]
+ newnode = new.From(node.module or '', names, node.level or None)
+ _set_infos(node, newnode, parent)
+ # store From names to add them to locals after building
+ self._from_nodes.append(newnode)
+ return newnode
+
+ def visit_function(self, node, parent):
+ """visit an Function node to become astroid"""
+ self._global_names.append({})
+ newnode = new.Function(node.name, None)
+ _lineno_parent(node, newnode, parent)
+ _init_set_doc(node, newnode)
+ newnode.args = self.visit(node.args, newnode)
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ if 'decorators' in node._fields: # py < 2.6
+ attr = 'decorators'
+ else:
+ attr = 'decorator_list'
+ decorators = getattr(node, attr)
+ if decorators:
+ newnode.decorators = self.visit_decorators(node, newnode)
+ if PY3K and node.returns:
+ newnode.returns = self.visit(node.returns, newnode)
+ self._global_names.pop()
+ frame = newnode.parent.frame()
+ if isinstance(frame, new.Class):
+ if newnode.name == '__new__':
+ newnode._type = 'classmethod'
+ else:
+ newnode._type = 'method'
+ if newnode.decorators is not None:
+ for decorator_expr in newnode.decorators.nodes:
+ if isinstance(decorator_expr, new.Name):
+ if decorator_expr.name in ('classmethod', 'staticmethod'):
+ newnode._type = decorator_expr.name
+ elif decorator_expr.name == 'classproperty':
+ newnode._type = 'classmethod'
+ frame.set_local(newnode.name, newnode)
+ return newnode
+
+ def visit_genexpr(self, node, parent):
+ """visit a GenExpr node by returning a fresh instance of it"""
+ newnode = new.GenExpr()
+ _lineno_parent(node, newnode, parent)
+ newnode.elt = self.visit(node.elt, newnode)
+ newnode.generators = [self.visit(child, newnode) for child in node.generators]
+ return newnode
+
+ def visit_getattr(self, node, parent):
+ """visit a Getattr node by returning a fresh instance of it"""
+ if self.asscontext == "Del":
+ # FIXME : maybe we should reintroduce and visit_delattr ?
+ # for instance, deactivating asscontext
+ newnode = new.DelAttr()
+ elif self.asscontext == "Ass":
+ # FIXME : maybe we should call visit_assattr ?
+ newnode = new.AssAttr()
+ self._delayed_assattr.append(newnode)
+ else:
+ newnode = new.Getattr()
+ _lineno_parent(node, newnode, parent)
+ asscontext, self.asscontext = self.asscontext, None
+ newnode.expr = self.visit(node.value, newnode)
+ self.asscontext = asscontext
+ newnode.attrname = node.attr
+ return newnode
+
+ def visit_global(self, node, parent):
+ """visit an Global node to become astroid"""
+ newnode = new.Global(node.names)
+ _set_infos(node, newnode, parent)
+ if self._global_names: # global at the module level, no effect
+ for name in node.names:
+ self._global_names[-1].setdefault(name, []).append(newnode)
+ return newnode
+
+ def visit_if(self, node, parent):
+ """visit a If node by returning a fresh instance of it"""
+ newnode = new.If()
+ _lineno_parent(node, newnode, parent)
+ newnode.test = self.visit(node.test, newnode)
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
+ return newnode
+
+ def visit_ifexp(self, node, parent):
+ """visit a IfExp node by returning a fresh instance of it"""
+ newnode = new.IfExp()
+ _lineno_parent(node, newnode, parent)
+ newnode.test = self.visit(node.test, newnode)
+ newnode.body = self.visit(node.body, newnode)
+ newnode.orelse = self.visit(node.orelse, newnode)
+ return newnode
+
+ def visit_import(self, node, parent):
+ """visit a Import node by returning a fresh instance of it"""
+ newnode = new.Import()
+ _set_infos(node, newnode, parent)
+ newnode.names = [(alias.name, alias.asname) for alias in node.names]
+ # save import names in parent's locals:
+ for (name, asname) in newnode.names:
+ name = asname or name
+ newnode.parent.set_local(name.split('.')[0], newnode)
+ return newnode
+
+ def visit_index(self, node, parent):
+ """visit a Index node by returning a fresh instance of it"""
+ newnode = new.Index()
+ newnode.parent = parent
+ newnode.value = self.visit(node.value, newnode)
+ return newnode
+
+ def visit_keyword(self, node, parent):
+ """visit a Keyword node by returning a fresh instance of it"""
+ newnode = new.Keyword()
+ newnode.parent = parent
+ newnode.arg = node.arg
+ newnode.value = self.visit(node.value, newnode)
+ return newnode
+
+ def visit_lambda(self, node, parent):
+ """visit a Lambda node by returning a fresh instance of it"""
+ newnode = new.Lambda()
+ _lineno_parent(node, newnode, parent)
+ newnode.args = self.visit(node.args, newnode)
+ newnode.body = self.visit(node.body, newnode)
+ return newnode
+
+ def visit_list(self, node, parent):
+ """visit a List node by returning a fresh instance of it"""
+ newnode = new.List()
+ _lineno_parent(node, newnode, parent)
+ newnode.elts = [self.visit(child, newnode) for child in node.elts]
+ return newnode
+
+ def visit_listcomp(self, node, parent):
+ """visit a ListComp node by returning a fresh instance of it"""
+ newnode = new.ListComp()
+ _lineno_parent(node, newnode, parent)
+ newnode.elt = self.visit(node.elt, newnode)
+ newnode.generators = [self.visit(child, newnode)
+ for child in node.generators]
+ return newnode
+
+ def visit_name(self, node, parent):
+ """visit a Name node by returning a fresh instance of it"""
+ # True and False can be assigned to something in py2x, so we have to
+ # check first the asscontext
+ if self.asscontext == "Del":
+ newnode = new.DelName()
+ elif self.asscontext is not None: # Ass
+ assert self.asscontext == "Ass"
+ newnode = new.AssName()
+ elif node.id in CONST_NAME_TRANSFORMS:
+ newnode = new.Const(CONST_NAME_TRANSFORMS[node.id])
+ _set_infos(node, newnode, parent)
+ return newnode
+ else:
+ newnode = new.Name()
+ _lineno_parent(node, newnode, parent)
+ newnode.name = node.id
+ # XXX REMOVE me :
+ if self.asscontext in ('Del', 'Ass'): # 'Aug' ??
+ self._save_assignment(newnode)
+ return newnode
+
+ def visit_bytes(self, node, parent):
+ """visit a Bytes node by returning a fresh instance of Const"""
+ newnode = new.Const(node.s)
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_num(self, node, parent):
+ """visit a Num node by returning a fresh instance of Const"""
+ newnode = new.Const(node.n)
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_pass(self, node, parent):
+ """visit a Pass node by returning a fresh instance of it"""
+ newnode = new.Pass()
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_str(self, node, parent):
+ """visit a Str node by returning a fresh instance of Const"""
+ newnode = new.Const(node.s)
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_print(self, node, parent):
+ """visit a Print node by returning a fresh instance of it"""
+ newnode = new.Print()
+ _lineno_parent(node, newnode, parent)
+ newnode.nl = node.nl
+ if node.dest is not None:
+ newnode.dest = self.visit(node.dest, newnode)
+ newnode.values = [self.visit(child, newnode) for child in node.values]
+ return newnode
+
+ def visit_raise(self, node, parent):
+ """visit a Raise node by returning a fresh instance of it"""
+ newnode = new.Raise()
+ _lineno_parent(node, newnode, parent)
+ if node.type is not None:
+ newnode.exc = self.visit(node.type, newnode)
+ if node.inst is not None:
+ newnode.inst = self.visit(node.inst, newnode)
+ if node.tback is not None:
+ newnode.tback = self.visit(node.tback, newnode)
+ return newnode
+
+ def visit_return(self, node, parent):
+ """visit a Return node by returning a fresh instance of it"""
+ newnode = new.Return()
+ _lineno_parent(node, newnode, parent)
+ if node.value is not None:
+ newnode.value = self.visit(node.value, newnode)
+ return newnode
+
+ def visit_set(self, node, parent):
+ """visit a Set node by returning a fresh instance of it"""
+ newnode = new.Set()
+ _lineno_parent(node, newnode, parent)
+ newnode.elts = [self.visit(child, newnode) for child in node.elts]
+ return newnode
+
+ def visit_setcomp(self, node, parent):
+ """visit a SetComp node by returning a fresh instance of it"""
+ newnode = new.SetComp()
+ _lineno_parent(node, newnode, parent)
+ newnode.elt = self.visit(node.elt, newnode)
+ newnode.generators = [self.visit(child, newnode)
+ for child in node.generators]
+ return newnode
+
+ def visit_slice(self, node, parent):
+ """visit a Slice node by returning a fresh instance of it"""
+ newnode = new.Slice()
+ newnode.parent = parent
+ if node.lower is not None:
+ newnode.lower = self.visit(node.lower, newnode)
+ if node.upper is not None:
+ newnode.upper = self.visit(node.upper, newnode)
+ if node.step is not None:
+ newnode.step = self.visit(node.step, newnode)
+ return newnode
+
+ def visit_subscript(self, node, parent):
+ """visit a Subscript node by returning a fresh instance of it"""
+ newnode = new.Subscript()
+ _lineno_parent(node, newnode, parent)
+ subcontext, self.asscontext = self.asscontext, None
+ newnode.value = self.visit(node.value, newnode)
+ newnode.slice = self.visit(node.slice, newnode)
+ self.asscontext = subcontext
+ return newnode
+
+ def visit_tryexcept(self, node, parent):
+ """visit a TryExcept node by returning a fresh instance of it"""
+ newnode = new.TryExcept()
+ _lineno_parent(node, newnode, parent)
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ newnode.handlers = [self.visit(child, newnode) for child in node.handlers]
+ newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
+ return newnode
+
+ def visit_tryfinally(self, node, parent):
+ """visit a TryFinally node by returning a fresh instance of it"""
+ newnode = new.TryFinally()
+ _lineno_parent(node, newnode, parent)
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ newnode.finalbody = [self.visit(n, newnode) for n in node.finalbody]
+ return newnode
+
+ def visit_tuple(self, node, parent):
+ """visit a Tuple node by returning a fresh instance of it"""
+ newnode = new.Tuple()
+ _lineno_parent(node, newnode, parent)
+ newnode.elts = [self.visit(child, newnode) for child in node.elts]
+ return newnode
+
+ def visit_unaryop(self, node, parent):
+ """visit a UnaryOp node by returning a fresh instance of it"""
+ newnode = new.UnaryOp()
+ _lineno_parent(node, newnode, parent)
+ newnode.operand = self.visit(node.operand, newnode)
+ newnode.op = _UNARY_OP_CLASSES[node.op.__class__]
+ return newnode
+
+ def visit_while(self, node, parent):
+ """visit a While node by returning a fresh instance of it"""
+ newnode = new.While()
+ _lineno_parent(node, newnode, parent)
+ newnode.test = self.visit(node.test, newnode)
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
+ return newnode
+
+ def visit_with(self, node, parent):
+ newnode = new.With()
+ _lineno_parent(node, newnode, parent)
+ expr = self.visit(node.context_expr, newnode)
+ self.asscontext = "Ass"
+ if node.optional_vars is not None:
+ vars = self.visit(node.optional_vars, newnode)
+ else:
+ vars = None
+ self.asscontext = None
+ newnode.items = [(expr, vars)]
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ return newnode
+
+ def visit_yield(self, node, parent):
+ """visit a Yield node by returning a fresh instance of it"""
+ return _create_yield_node(node, parent, self, new.Yield)
+
+class TreeRebuilder3k(TreeRebuilder):
+ """extend and overwrite TreeRebuilder for python3k"""
+
+ def visit_arg(self, node, parent):
+ """visit a arg node by returning a fresh AssName instance"""
+ # the node is coming from py>=3.0, but we use AssName in py2.x
+ # XXX or we should instead introduce a Arg node in astroid ?
+ return self.visit_assname(node, parent, node.arg)
+
+ def visit_nameconstant(self, node, parent):
+ # in Python 3.4 we have NameConstant for True / False / None
+ newnode = new.Const(node.value)
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_arguments(self, node, parent):
+ newnode = super(TreeRebuilder3k, self).visit_arguments(node, parent)
+ self.asscontext = "Ass"
+ newnode.kwonlyargs = [self.visit(child, newnode) for child in node.kwonlyargs]
+ self.asscontext = None
+ newnode.kw_defaults = [self.visit(child, newnode) if child else None for child in node.kw_defaults]
+ newnode.annotations = [
+ self.visit(arg.annotation, newnode) if arg.annotation else None
+ for arg in node.args]
+ return newnode
+
+ def visit_excepthandler(self, node, parent):
+ """visit an ExceptHandler node by returning a fresh instance of it"""
+ newnode = new.ExceptHandler()
+ _lineno_parent(node, newnode, parent)
+ if node.type is not None:
+ newnode.type = self.visit(node.type, newnode)
+ if node.name is not None:
+ newnode.name = self.visit_assname(node, newnode, node.name)
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ return newnode
+
+ def visit_nonlocal(self, node, parent):
+ """visit a Nonlocal node and return a new instance of it"""
+ newnode = new.Nonlocal(node.names)
+ _set_infos(node, newnode, parent)
+ return newnode
+
+ def visit_raise(self, node, parent):
+ """visit a Raise node by returning a fresh instance of it"""
+ newnode = new.Raise()
+ _lineno_parent(node, newnode, parent)
+ # no traceback; anyway it is not used in Pylint
+ if node.exc is not None:
+ newnode.exc = self.visit(node.exc, newnode)
+ if node.cause is not None:
+ newnode.cause = self.visit(node.cause, newnode)
+ return newnode
+
+ def visit_starred(self, node, parent):
+ """visit a Starred node and return a new instance of it"""
+ newnode = new.Starred()
+ _lineno_parent(node, newnode, parent)
+ newnode.value = self.visit(node.value, newnode)
+ return newnode
+
+ def visit_try(self, node, parent):
+ # python 3.3 introduce a new Try node replacing TryFinally/TryExcept nodes
+ if node.finalbody:
+ newnode = new.TryFinally()
+ _lineno_parent(node, newnode, parent)
+ newnode.finalbody = [self.visit(n, newnode) for n in node.finalbody]
+ if node.handlers:
+ excnode = new.TryExcept()
+ _lineno_parent(node, excnode, newnode)
+ excnode.body = [self.visit(child, excnode) for child in node.body]
+ excnode.handlers = [self.visit(child, excnode) for child in node.handlers]
+ excnode.orelse = [self.visit(child, excnode) for child in node.orelse]
+ newnode.body = [excnode]
+ else:
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ elif node.handlers:
+ newnode = new.TryExcept()
+ _lineno_parent(node, newnode, parent)
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ newnode.handlers = [self.visit(child, newnode) for child in node.handlers]
+ newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
+ return newnode
+
+ def visit_with(self, node, parent):
+ if 'items' not in node._fields:
+ # python < 3.3
+ return super(TreeRebuilder3k, self).visit_with(node, parent)
+
+ newnode = new.With()
+ _lineno_parent(node, newnode, parent)
+ def visit_child(child):
+ expr = self.visit(child.context_expr, newnode)
+ self.asscontext = 'Ass'
+ if child.optional_vars:
+ var = self.visit(child.optional_vars, newnode)
+ else:
+ var = None
+ self.asscontext = None
+ return expr, var
+ newnode.items = [visit_child(child)
+ for child in node.items]
+ newnode.body = [self.visit(child, newnode) for child in node.body]
+ return newnode
+
+ def visit_yieldfrom(self, node, parent):
+ return _create_yield_node(node, parent, self, new.YieldFrom)
+
+ def visit_class(self, node, parent):
+ newnode = super(TreeRebuilder3k, self).visit_class(node, parent)
+ newnode._newstyle = True
+ for keyword in node.keywords:
+ if keyword.arg == 'metaclass':
+ newnode._metaclass = self.visit(keyword, newnode).value
+ break
+ return newnode
+
+if sys.version_info >= (3, 0):
+ TreeRebuilder = TreeRebuilder3k
+
+
diff -Nru astroid-1.0.1/astroid/scoped_nodes.py astroid-1.3.8/astroid/scoped_nodes.py
--- astroid-1.0.1/astroid/scoped_nodes.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/scoped_nodes.py 2015-08-02 19:35:55.000000000 +0000
@@ -0,0 +1,1484 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""This module contains the classes for "scoped" node, i.e. which are opening a
+new local scope in the language definition : Module, Class, Function (and
+Lambda, GenExpr, DictComp and SetComp to some extent).
+"""
+from __future__ import with_statement
+
+__doctype__ = "restructuredtext en"
+
+import sys
+import warnings
+from itertools import chain
+try:
+ from io import BytesIO
+except ImportError:
+ from cStringIO import StringIO as BytesIO
+
+import six
+from logilab.common.compat import builtins
+from logilab.common.decorators import cached, cachedproperty
+
+from astroid.exceptions import NotFoundError, \
+ AstroidBuildingException, InferenceError, ResolveError
+from astroid.node_classes import Const, DelName, DelAttr, \
+ Dict, From, List, Pass, Raise, Return, Tuple, Yield, YieldFrom, \
+ LookupMixIn, const_factory as cf, unpack_infer, CallFunc
+from astroid.bases import NodeNG, InferenceContext, Instance, copy_context, \
+ YES, Generator, UnboundMethod, BoundMethod, _infer_stmts, \
+ BUILTINS
+from astroid.mixins import FilterStmtsMixin
+from astroid.bases import Statement
+from astroid.manager import AstroidManager
+
+ITER_METHODS = ('__iter__', '__getitem__')
+PY3K = sys.version_info >= (3, 0)
+
+def _c3_merge(sequences):
+ """Merges MROs in *sequences* to a single MRO using the C3 algorithm.
+
+ Adapted from http://www.python.org/download/releases/2.3/mro/.
+
+ """
+ result = []
+ while True:
+ sequences = [s for s in sequences if s] # purge empty sequences
+ if not sequences:
+ return result
+ for s1 in sequences: # find merge candidates among seq heads
+ candidate = s1[0]
+ for s2 in sequences:
+ if candidate in s2[1:]:
+ candidate = None
+ break # reject the current head, it appears later
+ else:
+ break
+ if not candidate:
+ # Show all the remaining bases, which were considered as
+ # candidates for the next mro sequence.
+ bases = ["({})".format(", ".join(base.name
+ for base in subsequence))
+ for subsequence in sequences]
+ raise ResolveError("Cannot create a consistent method resolution "
+ "order for bases %s" % ", ".join(bases))
+ result.append(candidate)
+ # remove the chosen candidate
+ for seq in sequences:
+ if seq[0] == candidate:
+ del seq[0]
+
+
+def _verify_duplicates_mro(sequences):
+ for sequence in sequences:
+ names = [node.qname() for node in sequence]
+ if len(names) != len(set(names)):
+ raise ResolveError('Duplicates found in the mro.')
+
+
+def remove_nodes(func, cls):
+ def wrapper(*args, **kwargs):
+ nodes = [n for n in func(*args, **kwargs) if not isinstance(n, cls)]
+ if not nodes:
+ raise NotFoundError()
+ return nodes
+ return wrapper
+
+
+def function_to_method(n, klass):
+ if isinstance(n, Function):
+ if n.type == 'classmethod':
+ return BoundMethod(n, klass)
+ if n.type != 'staticmethod':
+ return UnboundMethod(n)
+ return n
+
+def std_special_attributes(self, name, add_locals=True):
+ if add_locals:
+ locals = self.locals
+ else:
+ locals = {}
+ if name == '__name__':
+ return [cf(self.name)] + locals.get(name, [])
+ if name == '__doc__':
+ return [cf(self.doc)] + locals.get(name, [])
+ if name == '__dict__':
+ return [Dict()] + locals.get(name, [])
+ raise NotFoundError(name)
+
+MANAGER = AstroidManager()
+def builtin_lookup(name):
+ """lookup a name into the builtin module
+ return the list of matching statements and the astroid for the builtin
+ module
+ """
+ builtin_astroid = MANAGER.ast_from_module(builtins)
+ if name == '__dict__':
+ return builtin_astroid, ()
+ try:
+ stmts = builtin_astroid.locals[name]
+ except KeyError:
+ stmts = ()
+ return builtin_astroid, stmts
+
+
+# TODO move this Mixin to mixins.py; problem: 'Function' in _scope_lookup
+class LocalsDictNodeNG(LookupMixIn, NodeNG):
+ """ this class provides locals handling common to Module, Function
+ and Class nodes, including a dict like interface for direct access
+ to locals information
+ """
+
+ # attributes below are set by the builder module or by raw factories
+
+ # dictionary of locals with name as key and node defining the local as
+ # value
+
+ def qname(self):
+ """return the 'qualified' name of the node, eg module.name,
+ module.class.name ...
+ """
+ if self.parent is None:
+ return self.name
+ return '%s.%s' % (self.parent.frame().qname(), self.name)
+
+ def frame(self):
+ """return the first parent frame node (i.e. Module, Function or Class)
+ """
+ return self
+
+ def scope(self):
+ """return the first node defining a new scope (i.e. Module,
+ Function, Class, Lambda but also GenExpr, DictComp and SetComp)
+ """
+ return self
+
+
+ def _scope_lookup(self, node, name, offset=0):
+ """XXX method for interfacing the scope lookup"""
+ try:
+ stmts = node._filter_stmts(self.locals[name], self, offset)
+ except KeyError:
+ stmts = ()
+ if stmts:
+ return self, stmts
+ if self.parent: # i.e. not Module
+ # nested scope: if parent scope is a function, that's fine
+ # else jump to the module
+ pscope = self.parent.scope()
+ if not pscope.is_function:
+ pscope = pscope.root()
+ return pscope.scope_lookup(node, name)
+ return builtin_lookup(name) # Module
+
+
+
+ def set_local(self, name, stmt):
+ """define in locals ( is the node defining the name)
+ if the node is a Module node (i.e. has globals), add the name to
+ globals
+
+ if the name is already defined, ignore it
+ """
+ #assert not stmt in self.locals.get(name, ()), (self, stmt)
+ self.locals.setdefault(name, []).append(stmt)
+
+ __setitem__ = set_local
+
+ def _append_node(self, child):
+ """append a child, linking it in the tree"""
+ self.body.append(child)
+ child.parent = self
+
+ def add_local_node(self, child_node, name=None):
+ """append a child which should alter locals to the given node"""
+ if name != '__class__':
+ # add __class__ node as a child will cause infinite recursion later!
+ self._append_node(child_node)
+ self.set_local(name or child_node.name, child_node)
+
+
+ def __getitem__(self, item):
+ """method from the `dict` interface returning the first node
+ associated with the given name in the locals dictionary
+
+ :type item: str
+ :param item: the name of the locally defined object
+ :raises KeyError: if the name is not defined
+ """
+ return self.locals[item][0]
+
+ def __iter__(self):
+ """method from the `dict` interface returning an iterator on
+ `self.keys()`
+ """
+ return iter(self.keys())
+
+ def keys(self):
+ """method from the `dict` interface returning a tuple containing
+ locally defined names
+ """
+ return list(self.locals.keys())
+
+ def values(self):
+ """method from the `dict` interface returning a tuple containing
+ locally defined nodes which are instance of `Function` or `Class`
+ """
+ return [self[key] for key in self.keys()]
+
+ def items(self):
+ """method from the `dict` interface returning a list of tuple
+ containing each locally defined name with its associated node,
+ which is an instance of `Function` or `Class`
+ """
+ return list(zip(self.keys(), self.values()))
+
+
+ def __contains__(self, name):
+ return name in self.locals
+ has_key = __contains__
+
+# Module #####################################################################
+
+class Module(LocalsDictNodeNG):
+ _astroid_fields = ('body',)
+
+ fromlineno = 0
+ lineno = 0
+
+ # attributes below are set by the builder module or by raw factories
+
+ # the file from which as been extracted the astroid representation. It may
+ # be None if the representation has been built from a built-in module
+ file = None
+ # Alternatively, if built from a string/bytes, this can be set
+ file_bytes = None
+ # encoding of python source file, so we can get unicode out of it (python2
+ # only)
+ file_encoding = None
+ # the module name
+ name = None
+ # boolean for astroid built from source (i.e. ast)
+ pure_python = None
+ # boolean for package module
+ package = None
+ # dictionary of globals with name as key and node defining the global
+ # as value
+ globals = None
+
+ # Future imports
+ future_imports = None
+
+ # names of python special attributes (handled by getattr impl.)
+ special_attributes = set(('__name__', '__doc__', '__file__', '__path__',
+ '__dict__'))
+ # names of module attributes available through the global scope
+ scope_attrs = set(('__name__', '__doc__', '__file__', '__path__'))
+
+ def __init__(self, name, doc, pure_python=True):
+ self.name = name
+ self.doc = doc
+ self.pure_python = pure_python
+ self.locals = self.globals = {}
+ self.body = []
+ self.future_imports = set()
+
+ def _get_stream(self):
+ if self.file_bytes is not None:
+ return BytesIO(self.file_bytes)
+ if self.file is not None:
+ stream = open(self.file, 'rb')
+ return stream
+ return None
+
+ @property
+ def file_stream(self):
+ warnings.warn("file_stream property is deprecated and "
+ "it is slated for removal in astroid 1.6."
+ "Use the new method 'stream' instead.",
+ PendingDeprecationWarning,
+ stacklevel=2)
+ return self._get_stream()
+
+ def stream(self):
+ """Get a stream to the underlying file or bytes."""
+ return self._get_stream()
+
+ def close(self):
+ """Close the underlying file streams."""
+ warnings.warn("close method is deprecated and it is "
+ "slated for removal in astroid 1.6, along "
+ "with 'file_stream' property. "
+ "Its behaviour is replaced by managing each "
+ "file stream returned by the 'stream' method.",
+ PendingDeprecationWarning,
+ stacklevel=2)
+
+ def block_range(self, lineno):
+ """return block line numbers.
+
+ start from the beginning whatever the given lineno
+ """
+ return self.fromlineno, self.tolineno
+
+ def scope_lookup(self, node, name, offset=0):
+ if name in self.scope_attrs and not name in self.locals:
+ try:
+ return self, self.getattr(name)
+ except NotFoundError:
+ return self, ()
+ return self._scope_lookup(node, name, offset)
+
+ def pytype(self):
+ return '%s.module' % BUILTINS
+
+ def display_type(self):
+ return 'Module'
+
+ def getattr(self, name, context=None, ignore_locals=False):
+ if name in self.special_attributes:
+ if name == '__file__':
+ return [cf(self.file)] + self.locals.get(name, [])
+ if name == '__path__' and self.package:
+ return [List()] + self.locals.get(name, [])
+ return std_special_attributes(self, name)
+ if not ignore_locals and name in self.locals:
+ return self.locals[name]
+ if self.package:
+ try:
+ return [self.import_module(name, relative_only=True)]
+ except AstroidBuildingException:
+ raise NotFoundError(name)
+ except SyntaxError:
+ raise NotFoundError(name)
+ except Exception:# XXX pylint tests never pass here; do we need it?
+ import traceback
+ traceback.print_exc()
+ raise NotFoundError(name)
+ getattr = remove_nodes(getattr, DelName)
+
+ def igetattr(self, name, context=None):
+ """inferred getattr"""
+ # set lookup name since this is necessary to infer on import nodes for
+ # instance
+ context = copy_context(context)
+ context.lookupname = name
+ try:
+ return _infer_stmts(self.getattr(name, context), context, frame=self)
+ except NotFoundError:
+ raise InferenceError(name)
+
+ def fully_defined(self):
+ """return True if this module has been built from a .py file
+ and so contains a complete representation including the code
+ """
+ return self.file is not None and self.file.endswith('.py')
+
+ def statement(self):
+ """return the first parent node marked as statement node
+ consider a module as a statement...
+ """
+ return self
+
+ def previous_sibling(self):
+ """module has no sibling"""
+ return
+
+ def next_sibling(self):
+ """module has no sibling"""
+ return
+
+ if sys.version_info < (2, 8):
+ @cachedproperty
+ def _absolute_import_activated(self):
+ for stmt in self.locals.get('absolute_import', ()):
+ if isinstance(stmt, From) and stmt.modname == '__future__':
+ return True
+ return False
+ else:
+ _absolute_import_activated = True
+
+ def absolute_import_activated(self):
+ return self._absolute_import_activated
+
+ def import_module(self, modname, relative_only=False, level=None):
+ """import the given module considering self as context"""
+ if relative_only and level is None:
+ level = 0
+ absmodname = self.relative_to_absolute_name(modname, level)
+ try:
+ return MANAGER.ast_from_module_name(absmodname)
+ except AstroidBuildingException:
+ # we only want to import a sub module or package of this module,
+ # skip here
+ if relative_only:
+ raise
+ return MANAGER.ast_from_module_name(modname)
+
+ def relative_to_absolute_name(self, modname, level):
+ """return the absolute module name for a relative import.
+
+ The relative import can be implicit or explicit.
+ """
+ # XXX this returns non sens when called on an absolute import
+ # like 'pylint.checkers.astroid.utils'
+ # XXX doesn't return absolute name if self.name isn't absolute name
+ if self.absolute_import_activated() and level is None:
+ return modname
+ if level:
+ if self.package:
+ level = level - 1
+ package_name = self.name.rsplit('.', level)[0]
+ elif self.package:
+ package_name = self.name
+ else:
+ package_name = self.name.rsplit('.', 1)[0]
+ if package_name:
+ if not modname:
+ return package_name
+ return '%s.%s' % (package_name, modname)
+ return modname
+
+
+ def wildcard_import_names(self):
+ """return the list of imported names when this module is 'wildcard
+ imported'
+
+ It doesn't include the '__builtins__' name which is added by the
+ current CPython implementation of wildcard imports.
+ """
+ # take advantage of a living module if it exists
+ try:
+ living = sys.modules[self.name]
+ except KeyError:
+ pass
+ else:
+ try:
+ return living.__all__
+ except AttributeError:
+ return [name for name in living.__dict__.keys()
+ if not name.startswith('_')]
+ # else lookup the astroid
+ #
+ # We separate the different steps of lookup in try/excepts
+ # to avoid catching too many Exceptions
+ default = [name for name in self.keys() if not name.startswith('_')]
+ try:
+ all = self['__all__']
+ except KeyError:
+ return default
+ try:
+ explicit = next(all.assigned_stmts())
+ except InferenceError:
+ return default
+ except AttributeError:
+ # not an assignment node
+ # XXX infer?
+ return default
+
+ # Try our best to detect the exported name.
+ infered = []
+ try:
+ explicit = next(explicit.infer())
+ except InferenceError:
+ return default
+ if not isinstance(explicit, (Tuple, List)):
+ return default
+
+ str_const = lambda node: (isinstance(node, Const) and
+ isinstance(node.value, six.string_types))
+ for node in explicit.elts:
+ if str_const(node):
+ infered.append(node.value)
+ else:
+ try:
+ infered_node = next(node.infer())
+ except InferenceError:
+ continue
+ if str_const(infered_node):
+ infered.append(infered_node.value)
+ return infered
+
+
+
+class ComprehensionScope(LocalsDictNodeNG):
+ def frame(self):
+ return self.parent.frame()
+
+ scope_lookup = LocalsDictNodeNG._scope_lookup
+
+
+class GenExpr(ComprehensionScope):
+ _astroid_fields = ('elt', 'generators')
+
+ def __init__(self):
+ self.locals = {}
+ self.elt = None
+ self.generators = []
+
+
+class DictComp(ComprehensionScope):
+ _astroid_fields = ('key', 'value', 'generators')
+
+ def __init__(self):
+ self.locals = {}
+ self.key = None
+ self.value = None
+ self.generators = []
+
+
+class SetComp(ComprehensionScope):
+ _astroid_fields = ('elt', 'generators')
+
+ def __init__(self):
+ self.locals = {}
+ self.elt = None
+ self.generators = []
+
+
+class _ListComp(NodeNG):
+ """class representing a ListComp node"""
+ _astroid_fields = ('elt', 'generators')
+ elt = None
+ generators = None
+
+if sys.version_info >= (3, 0):
+ class ListComp(_ListComp, ComprehensionScope):
+ """class representing a ListComp node"""
+ def __init__(self):
+ self.locals = {}
+else:
+ class ListComp(_ListComp):
+ """class representing a ListComp node"""
+
+# Function ###################################################################
+
+def _infer_decorator_callchain(node):
+ """Detect decorator call chaining and see if the end result is a
+ static or a classmethod.
+ """
+ if not isinstance(node, Function):
+ return
+ if not node.parent:
+ return
+ try:
+ # TODO: We don't handle multiple inference results right now,
+ # because there's no flow to reason when the return
+ # is what we are looking for, a static or a class method.
+ result = next(node.infer_call_result(node.parent))
+ except (StopIteration, InferenceError):
+ return
+ if isinstance(result, Instance):
+ result = result._proxied
+ if isinstance(result, Class):
+ if result.is_subtype_of('%s.classmethod' % BUILTINS):
+ return 'classmethod'
+ if result.is_subtype_of('%s.staticmethod' % BUILTINS):
+ return 'staticmethod'
+
+
+def _function_type(self):
+ """
+ Function type, possible values are:
+ method, function, staticmethod, classmethod.
+ """
+ # Can't infer that this node is decorated
+ # with a subclass of `classmethod` where `type` is first set,
+ # so do it here.
+ if self.decorators:
+ for node in self.decorators.nodes:
+ if isinstance(node, CallFunc):
+ # Handle the following case:
+ # @some_decorator(arg1, arg2)
+ # def func(...)
+ #
+ try:
+ current = next(node.func.infer())
+ except InferenceError:
+ continue
+ _type = _infer_decorator_callchain(current)
+ if _type is not None:
+ return _type
+
+ try:
+ for infered in node.infer():
+ # Check to see if this returns a static or a class method.
+ _type = _infer_decorator_callchain(infered)
+ if _type is not None:
+ return _type
+
+ if not isinstance(infered, Class):
+ continue
+ for ancestor in infered.ancestors():
+ if not isinstance(ancestor, Class):
+ continue
+ if ancestor.is_subtype_of('%s.classmethod' % BUILTINS):
+ return 'classmethod'
+ elif ancestor.is_subtype_of('%s.staticmethod' % BUILTINS):
+ return 'staticmethod'
+ except InferenceError:
+ pass
+ return self._type
+
+
+class Lambda(LocalsDictNodeNG, FilterStmtsMixin):
+ _astroid_fields = ('args', 'body',)
+ name = ''
+
+ # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod'
+ type = 'function'
+
+ def __init__(self):
+ self.locals = {}
+ self.args = []
+ self.body = []
+
+ def pytype(self):
+ if 'method' in self.type:
+ return '%s.instancemethod' % BUILTINS
+ return '%s.function' % BUILTINS
+
+ def display_type(self):
+ if 'method' in self.type:
+ return 'Method'
+ return 'Function'
+
+ def callable(self):
+ return True
+
+ def argnames(self):
+ """return a list of argument names"""
+ if self.args.args: # maybe None with builtin functions
+ names = _rec_get_names(self.args.args)
+ else:
+ names = []
+ if self.args.vararg:
+ names.append(self.args.vararg)
+ if self.args.kwarg:
+ names.append(self.args.kwarg)
+ return names
+
+ def infer_call_result(self, caller, context=None):
+ """infer what a function is returning when called"""
+ return self.body.infer(context)
+
+ def scope_lookup(self, node, name, offset=0):
+ if node in self.args.defaults or node in self.args.kw_defaults:
+ frame = self.parent.frame()
+ # line offset to avoid that def func(f=func) resolve the default
+ # value to the defined function
+ offset = -1
+ else:
+ # check this is not used in function decorators
+ frame = self
+ return frame._scope_lookup(node, name, offset)
+
+
+class Function(Statement, Lambda):
+ if PY3K:
+ _astroid_fields = ('decorators', 'args', 'body', 'returns')
+ returns = None
+ else:
+ _astroid_fields = ('decorators', 'args', 'body')
+
+ special_attributes = set(('__name__', '__doc__', '__dict__'))
+ is_function = True
+ # attributes below are set by the builder module or by raw factories
+ blockstart_tolineno = None
+ decorators = None
+ _type = "function"
+ type = cachedproperty(_function_type)
+
+ def __init__(self, name, doc):
+ self.locals = {}
+ self.args = []
+ self.body = []
+ self.name = name
+ self.doc = doc
+ self.extra_decorators = []
+ self.instance_attrs = {}
+
+ @cachedproperty
+ def fromlineno(self):
+ # lineno is the line number of the first decorator, we want the def
+ # statement lineno
+ lineno = self.lineno
+ if self.decorators is not None:
+ lineno += sum(node.tolineno - node.lineno + 1
+ for node in self.decorators.nodes)
+
+ return lineno
+
+ @cachedproperty
+ def blockstart_tolineno(self):
+ return self.args.tolineno
+
+ def block_range(self, lineno):
+ """return block line numbers.
+
+ start from the "def" position whatever the given lineno
+ """
+ return self.fromlineno, self.tolineno
+
+ def getattr(self, name, context=None):
+ """this method doesn't look in the instance_attrs dictionary since it's
+ done by an Instance proxy at inference time.
+ """
+ if name == '__module__':
+ return [cf(self.root().qname())]
+ if name in self.instance_attrs:
+ return self.instance_attrs[name]
+ return std_special_attributes(self, name, False)
+
+ def is_method(self):
+ """return true if the function node should be considered as a method"""
+ # check we are defined in a Class, because this is usually expected
+ # (e.g. pylint...) when is_method() return True
+ return self.type != 'function' and isinstance(self.parent.frame(), Class)
+
+ def decoratornames(self):
+ """return a list of decorator qualified names"""
+ result = set()
+ decoratornodes = []
+ if self.decorators is not None:
+ decoratornodes += self.decorators.nodes
+ decoratornodes += self.extra_decorators
+ for decnode in decoratornodes:
+ for infnode in decnode.infer():
+ result.add(infnode.qname())
+ return result
+ decoratornames = cached(decoratornames)
+
+ def is_bound(self):
+ """return true if the function is bound to an Instance or a class"""
+ return self.type == 'classmethod'
+
+ def is_abstract(self, pass_is_abstract=True):
+ """Returns True if the method is abstract.
+
+ A method is considered abstract if
+ - the only statement is 'raise NotImplementedError', or
+ - the only statement is 'pass' and pass_is_abstract is True, or
+ - the method is annotated with abc.astractproperty/abc.abstractmethod
+ """
+ if self.decorators:
+ for node in self.decorators.nodes:
+ try:
+ infered = next(node.infer())
+ except InferenceError:
+ continue
+ if infered and infered.qname() in ('abc.abstractproperty',
+ 'abc.abstractmethod'):
+ return True
+
+ for child_node in self.body:
+ if isinstance(child_node, Raise):
+ if child_node.raises_not_implemented():
+ return True
+ if pass_is_abstract and isinstance(child_node, Pass):
+ return True
+ return False
+ # empty function is the same as function with a single "pass" statement
+ if pass_is_abstract:
+ return True
+
+ def is_generator(self):
+ """return true if this is a generator function"""
+ # XXX should be flagged, not computed
+ return next(self.nodes_of_class((Yield, YieldFrom),
+ skip_klass=(Function, Lambda)), False)
+
+ def infer_call_result(self, caller, context=None):
+ """infer what a function is returning when called"""
+ if self.is_generator():
+ yield Generator()
+ return
+ # This is really a gigantic hack to work around metaclass generators
+ # that return transient class-generating functions. Pylint's AST structure
+ # cannot handle a base class object that is only used for calling __new__,
+ # but does not contribute to the inheritance structure itself. We inject
+ # a fake class into the hierarchy here for several well-known metaclass
+ # generators, and filter it out later.
+ if (self.name == 'with_metaclass' and
+ len(self.args.args) == 1 and
+ self.args.vararg is not None):
+ metaclass = next(caller.args[0].infer(context))
+ if isinstance(metaclass, Class):
+ c = Class('temporary_class', None)
+ c.hide = True
+ c.parent = self
+ bases = [next(b.infer(context)) for b in caller.args[1:]]
+ c.bases = [base for base in bases if base != YES]
+ c._metaclass = metaclass
+ yield c
+ return
+ returns = self.nodes_of_class(Return, skip_klass=Function)
+ for returnnode in returns:
+ if returnnode.value is None:
+ yield Const(None)
+ else:
+ try:
+ for infered in returnnode.value.infer(context):
+ yield infered
+ except InferenceError:
+ yield YES
+
+
+def _rec_get_names(args, names=None):
+ """return a list of all argument names"""
+ if names is None:
+ names = []
+ for arg in args:
+ if isinstance(arg, Tuple):
+ _rec_get_names(arg.elts, names)
+ else:
+ names.append(arg.name)
+ return names
+
+
+# Class ######################################################################
+
+
+def _is_metaclass(klass, seen=None):
+ """ Return if the given class can be
+ used as a metaclass.
+ """
+ if klass.name == 'type':
+ return True
+ if seen is None:
+ seen = set()
+ for base in klass.bases:
+ try:
+ for baseobj in base.infer():
+ if baseobj in seen:
+ continue
+ else:
+ seen.add(baseobj)
+ if isinstance(baseobj, Instance):
+ # not abstract
+ return False
+ if baseobj is YES:
+ continue
+ if baseobj is klass:
+ continue
+ if not isinstance(baseobj, Class):
+ continue
+ if baseobj._type == 'metaclass':
+ return True
+ if _is_metaclass(baseobj, seen):
+ return True
+ except InferenceError:
+ continue
+ return False
+
+
+def _class_type(klass, ancestors=None):
+ """return a Class node type to differ metaclass, interface and exception
+ from 'regular' classes
+ """
+ # XXX we have to store ancestors in case we have a ancestor loop
+ if klass._type is not None:
+ return klass._type
+ if _is_metaclass(klass):
+ klass._type = 'metaclass'
+ elif klass.name.endswith('Interface'):
+ klass._type = 'interface'
+ elif klass.name.endswith('Exception'):
+ klass._type = 'exception'
+ else:
+ if ancestors is None:
+ ancestors = set()
+ if klass in ancestors:
+ # XXX we are in loop ancestors, and have found no type
+ klass._type = 'class'
+ return 'class'
+ ancestors.add(klass)
+ for base in klass.ancestors(recurs=False):
+ name = _class_type(base, ancestors)
+ if name != 'class':
+ if name == 'metaclass' and not _is_metaclass(klass):
+ # don't propagate it if the current class
+ # can't be a metaclass
+ continue
+ klass._type = base.type
+ break
+ if klass._type is None:
+ klass._type = 'class'
+ return klass._type
+
+def _iface_hdlr(iface_node):
+ """a handler function used by interfaces to handle suspicious
+ interface nodes
+ """
+ return True
+
+
+class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
+
+ # some of the attributes below are set by the builder module or
+ # by a raw factories
+
+ # a dictionary of class instances attributes
+ _astroid_fields = ('decorators', 'bases', 'body') # name
+
+ decorators = None
+ special_attributes = set(('__name__', '__doc__', '__dict__', '__module__',
+ '__bases__', '__mro__', '__subclasses__'))
+ blockstart_tolineno = None
+
+ _type = None
+ _metaclass_hack = False
+ hide = False
+ type = property(_class_type,
+ doc="class'type, possible values are 'class' | "
+ "'metaclass' | 'interface' | 'exception'")
+
+ def __init__(self, name, doc):
+ self.instance_attrs = {}
+ self.locals = {}
+ self.bases = []
+ self.body = []
+ self.name = name
+ self.doc = doc
+
+ def _newstyle_impl(self, context=None):
+ if context is None:
+ context = InferenceContext()
+ if self._newstyle is not None:
+ return self._newstyle
+ for base in self.ancestors(recurs=False, context=context):
+ if base._newstyle_impl(context):
+ self._newstyle = True
+ break
+ klass = self._explicit_metaclass()
+ # could be any callable, we'd need to infer the result of klass(name,
+ # bases, dict). punt if it's not a class node.
+ if klass is not None and isinstance(klass, Class):
+ self._newstyle = klass._newstyle_impl(context)
+ if self._newstyle is None:
+ self._newstyle = False
+ return self._newstyle
+
+ _newstyle = None
+ newstyle = property(_newstyle_impl,
+ doc="boolean indicating if it's a new style class"
+ "or not")
+
+ @cachedproperty
+ def blockstart_tolineno(self):
+ if self.bases:
+ return self.bases[-1].tolineno
+ else:
+ return self.fromlineno
+
+ def block_range(self, lineno):
+ """return block line numbers.
+
+ start from the "class" position whatever the given lineno
+ """
+ return self.fromlineno, self.tolineno
+
+ def pytype(self):
+ if self.newstyle:
+ return '%s.type' % BUILTINS
+ return '%s.classobj' % BUILTINS
+
+ def display_type(self):
+ return 'Class'
+
+ def callable(self):
+ return True
+
+ def is_subtype_of(self, type_name, context=None):
+ if self.qname() == type_name:
+ return True
+ for anc in self.ancestors(context=context):
+ if anc.qname() == type_name:
+ return True
+
+ def infer_call_result(self, caller, context=None):
+ """infer what a class is returning when called"""
+ if self.is_subtype_of('%s.type' % (BUILTINS,), context) and len(caller.args) == 3:
+ name_node = next(caller.args[0].infer(context))
+ if (isinstance(name_node, Const) and
+ isinstance(name_node.value, six.string_types)):
+ name = name_node.value
+ else:
+ yield YES
+ return
+ result = Class(name, None)
+ bases = next(caller.args[1].infer(context))
+ if isinstance(bases, (Tuple, List)):
+ result.bases = bases.itered()
+ else:
+ # There is currently no AST node that can represent an 'unknown'
+ # node (YES is not an AST node), therefore we simply return YES here
+ # although we know at least the name of the class.
+ yield YES
+ return
+ result.parent = caller.parent
+ yield result
+ else:
+ yield Instance(self)
+
+ def scope_lookup(self, node, name, offset=0):
+ if any(node == base or base.parent_of(node)
+ for base in self.bases):
+ # Handle the case where we have either a name
+ # in the bases of a class, which exists before
+ # the actual definition or the case where we have
+ # a Getattr node, with that name.
+ #
+ # name = ...
+ # class A(name):
+ # def name(self): ...
+ #
+ # import name
+ # class A(name.Name):
+ # def name(self): ...
+
+ frame = self.parent.frame()
+ # line offset to avoid that class A(A) resolve the ancestor to
+ # the defined class
+ offset = -1
+ else:
+ frame = self
+ return frame._scope_lookup(node, name, offset)
+
+ # list of parent class as a list of string (i.e. names as they appear
+ # in the class definition) XXX bw compat
+ def basenames(self):
+ return [bnode.as_string() for bnode in self.bases]
+ basenames = property(basenames)
+
+ def ancestors(self, recurs=True, context=None):
+ """return an iterator on the node base classes in a prefixed
+ depth first order
+
+ :param recurs:
+ boolean indicating if it should recurse or return direct
+ ancestors only
+ """
+ # FIXME: should be possible to choose the resolution order
+ # FIXME: inference make infinite loops possible here
+ yielded = set([self])
+ if context is None:
+ context = InferenceContext()
+ if sys.version_info[0] >= 3:
+ if not self.bases and self.qname() != 'builtins.object':
+ yield builtin_lookup("object")[1][0]
+ return
+
+ for stmt in self.bases:
+ with context.restore_path():
+ try:
+ for baseobj in stmt.infer(context):
+ if not isinstance(baseobj, Class):
+ if isinstance(baseobj, Instance):
+ baseobj = baseobj._proxied
+ else:
+ # duh ?
+ continue
+ if not baseobj.hide:
+ if baseobj in yielded:
+ continue # cf xxx above
+ yielded.add(baseobj)
+ yield baseobj
+ if recurs:
+ for grandpa in baseobj.ancestors(recurs=True,
+ context=context):
+ if grandpa is self:
+ # This class is the ancestor of itself.
+ break
+ if grandpa in yielded:
+ continue # cf xxx above
+ yielded.add(grandpa)
+ yield grandpa
+ except InferenceError:
+ # XXX log error ?
+ continue
+
+ def local_attr_ancestors(self, name, context=None):
+ """return an iterator on astroid representation of parent classes
+ which have defined in their locals
+ """
+ for astroid in self.ancestors(context=context):
+ if name in astroid:
+ yield astroid
+
+ def instance_attr_ancestors(self, name, context=None):
+ """return an iterator on astroid representation of parent classes
+ which have defined in their instance attribute dictionary
+ """
+ for astroid in self.ancestors(context=context):
+ if name in astroid.instance_attrs:
+ yield astroid
+
+ def has_base(self, node):
+ return node in self.bases
+
+ def local_attr(self, name, context=None):
+ """return the list of assign node associated to name in this class
+ locals or in its parents
+
+ :raises `NotFoundError`:
+ if no attribute with this name has been find in this class or
+ its parent classes
+ """
+ try:
+ return self.locals[name]
+ except KeyError:
+ # get if from the first parent implementing it if any
+ for class_node in self.local_attr_ancestors(name, context):
+ return class_node.locals[name]
+ raise NotFoundError(name)
+ local_attr = remove_nodes(local_attr, DelAttr)
+
+ def instance_attr(self, name, context=None):
+ """return the astroid nodes associated to name in this class instance
+ attributes dictionary and in its parents
+
+ :raises `NotFoundError`:
+ if no attribute with this name has been find in this class or
+ its parent classes
+ """
+ # Return a copy, so we don't modify self.instance_attrs,
+ # which could lead to infinite loop.
+ values = list(self.instance_attrs.get(name, []))
+ # get all values from parents
+ for class_node in self.instance_attr_ancestors(name, context):
+ values += class_node.instance_attrs[name]
+ if not values:
+ raise NotFoundError(name)
+ return values
+ instance_attr = remove_nodes(instance_attr, DelAttr)
+
+ def instanciate_class(self):
+ """return Instance of Class node, else return self"""
+ return Instance(self)
+
+ def getattr(self, name, context=None):
+ """this method doesn't look in the instance_attrs dictionary since it's
+ done by an Instance proxy at inference time.
+
+ It may return a YES object if the attribute has not been actually
+ found but a __getattr__ or __getattribute__ method is defined
+ """
+ values = self.locals.get(name, [])
+ if name in self.special_attributes:
+ if name == '__module__':
+ return [cf(self.root().qname())] + values
+ # FIXME: do we really need the actual list of ancestors?
+ # returning [Tuple()] + values don't break any test
+ # this is ticket http://www.logilab.org/ticket/52785
+ # XXX need proper meta class handling + MRO implementation
+ if name == '__bases__' or (name == '__mro__' and self.newstyle):
+ node = Tuple()
+ node.items = self.ancestors(recurs=True, context=context)
+ return [node] + values
+ return std_special_attributes(self, name)
+ # don't modify the list in self.locals!
+ values = list(values)
+ for classnode in self.ancestors(recurs=True, context=context):
+ values += classnode.locals.get(name, [])
+ if not values:
+ raise NotFoundError(name)
+ return values
+
+ def igetattr(self, name, context=None):
+ """inferred getattr, need special treatment in class to handle
+ descriptors
+ """
+ # set lookup name since this is necessary to infer on import nodes for
+ # instance
+ context = copy_context(context)
+ context.lookupname = name
+ try:
+ for infered in _infer_stmts(self.getattr(name, context), context,
+ frame=self):
+ # yield YES object instead of descriptors when necessary
+ if not isinstance(infered, Const) and isinstance(infered, Instance):
+ try:
+ infered._proxied.getattr('__get__', context)
+ except NotFoundError:
+ yield infered
+ else:
+ yield YES
+ else:
+ yield function_to_method(infered, self)
+ except NotFoundError:
+ if not name.startswith('__') and self.has_dynamic_getattr(context):
+ # class handle some dynamic attributes, return a YES object
+ yield YES
+ else:
+ raise InferenceError(name)
+
+ def has_dynamic_getattr(self, context=None):
+ """return True if the class has a custom __getattr__ or
+ __getattribute__ method
+ """
+ # need to explicitly handle optparse.Values (setattr is not detected)
+ if self.name == 'Values' and self.root().name == 'optparse':
+ return True
+ try:
+ self.getattr('__getattr__', context)
+ return True
+ except NotFoundError:
+ #if self.newstyle: XXX cause an infinite recursion error
+ try:
+ getattribute = self.getattr('__getattribute__', context)[0]
+ if getattribute.root().name != BUILTINS:
+ # class has a custom __getattribute__ defined
+ return True
+ except NotFoundError:
+ pass
+ return False
+
+ def methods(self):
+ """return an iterator on all methods defined in the class and
+ its ancestors
+ """
+ done = {}
+ for astroid in chain(iter((self,)), self.ancestors()):
+ for meth in astroid.mymethods():
+ if meth.name in done:
+ continue
+ done[meth.name] = None
+ yield meth
+
+ def mymethods(self):
+ """return an iterator on all methods defined in the class"""
+ for member in self.values():
+ if isinstance(member, Function):
+ yield member
+
+ def interfaces(self, herited=True, handler_func=_iface_hdlr):
+ """return an iterator on interfaces implemented by the given
+ class node
+ """
+ # FIXME: what if __implements__ = (MyIFace, MyParent.__implements__)...
+ try:
+ implements = Instance(self).getattr('__implements__')[0]
+ except NotFoundError:
+ return
+ if not herited and not implements.frame() is self:
+ return
+ found = set()
+ missing = False
+ for iface in unpack_infer(implements):
+ if iface is YES:
+ missing = True
+ continue
+ if not iface in found and handler_func(iface):
+ found.add(iface)
+ yield iface
+ if missing:
+ raise InferenceError()
+
+ _metaclass = None
+ def _explicit_metaclass(self):
+ """ Return the explicit defined metaclass
+ for the current class.
+
+ An explicit defined metaclass is defined
+ either by passing the ``metaclass`` keyword argument
+ in the class definition line (Python 3) or (Python 2) by
+ having a ``__metaclass__`` class attribute, or if there are
+ no explicit bases but there is a global ``__metaclass__`` variable.
+ """
+ for base in self.bases:
+ try:
+ for baseobj in base.infer():
+ if isinstance(baseobj, Class) and baseobj.hide:
+ self._metaclass = baseobj._metaclass
+ self._metaclass_hack = True
+ break
+ except InferenceError:
+ pass
+
+ if self._metaclass:
+ # Expects this from Py3k TreeRebuilder
+ try:
+ return next(node for node in self._metaclass.infer()
+ if node is not YES)
+ except (InferenceError, StopIteration):
+ return None
+ if sys.version_info >= (3, ):
+ return None
+
+ if '__metaclass__' in self.locals:
+ assignment = self.locals['__metaclass__'][-1]
+ elif self.bases:
+ return None
+ elif '__metaclass__' in self.root().locals:
+ assignments = [ass for ass in self.root().locals['__metaclass__']
+ if ass.lineno < self.lineno]
+ if not assignments:
+ return None
+ assignment = assignments[-1]
+ else:
+ return None
+
+ try:
+ infered = next(assignment.infer())
+ except InferenceError:
+ return
+ if infered is YES: # don't expose this
+ return None
+ return infered
+
+ def metaclass(self):
+ """ Return the metaclass of this class.
+
+ If this class does not define explicitly a metaclass,
+ then the first defined metaclass in ancestors will be used
+ instead.
+ """
+ klass = self._explicit_metaclass()
+ if klass is None:
+ for parent in self.ancestors():
+ klass = parent.metaclass()
+ if klass is not None:
+ break
+ return klass
+
+ def has_metaclass_hack(self):
+ return self._metaclass_hack
+
+ def _islots(self):
+ """ Return an iterator with the inferred slots. """
+ if '__slots__' not in self.locals:
+ return
+ for slots in self.igetattr('__slots__'):
+ # check if __slots__ is a valid type
+ for meth in ITER_METHODS:
+ try:
+ slots.getattr(meth)
+ break
+ except NotFoundError:
+ continue
+ else:
+ continue
+
+ if isinstance(slots, Const):
+ # a string. Ignore the following checks,
+ # but yield the node, only if it has a value
+ if slots.value:
+ yield slots
+ continue
+ if not hasattr(slots, 'itered'):
+ # we can't obtain the values, maybe a .deque?
+ continue
+
+ if isinstance(slots, Dict):
+ values = [item[0] for item in slots.items]
+ else:
+ values = slots.itered()
+ if values is YES:
+ continue
+
+ for elt in values:
+ try:
+ for infered in elt.infer():
+ if infered is YES:
+ continue
+ if (not isinstance(infered, Const) or
+ not isinstance(infered.value,
+ six.string_types)):
+ continue
+ if not infered.value:
+ continue
+ yield infered
+ except InferenceError:
+ continue
+
+ # Cached, because inferring them all the time is expensive
+ @cached
+ def slots(self):
+ """Get all the slots for this node.
+
+ If the class doesn't define any slot, through `__slots__`
+ variable, then this function will return a None.
+ Also, it will return None in the case the slots weren't inferred.
+ Otherwise, it will return a list of slot names.
+ """
+ if not self.newstyle:
+ raise NotImplementedError(
+ "The concept of slots is undefined for old-style classes.")
+
+ slots = self._islots()
+ try:
+ first = next(slots)
+ except StopIteration:
+ # The class doesn't have a __slots__ definition.
+ return None
+ return [first] + list(slots)
+
+ def _inferred_bases(self, recurs=True, context=None):
+ # TODO(cpopa): really similar with .ancestors,
+ # but the difference is when one base is inferred,
+ # only the first object is wanted. That's because
+ # we aren't interested in superclasses, as in the following
+ # example:
+ #
+ # class SomeSuperClass(object): pass
+ # class SomeClass(SomeSuperClass): pass
+ # class Test(SomeClass): pass
+ #
+ # Inferring SomeClass from the Test's bases will give
+ # us both SomeClass and SomeSuperClass, but we are interested
+ # only in SomeClass.
+
+ if context is None:
+ context = InferenceContext()
+ if sys.version_info[0] >= 3:
+ if not self.bases and self.qname() != 'builtins.object':
+ yield builtin_lookup("object")[1][0]
+ return
+
+ for stmt in self.bases:
+ try:
+ baseobj = next(stmt.infer(context=context))
+ except InferenceError:
+ # XXX log error ?
+ continue
+ if isinstance(baseobj, Instance):
+ baseobj = baseobj._proxied
+ if not isinstance(baseobj, Class):
+ continue
+ if not baseobj.hide:
+ yield baseobj
+
+ def mro(self, context=None):
+ """Get the method resolution order, using C3 linearization.
+
+ It returns the list of ancestors sorted by the mro.
+ This will raise `NotImplementedError` for old-style classes, since
+ they don't have the concept of MRO.
+ """
+ if not self.newstyle:
+ raise NotImplementedError(
+ "Could not obtain mro for old-style classes.")
+
+ bases = list(self._inferred_bases(context=context))
+ unmerged_mro = ([[self]] +
+ [base.mro() for base in bases if base is not self] +
+ [bases])
+
+ _verify_duplicates_mro(unmerged_mro)
+ return _c3_merge(unmerged_mro)
diff -Nru astroid-1.0.1/astroid/tests/resources.py astroid-1.3.8/astroid/tests/resources.py
--- astroid-1.0.1/astroid/tests/resources.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/resources.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,72 @@
+# Copyright 2014 Google, Inc. All rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+import os
+import sys
+
+import pkg_resources
+
+from astroid import builder
+from astroid import MANAGER
+from astroid.bases import BUILTINS
+
+
+DATA_DIR = 'testdata/python{}/'.format(sys.version_info[0])
+
+def find(name):
+ return pkg_resources.resource_filename(
+ 'astroid.tests', os.path.normpath(os.path.join(DATA_DIR, name)))
+
+
+def build_file(path, modname=None):
+ return builder.AstroidBuilder().file_build(find(path), modname)
+
+
+class SysPathSetup(object):
+ def setUp(self):
+ sys.path.insert(0, find(''))
+
+ def tearDown(self):
+ del sys.path[0]
+ datadir = find('')
+ for key in list(sys.path_importer_cache):
+ if key.startswith(datadir):
+ del sys.path_importer_cache[key]
+
+
+class AstroidCacheSetupMixin(object):
+ """Mixin for handling the astroid cache problems.
+
+ When clearing the astroid cache, some tests fails due to
+ cache inconsistencies, where some objects had a different
+ builtins object referenced.
+ This saves the builtins module and makes sure to add it
+ back to the astroid_cache after the tests finishes.
+ The builtins module is special, since some of the
+ transforms for a couple of its objects (str, bytes etc)
+ are executed only once, so astroid_bootstrapping will be
+ useless for retrieving the original builtins module.
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ cls._builtins = MANAGER.astroid_cache.get(BUILTINS)
+
+ @classmethod
+ def tearDownClass(cls):
+ if cls._builtins:
+ MANAGER.astroid_cache[BUILTINS] = cls._builtins
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/absimp/__init__.py astroid-1.3.8/astroid/tests/testdata/python2/data/absimp/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/absimp/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/absimp/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,5 @@
+"""a package with absolute import activated
+"""
+
+from __future__ import absolute_import
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py astroid-1.3.8/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,3 @@
+"""a side package with nothing in it
+"""
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/absimp/string.py astroid-1.3.8/astroid/tests/testdata/python2/data/absimp/string.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/absimp/string.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/absimp/string.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,3 @@
+from __future__ import absolute_import, print_function
+import string
+print(string)
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/absimport.py astroid-1.3.8/astroid/tests/testdata/python2/data/absimport.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/absimport.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/absimport.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,3 @@
+from __future__ import absolute_import
+import email
+from email import message
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/all.py astroid-1.3.8/astroid/tests/testdata/python2/data/all.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/all.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/all.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,9 @@
+
+name = 'a'
+_bla = 2
+other = 'o'
+class Aaa: pass
+
+def func(): print 'yo'
+
+__all__ = 'Aaa', '_bla', 'name'
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/appl/__init__.py astroid-1.3.8/astroid/tests/testdata/python2/data/appl/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/appl/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/appl/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,3 @@
+"""
+Init
+"""
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/appl/myConnection.py astroid-1.3.8/astroid/tests/testdata/python2/data/appl/myConnection.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/appl/myConnection.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/appl/myConnection.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,11 @@
+from data import SSL1
+class MyConnection(SSL1.Connection):
+
+ """An SSL connection."""
+
+ def __init__(self, dummy):
+ print 'MyConnection init'
+
+if __name__ == '__main__':
+ myConnection = MyConnection(' ')
+ raw_input('Press Enter to continue...')
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/clientmodule_test.py astroid-1.3.8/astroid/tests/testdata/python2/data/clientmodule_test.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/clientmodule_test.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/clientmodule_test.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,32 @@
+""" docstring for file clientmodule.py """
+from data.suppliermodule_test import Interface as IFace, DoNothing
+
+class Toto: pass
+
+class Ancestor:
+ """ Ancestor method """
+ __implements__ = (IFace,)
+
+ def __init__(self, value):
+ local_variable = 0
+ self.attr = 'this method shouldn\'t have a docstring'
+ self.__value = value
+
+ def get_value(self):
+ """ nice docstring ;-) """
+ return self.__value
+
+ def set_value(self, value):
+ self.__value = value
+ return 'this method shouldn\'t have a docstring'
+
+class Specialization(Ancestor):
+ TYPE = 'final class'
+ top = 'class'
+
+ def __init__(self, value, _id):
+ Ancestor.__init__(self, value)
+ self._id = _id
+ self.relation = DoNothing()
+ self.toto = Toto()
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/descriptor_crash.py astroid-1.3.8/astroid/tests/testdata/python2/data/descriptor_crash.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/descriptor_crash.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/descriptor_crash.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,11 @@
+
+import urllib
+
+class Page(object):
+ _urlOpen = staticmethod(urllib.urlopen)
+
+ def getPage(self, url):
+ handle = self._urlOpen(url)
+ data = handle.read()
+ handle.close()
+ return data
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/email.py astroid-1.3.8/astroid/tests/testdata/python2/data/email.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/email.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/email.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+"""fake email module to test absolute import doesn't grab this one"""
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/format.py astroid-1.3.8/astroid/tests/testdata/python2/data/format.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/format.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/format.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,34 @@
+"""A multiline string
+"""
+
+function('aeozrijz\
+earzer', hop)
+# XXX write test
+x = [i for i in range(5)
+ if i % 4]
+
+fonction(1,
+ 2,
+ 3,
+ 4)
+
+def definition(a,
+ b,
+ c):
+ return a + b + c
+
+class debile(dict,
+ object):
+ pass
+
+if aaaa: pass
+else:
+ aaaa,bbbb = 1,2
+ aaaa,bbbb = bbbb,aaaa
+# XXX write test
+hop = \
+ aaaa
+
+
+__revision__.lower();
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/__init__.py astroid-1.3.8/astroid/tests/testdata/python2/data/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+__revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $"
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/joined_strings.py astroid-1.3.8/astroid/tests/testdata/python2/data/joined_strings.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/joined_strings.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/joined_strings.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,1051 @@
+x = ('R0lGODlhigJnAef/AAABAAEEAAkCAAMGAg0GBAYJBQoMCBMODQ4QDRITEBkS'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7')
\ No newline at end of file
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/lmfp/foo.py astroid-1.3.8/astroid/tests/testdata/python2/data/lmfp/foo.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/lmfp/foo.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/lmfp/foo.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,6 @@
+import sys
+if not getattr(sys, 'bar', None):
+ sys.just_once = []
+# there used to be two numbers here because
+# of a load_module_from_path bug
+sys.just_once.append(42)
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/lmfp/__init__.py astroid-1.3.8/astroid/tests/testdata/python2/data/lmfp/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/lmfp/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/lmfp/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,2 @@
+# force a "direct" python import
+from . import foo
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/module1abs/core.py astroid-1.3.8/astroid/tests/testdata/python2/data/module1abs/core.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/module1abs/core.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/module1abs/core.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+import sys
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/module1abs/__init__.py astroid-1.3.8/astroid/tests/testdata/python2/data/module1abs/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/module1abs/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/module1abs/__init__.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,4 @@
+from __future__ import absolute_import
+from . import core
+from .core import *
+print sys.version
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/module2.py astroid-1.3.8/astroid/tests/testdata/python2/data/module2.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/module2.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/module2.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,143 @@
+from data.module import YO, YOUPI
+import data
+
+
+class Specialization(YOUPI, YO):
+ pass
+
+
+
+class Metaclass(type):
+ pass
+
+
+
+class Interface:
+ pass
+
+
+
+class MyIFace(Interface):
+ pass
+
+
+
+class AnotherIFace(Interface):
+ pass
+
+
+
+class MyException(Exception):
+ pass
+
+
+
+class MyError(MyException):
+ pass
+
+
+
+class AbstractClass(object):
+
+ def to_override(self, whatever):
+ raise NotImplementedError()
+
+ def return_something(self, param):
+ if param:
+ return 'toto'
+ return
+
+
+
+class Concrete0:
+ __implements__ = MyIFace
+
+
+
+class Concrete1:
+ __implements__ = (MyIFace, AnotherIFace)
+
+
+
+class Concrete2:
+ __implements__ = (MyIFace, AnotherIFace)
+
+
+
+class Concrete23(Concrete1):
+ pass
+
+del YO.member
+del YO
+[SYN1, SYN2] = (Concrete0, Concrete1)
+assert `1`
+b = (1) | (((2) & (3)) ^ (8))
+bb = ((1) | (two)) | (6)
+ccc = ((one) & (two)) & (three)
+dddd = ((x) ^ (o)) ^ (r)
+exec 'c = 3'
+exec 'c = 3' in {}, {}
+
+def raise_string(a=2, *args, **kwargs):
+ raise Exception, 'yo'
+ yield 'coucou'
+ yield
+a = (b) + (2)
+c = (b) * (2)
+c = (b) / (2)
+c = (b) // (2)
+c = (b) - (2)
+c = (b) % (2)
+c = (b) ** (2)
+c = (b) << (2)
+c = (b) >> (2)
+c = ~b
+c = not b
+d = [c]
+e = d[:]
+e = d[a:b:c]
+raise_string(*args, **kwargs)
+print >> stream, 'bonjour'
+print >> stream, 'salut',
+
+def make_class(any, base=data.module.YO, *args, **kwargs):
+ """check base is correctly resolved to Concrete0"""
+
+
+ class Aaaa(base):
+ """dynamic class"""
+
+
+ return Aaaa
+from os.path import abspath
+import os as myos
+
+
+class A:
+ pass
+
+
+
+class A(A):
+ pass
+
+
+def generator():
+ """A generator."""
+ yield
+
+def not_a_generator():
+ """A function that contains generator, but is not one."""
+
+ def generator():
+ yield
+ genl = lambda : (yield)
+
+def with_metaclass(meta, *bases):
+ return meta('NewBase', bases, {})
+
+
+class NotMetaclass(with_metaclass(Metaclass)):
+ pass
+
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/module.py astroid-1.3.8/astroid/tests/testdata/python2/data/module.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/module.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/module.py 2015-08-02 19:35:46.000000000 +0000
@@ -0,0 +1,89 @@
+"""test module for astroid
+"""
+
+__revision__ = '$Id: module.py,v 1.2 2005-11-02 11:56:54 syt Exp $'
+from logilab.common.shellutils import ProgressBar as pb
+from astroid import modutils
+from astroid.utils import *
+import os.path
+MY_DICT = {}
+
+def global_access(key, val):
+ """function test"""
+ local = 1
+ MY_DICT[key] = val
+ for i in val:
+ if i:
+ del MY_DICT[i]
+ continue
+ else:
+ break
+ else:
+ print '!!!'
+
+
+class YO:
+ """hehe"""
+ a = 1
+
+ def __init__(self):
+ try:
+ self.yo = 1
+ except ValueError, ex:
+ pass
+ except (NameError, TypeError):
+ raise XXXError()
+ except:
+ raise
+
+
+
+class YOUPI(YO):
+ class_attr = None
+
+ def __init__(self):
+ self.member = None
+
+ def method(self):
+ """method test"""
+ global MY_DICT
+ try:
+ MY_DICT = {}
+ local = None
+ autre = [a for (a, b) in MY_DICT if b]
+ if b in autre:
+ print 'yo',
+ else:
+ if a in autre:
+ print 'hehe'
+ global_access(local, val=autre)
+ finally:
+ return local
+
+ def static_method():
+ """static method test"""
+ assert MY_DICT, '???'
+ static_method = staticmethod(static_method)
+
+ def class_method(cls):
+ """class method test"""
+ exec a in b
+ class_method = classmethod(class_method)
+
+
+def four_args(a, b, c, d):
+ """four arguments (was nested_args)"""
+ print a, b, c, d
+ while 1:
+ if a:
+ break
+ a += +1
+ else:
+ b += -2
+ if c:
+ d = ((a) and (b)) or (c)
+ else:
+ c = ((a) and (b)) or (d)
+ map(lambda x, y: (y, x), a)
+redirect = four_args
+
Binary files /tmp/tehDuGV_EZ/astroid-1.0.1/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg and /tmp/WwBlO9ZnuM/astroid-1.3.8/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg differ
Binary files /tmp/tehDuGV_EZ/astroid-1.0.1/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip and /tmp/WwBlO9ZnuM/astroid-1.3.8/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip differ
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/noendingnewline.py astroid-1.3.8/astroid/tests/testdata/python2/data/noendingnewline.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/noendingnewline.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/noendingnewline.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,36 @@
+import unittest
+
+
+class TestCase(unittest.TestCase):
+
+ def setUp(self):
+ unittest.TestCase.setUp(self)
+
+
+ def tearDown(self):
+ unittest.TestCase.tearDown(self)
+
+ def testIt(self):
+ self.a = 10
+ self.xxx()
+
+
+ def xxx(self):
+ if False:
+ pass
+ print 'a'
+
+ if False:
+ pass
+ pass
+
+ if False:
+ pass
+ print 'rara'
+
+
+if __name__ == '__main__':
+ print 'test2'
+ unittest.main()
+
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/nonregr.py astroid-1.3.8/astroid/tests/testdata/python2/data/nonregr.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/nonregr.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/nonregr.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,57 @@
+from __future__ import generators
+
+try:
+ enumerate = enumerate
+except NameError:
+
+ def enumerate(iterable):
+ """emulates the python2.3 enumerate() function"""
+ i = 0
+ for val in iterable:
+ yield i, val
+ i += 1
+
+def toto(value):
+ for k, v in value:
+ print v.get('yo')
+
+
+import imp
+fp, mpath, desc = imp.find_module('optparse',a)
+s_opt = imp.load_module('std_optparse', fp, mpath, desc)
+
+class OptionParser(s_opt.OptionParser):
+
+ def parse_args(self, args=None, values=None, real_optparse=False):
+ if real_optparse:
+ pass
+## return super(OptionParser, self).parse_args()
+ else:
+ import optcomp
+ optcomp.completion(self)
+
+
+class Aaa(object):
+ """docstring"""
+ def __init__(self):
+ self.__setattr__('a','b')
+ pass
+
+ def one_public(self):
+ """docstring"""
+ pass
+
+ def another_public(self):
+ """docstring"""
+ pass
+
+class Ccc(Aaa):
+ """docstring"""
+
+ class Ddd(Aaa):
+ """docstring"""
+ pass
+
+ class Eee(Ddd):
+ """docstring"""
+ pass
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/notall.py astroid-1.3.8/astroid/tests/testdata/python2/data/notall.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/notall.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/notall.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,8 @@
+
+name = 'a'
+_bla = 2
+other = 'o'
+class Aaa: pass
+
+def func(): print 'yo'
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/package/absimport.py astroid-1.3.8/astroid/tests/testdata/python2/data/package/absimport.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/package/absimport.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/package/absimport.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,6 @@
+from __future__ import absolute_import, print_function
+import import_package_subpackage_module # fail
+print(import_package_subpackage_module)
+
+from . import hello as hola
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/package/hello.py astroid-1.3.8/astroid/tests/testdata/python2/data/package/hello.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/package/hello.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/package/hello.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,2 @@
+"""hello module"""
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py astroid-1.3.8/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,49 @@
+# pylint: disable-msg=I0011,C0301,W0611
+"""I found some of my scripts trigger off an AttributeError in pylint
+0.8.1 (with common 0.12.0 and astroid 0.13.1).
+
+Traceback (most recent call last):
+ File "/usr/bin/pylint", line 4, in ?
+ lint.Run(sys.argv[1:])
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__
+ linter.check(args)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check
+ self.check_file(filepath, modname, checkers)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file
+ astroid = self._check_file(filepath, modname, checkers)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file
+ self.check_astroid_module(astroid, checkers)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module
+ self.astroid_events(astroid, [checker for checker in checkers
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
+ self.astroid_events(child, checkers, _reversed_checkers)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
+ self.astroid_events(child, checkers, _reversed_checkers)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events
+ checker.visit(astroid)
+ File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit
+ method(node)
+ File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import
+ self._check_module_attrs(node, module, name_parts[1:])
+ File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs
+ self.add_message('E0611', args=(name, module.name),
+AttributeError: Import instance has no attribute 'name'
+
+
+You can reproduce it by:
+(1) create package structure like the following:
+
+package/
+ __init__.py
+ subpackage/
+ __init__.py
+ module.py
+
+(2) in package/__init__.py write:
+
+import subpackage
+
+(3) run pylint with a script importing package.subpackage.module.
+"""
+__revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 15:59:32 syt Exp $'
+import package.subpackage.module
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/package/__init__.py astroid-1.3.8/astroid/tests/testdata/python2/data/package/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/package/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/package/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,4 @@
+"""package's __init__ file"""
+
+
+from . import subpackage
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/package/subpackage/__init__.py astroid-1.3.8/astroid/tests/testdata/python2/data/package/subpackage/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/package/subpackage/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/package/subpackage/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+"""package.subpackage"""
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/package/subpackage/module.py astroid-1.3.8/astroid/tests/testdata/python2/data/package/subpackage/module.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/package/subpackage/module.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/package/subpackage/module.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+"""package.subpackage.module"""
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/recursion.py astroid-1.3.8/astroid/tests/testdata/python2/data/recursion.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/recursion.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/recursion.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,3 @@
+""" For issue #25 """
+class Base(object):
+ pass
\ No newline at end of file
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/SSL1/Connection1.py astroid-1.3.8/astroid/tests/testdata/python2/data/SSL1/Connection1.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/SSL1/Connection1.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/SSL1/Connection1.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,14 @@
+"""M2Crypto.SSL.Connection
+
+Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved."""
+
+RCS_id='$Id: Connection1.py,v 1.1 2005-06-13 20:55:22 syt Exp $'
+
+#Some code deleted here
+
+class Connection:
+
+ """An SSL connection."""
+
+ def __init__(self, ctx, sock=None):
+ print 'init Connection'
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/SSL1/__init__.py astroid-1.3.8/astroid/tests/testdata/python2/data/SSL1/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/SSL1/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/SSL1/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+from Connection1 import Connection
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/suppliermodule_test.py astroid-1.3.8/astroid/tests/testdata/python2/data/suppliermodule_test.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/suppliermodule_test.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/suppliermodule_test.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,13 @@
+""" file suppliermodule.py """
+
+class NotImplemented(Exception):
+ pass
+
+class Interface:
+ def get_value(self):
+ raise NotImplemented()
+
+ def set_value(self, value):
+ raise NotImplemented()
+
+class DoNothing : pass
diff -Nru astroid-1.0.1/astroid/tests/testdata/python2/data/unicode_package/__init__.py astroid-1.3.8/astroid/tests/testdata/python2/data/unicode_package/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python2/data/unicode_package/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python2/data/unicode_package/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+x = "șțîâ"
\ No newline at end of file
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/absimp/__init__.py astroid-1.3.8/astroid/tests/testdata/python3/data/absimp/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/absimp/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/absimp/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,5 @@
+"""a package with absolute import activated
+"""
+
+from __future__ import absolute_import
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py astroid-1.3.8/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,3 @@
+"""a side package with nothing in it
+"""
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/absimp/string.py astroid-1.3.8/astroid/tests/testdata/python3/data/absimp/string.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/absimp/string.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/absimp/string.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,3 @@
+from __future__ import absolute_import, print_function
+import string
+print(string)
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/absimport.py astroid-1.3.8/astroid/tests/testdata/python3/data/absimport.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/absimport.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/absimport.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,3 @@
+
+import email
+from email import message
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/all.py astroid-1.3.8/astroid/tests/testdata/python3/data/all.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/all.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/all.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,9 @@
+
+name = 'a'
+_bla = 2
+other = 'o'
+class Aaa: pass
+
+def func(): print('yo')
+
+__all__ = 'Aaa', '_bla', 'name'
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/appl/__init__.py astroid-1.3.8/astroid/tests/testdata/python3/data/appl/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/appl/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/appl/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,3 @@
+"""
+Init
+"""
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/appl/myConnection.py astroid-1.3.8/astroid/tests/testdata/python3/data/appl/myConnection.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/appl/myConnection.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/appl/myConnection.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,11 @@
+from data import SSL1
+class MyConnection(SSL1.Connection):
+
+ """An SSL connection."""
+
+ def __init__(self, dummy):
+ print('MyConnection init')
+
+if __name__ == '__main__':
+ myConnection = MyConnection(' ')
+ input('Press Enter to continue...')
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/clientmodule_test.py astroid-1.3.8/astroid/tests/testdata/python3/data/clientmodule_test.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/clientmodule_test.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/clientmodule_test.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,32 @@
+""" docstring for file clientmodule.py """
+from data.suppliermodule_test import Interface as IFace, DoNothing
+
+class Toto: pass
+
+class Ancestor:
+ """ Ancestor method """
+ __implements__ = (IFace,)
+
+ def __init__(self, value):
+ local_variable = 0
+ self.attr = 'this method shouldn\'t have a docstring'
+ self.__value = value
+
+ def get_value(self):
+ """ nice docstring ;-) """
+ return self.__value
+
+ def set_value(self, value):
+ self.__value = value
+ return 'this method shouldn\'t have a docstring'
+
+class Specialization(Ancestor):
+ TYPE = 'final class'
+ top = 'class'
+
+ def __init__(self, value, _id):
+ Ancestor.__init__(self, value)
+ self._id = _id
+ self.relation = DoNothing()
+ self.toto = Toto()
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/descriptor_crash.py astroid-1.3.8/astroid/tests/testdata/python3/data/descriptor_crash.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/descriptor_crash.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/descriptor_crash.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,11 @@
+
+import urllib
+
+class Page(object):
+ _urlOpen = staticmethod(urllib.urlopen)
+
+ def getPage(self, url):
+ handle = self._urlOpen(url)
+ data = handle.read()
+ handle.close()
+ return data
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/email.py astroid-1.3.8/astroid/tests/testdata/python3/data/email.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/email.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/email.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+"""fake email module to test absolute import doesn't grab this one"""
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/format.py astroid-1.3.8/astroid/tests/testdata/python3/data/format.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/format.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/format.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,34 @@
+"""A multiline string
+"""
+
+function('aeozrijz\
+earzer', hop)
+# XXX write test
+x = [i for i in range(5)
+ if i % 4]
+
+fonction(1,
+ 2,
+ 3,
+ 4)
+
+def definition(a,
+ b,
+ c):
+ return a + b + c
+
+class debile(dict,
+ object):
+ pass
+
+if aaaa: pass
+else:
+ aaaa,bbbb = 1,2
+ aaaa,bbbb = bbbb,aaaa
+# XXX write test
+hop = \
+ aaaa
+
+
+__revision__.lower();
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/__init__.py astroid-1.3.8/astroid/tests/testdata/python3/data/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+__revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $"
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/joined_strings.py astroid-1.3.8/astroid/tests/testdata/python3/data/joined_strings.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/joined_strings.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/joined_strings.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,1051 @@
+x = ('R0lGODlhigJnAef/AAABAAEEAAkCAAMGAg0GBAYJBQoMCBMODQ4QDRITEBkS'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7'
+ +'CxsSEhkWDhYYFQ0aJhkaGBweGyccGh8hHiIkIiMmGTEiHhQoPSYoJSkqKDcp'
+ +'Ii0uLDAxLzI0Mh44U0gxMDI5JkM0JjU3NDY6Kjc5Njo7OUE8Ozw+Oz89QTxA'
+ +'F1akOFFiRIgPHTZksKBAgMCLGTdGNIAAQgKfDAcgZbj0odOnUA8GBAA7')
\ No newline at end of file
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/lmfp/foo.py astroid-1.3.8/astroid/tests/testdata/python3/data/lmfp/foo.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/lmfp/foo.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/lmfp/foo.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,6 @@
+import sys
+if not getattr(sys, 'bar', None):
+ sys.just_once = []
+# there used to be two numbers here because
+# of a load_module_from_path bug
+sys.just_once.append(42)
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/lmfp/__init__.py astroid-1.3.8/astroid/tests/testdata/python3/data/lmfp/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/lmfp/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/lmfp/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,2 @@
+# force a "direct" python import
+from . import foo
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/module1abs/core.py astroid-1.3.8/astroid/tests/testdata/python3/data/module1abs/core.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/module1abs/core.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/module1abs/core.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+import sys
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/module1abs/__init__.py astroid-1.3.8/astroid/tests/testdata/python3/data/module1abs/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/module1abs/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/module1abs/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,4 @@
+
+from . import core
+from .core import *
+print(sys.version)
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/module2.py astroid-1.3.8/astroid/tests/testdata/python3/data/module2.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/module2.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/module2.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,143 @@
+from data.module import YO, YOUPI
+import data
+
+
+class Specialization(YOUPI, YO):
+ pass
+
+
+
+class Metaclass(type):
+ pass
+
+
+
+class Interface:
+ pass
+
+
+
+class MyIFace(Interface):
+ pass
+
+
+
+class AnotherIFace(Interface):
+ pass
+
+
+
+class MyException(Exception):
+ pass
+
+
+
+class MyError(MyException):
+ pass
+
+
+
+class AbstractClass(object):
+
+ def to_override(self, whatever):
+ raise NotImplementedError()
+
+ def return_something(self, param):
+ if param:
+ return 'toto'
+ return
+
+
+
+class Concrete0:
+ __implements__ = MyIFace
+
+
+
+class Concrete1:
+ __implements__ = (MyIFace, AnotherIFace)
+
+
+
+class Concrete2:
+ __implements__ = (MyIFace, AnotherIFace)
+
+
+
+class Concrete23(Concrete1):
+ pass
+
+del YO.member
+del YO
+[SYN1, SYN2] = (Concrete0, Concrete1)
+assert repr(1)
+b = (1) | (((2) & (3)) ^ (8))
+bb = ((1) | (two)) | (6)
+ccc = ((one) & (two)) & (three)
+dddd = ((x) ^ (o)) ^ (r)
+exec('c = 3')
+exec('c = 3', {}, {})
+
+def raise_string(a=2, *args, **kwargs):
+ raise Exception('yo')
+ yield 'coucou'
+ yield
+a = (b) + (2)
+c = (b) * (2)
+c = (b) / (2)
+c = (b) // (2)
+c = (b) - (2)
+c = (b) % (2)
+c = (b) ** (2)
+c = (b) << (2)
+c = (b) >> (2)
+c = ~b
+c = not b
+d = [c]
+e = d[:]
+e = d[a:b:c]
+raise_string(*args, **kwargs)
+print('bonjour', file=stream)
+print('salut', end=' ', file=stream)
+
+def make_class(any, base=data.module.YO, *args, **kwargs):
+ """check base is correctly resolved to Concrete0"""
+
+
+ class Aaaa(base):
+ """dynamic class"""
+
+
+ return Aaaa
+from os.path import abspath
+import os as myos
+
+
+class A:
+ pass
+
+
+
+class A(A):
+ pass
+
+
+def generator():
+ """A generator."""
+ yield
+
+def not_a_generator():
+ """A function that contains generator, but is not one."""
+
+ def generator():
+ yield
+ genl = lambda : (yield)
+
+def with_metaclass(meta, *bases):
+ return meta('NewBase', bases, {})
+
+
+class NotMetaclass(with_metaclass(Metaclass)):
+ pass
+
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/module.py astroid-1.3.8/astroid/tests/testdata/python3/data/module.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/module.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/module.py 2015-08-02 19:35:46.000000000 +0000
@@ -0,0 +1,89 @@
+"""test module for astroid
+"""
+
+__revision__ = '$Id: module.py,v 1.2 2005-11-02 11:56:54 syt Exp $'
+from logilab.common.shellutils import ProgressBar as pb
+from astroid import modutils
+from astroid.utils import *
+import os.path
+MY_DICT = {}
+
+def global_access(key, val):
+ """function test"""
+ local = 1
+ MY_DICT[key] = val
+ for i in val:
+ if i:
+ del MY_DICT[i]
+ continue
+ else:
+ break
+ else:
+ print('!!!')
+
+
+class YO:
+ """hehe"""
+ a = 1
+
+ def __init__(self):
+ try:
+ self.yo = 1
+ except ValueError as ex:
+ pass
+ except (NameError, TypeError):
+ raise XXXError()
+ except:
+ raise
+
+
+
+class YOUPI(YO):
+ class_attr = None
+
+ def __init__(self):
+ self.member = None
+
+ def method(self):
+ """method test"""
+ global MY_DICT
+ try:
+ MY_DICT = {}
+ local = None
+ autre = [a for (a, b) in MY_DICT if b]
+ if b in autre:
+ print('yo', end=' ')
+ else:
+ if a in autre:
+ print('hehe')
+ global_access(local, val=autre)
+ finally:
+ return local
+
+ def static_method():
+ """static method test"""
+ assert MY_DICT, '???'
+ static_method = staticmethod(static_method)
+
+ def class_method(cls):
+ """class method test"""
+ exec(a, b)
+ class_method = classmethod(class_method)
+
+
+def four_args(a, b, c, d):
+ """four arguments (was nested_args)"""
+ print(a, b, c, d)
+ while 1:
+ if a:
+ break
+ a += +1
+ else:
+ b += -2
+ if c:
+ d = ((a) and (b)) or (c)
+ else:
+ c = ((a) and (b)) or (d)
+ list(map(lambda x, y: (y, x), a))
+redirect = four_args
+
Binary files /tmp/tehDuGV_EZ/astroid-1.0.1/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg and /tmp/WwBlO9ZnuM/astroid-1.3.8/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg differ
Binary files /tmp/tehDuGV_EZ/astroid-1.0.1/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip and /tmp/WwBlO9ZnuM/astroid-1.3.8/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip differ
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/noendingnewline.py astroid-1.3.8/astroid/tests/testdata/python3/data/noendingnewline.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/noendingnewline.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/noendingnewline.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,36 @@
+import unittest
+
+
+class TestCase(unittest.TestCase):
+
+ def setUp(self):
+ unittest.TestCase.setUp(self)
+
+
+ def tearDown(self):
+ unittest.TestCase.tearDown(self)
+
+ def testIt(self):
+ self.a = 10
+ self.xxx()
+
+
+ def xxx(self):
+ if False:
+ pass
+ print('a')
+
+ if False:
+ pass
+ pass
+
+ if False:
+ pass
+ print('rara')
+
+
+if __name__ == '__main__':
+ print('test2')
+ unittest.main()
+
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/nonregr.py astroid-1.3.8/astroid/tests/testdata/python3/data/nonregr.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/nonregr.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/nonregr.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,57 @@
+
+
+try:
+ enumerate = enumerate
+except NameError:
+
+ def enumerate(iterable):
+ """emulates the python2.3 enumerate() function"""
+ i = 0
+ for val in iterable:
+ yield i, val
+ i += 1
+
+def toto(value):
+ for k, v in value:
+ print(v.get('yo'))
+
+
+import imp
+fp, mpath, desc = imp.find_module('optparse',a)
+s_opt = imp.load_module('std_optparse', fp, mpath, desc)
+
+class OptionParser(s_opt.OptionParser):
+
+ def parse_args(self, args=None, values=None, real_optparse=False):
+ if real_optparse:
+ pass
+## return super(OptionParser, self).parse_args()
+ else:
+ import optcomp
+ optcomp.completion(self)
+
+
+class Aaa(object):
+ """docstring"""
+ def __init__(self):
+ self.__setattr__('a','b')
+ pass
+
+ def one_public(self):
+ """docstring"""
+ pass
+
+ def another_public(self):
+ """docstring"""
+ pass
+
+class Ccc(Aaa):
+ """docstring"""
+
+ class Ddd(Aaa):
+ """docstring"""
+ pass
+
+ class Eee(Ddd):
+ """docstring"""
+ pass
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/notall.py astroid-1.3.8/astroid/tests/testdata/python3/data/notall.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/notall.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/notall.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,8 @@
+
+name = 'a'
+_bla = 2
+other = 'o'
+class Aaa: pass
+
+def func(): print('yo')
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/package/absimport.py astroid-1.3.8/astroid/tests/testdata/python3/data/package/absimport.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/package/absimport.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/package/absimport.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,6 @@
+from __future__ import absolute_import, print_function
+import import_package_subpackage_module # fail
+print(import_package_subpackage_module)
+
+from . import hello as hola
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/package/hello.py astroid-1.3.8/astroid/tests/testdata/python3/data/package/hello.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/package/hello.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/package/hello.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,2 @@
+"""hello module"""
+
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py astroid-1.3.8/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,49 @@
+# pylint: disable-msg=I0011,C0301,W0611
+"""I found some of my scripts trigger off an AttributeError in pylint
+0.8.1 (with common 0.12.0 and astroid 0.13.1).
+
+Traceback (most recent call last):
+ File "/usr/bin/pylint", line 4, in ?
+ lint.Run(sys.argv[1:])
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__
+ linter.check(args)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check
+ self.check_file(filepath, modname, checkers)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file
+ astroid = self._check_file(filepath, modname, checkers)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file
+ self.check_astroid_module(astroid, checkers)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module
+ self.astroid_events(astroid, [checker for checker in checkers
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
+ self.astroid_events(child, checkers, _reversed_checkers)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
+ self.astroid_events(child, checkers, _reversed_checkers)
+ File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events
+ checker.visit(astroid)
+ File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit
+ method(node)
+ File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import
+ self._check_module_attrs(node, module, name_parts[1:])
+ File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs
+ self.add_message('E0611', args=(name, module.name),
+AttributeError: Import instance has no attribute 'name'
+
+
+You can reproduce it by:
+(1) create package structure like the following:
+
+package/
+ __init__.py
+ subpackage/
+ __init__.py
+ module.py
+
+(2) in package/__init__.py write:
+
+import subpackage
+
+(3) run pylint with a script importing package.subpackage.module.
+"""
+__revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 15:59:32 syt Exp $'
+import package.subpackage.module
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/package/__init__.py astroid-1.3.8/astroid/tests/testdata/python3/data/package/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/package/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/package/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,4 @@
+"""package's __init__ file"""
+
+
+from . import subpackage
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/package/subpackage/__init__.py astroid-1.3.8/astroid/tests/testdata/python3/data/package/subpackage/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/package/subpackage/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/package/subpackage/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+"""package.subpackage"""
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/package/subpackage/module.py astroid-1.3.8/astroid/tests/testdata/python3/data/package/subpackage/module.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/package/subpackage/module.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/package/subpackage/module.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+"""package.subpackage.module"""
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/recursion.py astroid-1.3.8/astroid/tests/testdata/python3/data/recursion.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/recursion.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/recursion.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,3 @@
+""" For issue #25 """
+class Base(object):
+ pass
\ No newline at end of file
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/SSL1/Connection1.py astroid-1.3.8/astroid/tests/testdata/python3/data/SSL1/Connection1.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/SSL1/Connection1.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/SSL1/Connection1.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,14 @@
+"""M2Crypto.SSL.Connection
+
+Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved."""
+
+RCS_id='$Id: Connection1.py,v 1.1 2005-06-13 20:55:22 syt Exp $'
+
+#Some code deleted here
+
+class Connection:
+
+ """An SSL connection."""
+
+ def __init__(self, ctx, sock=None):
+ print('init Connection')
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/SSL1/__init__.py astroid-1.3.8/astroid/tests/testdata/python3/data/SSL1/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/SSL1/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/SSL1/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+from .Connection1 import Connection
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/suppliermodule_test.py astroid-1.3.8/astroid/tests/testdata/python3/data/suppliermodule_test.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/suppliermodule_test.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/suppliermodule_test.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,13 @@
+""" file suppliermodule.py """
+
+class NotImplemented(Exception):
+ pass
+
+class Interface:
+ def get_value(self):
+ raise NotImplemented()
+
+ def set_value(self, value):
+ raise NotImplemented()
+
+class DoNothing : pass
diff -Nru astroid-1.0.1/astroid/tests/testdata/python3/data/unicode_package/__init__.py astroid-1.3.8/astroid/tests/testdata/python3/data/unicode_package/__init__.py
--- astroid-1.0.1/astroid/tests/testdata/python3/data/unicode_package/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/testdata/python3/data/unicode_package/__init__.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1 @@
+x = "șțîâ"
\ No newline at end of file
diff -Nru astroid-1.0.1/astroid/tests/unittest_brain.py astroid-1.3.8/astroid/tests/unittest_brain.py
--- astroid-1.0.1/astroid/tests/unittest_brain.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_brain.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,226 @@
+# Copyright 2013 Google Inc. All Rights Reserved.
+#
+# This file is part of astroid.
+#
+# logilab-astng is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# logilab-astng is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with logilab-astng. If not, see .
+"""Tests for basic functionality in astroid.brain."""
+import sys
+import unittest
+
+from astroid import MANAGER
+from astroid import bases
+from astroid import nodes
+from astroid import test_utils
+import astroid
+
+import six
+
+
+try:
+ import nose # pylint: disable=unused-import
+ HAS_NOSE = True
+except ImportError:
+ HAS_NOSE = False
+
+
+class HashlibTest(unittest.TestCase):
+ def test_hashlib(self):
+ """Tests that brain extensions for hashlib work."""
+ hashlib_module = MANAGER.ast_from_module_name('hashlib')
+ for class_name in ['md5', 'sha1']:
+ class_obj = hashlib_module[class_name]
+ self.assertIn('update', class_obj)
+ self.assertIn('digest', class_obj)
+ self.assertIn('hexdigest', class_obj)
+ self.assertIn('block_size', class_obj)
+ self.assertIn('digest_size', class_obj)
+ self.assertEqual(len(class_obj['__init__'].args.args), 2)
+ self.assertEqual(len(class_obj['__init__'].args.defaults), 1)
+ self.assertEqual(len(class_obj['update'].args.args), 2)
+ self.assertEqual(len(class_obj['digest'].args.args), 1)
+ self.assertEqual(len(class_obj['hexdigest'].args.args), 1)
+
+
+class NamedTupleTest(unittest.TestCase):
+ def test_namedtuple_base(self):
+ klass = test_utils.extract_node("""
+ from collections import namedtuple
+
+ class X(namedtuple("X", ["a", "b", "c"])):
+ pass
+ """)
+ self.assertEqual(
+ [anc.name for anc in klass.ancestors()],
+ ['X', 'tuple', 'object'])
+ for anc in klass.ancestors():
+ self.assertFalse(anc.parent is None)
+
+ def test_namedtuple_inference(self):
+ klass = test_utils.extract_node("""
+ from collections import namedtuple
+
+ name = "X"
+ fields = ["a", "b", "c"]
+ class X(namedtuple(name, fields)):
+ pass
+ """)
+ for base in klass.ancestors():
+ if base.name == 'X':
+ break
+ self.assertSetEqual({"a", "b", "c"}, set(base.instance_attrs))
+
+ def test_namedtuple_inference_failure(self):
+ klass = test_utils.extract_node("""
+ from collections import namedtuple
+
+ def foo(fields):
+ return __(namedtuple("foo", fields))
+ """)
+ self.assertIs(bases.YES, next(klass.infer()))
+
+
+ @unittest.skipIf(sys.version_info[0] > 2,
+ 'namedtuple inference is broken on Python 3')
+ def test_namedtuple_advanced_inference(self):
+ # urlparse return an object of class ParseResult, which has a
+ # namedtuple call and a mixin as base classes
+ result = test_utils.extract_node("""
+ import urlparse
+
+ result = __(urlparse.urlparse('gopher://'))
+ """)
+ instance = next(result.infer())
+ self.assertEqual(len(instance.getattr('scheme')), 1)
+ self.assertEqual(len(instance.getattr('port')), 1)
+ with self.assertRaises(astroid.NotFoundError):
+ instance.getattr('foo')
+
+
+class ModuleExtenderTest(unittest.TestCase):
+ def testExtensionModules(self):
+ for extender, _ in MANAGER.transforms[nodes.Module]:
+ n = nodes.Module('__main__', None)
+ extender(n)
+
+
+@unittest.skipUnless(HAS_NOSE, "This test requires nose library.")
+class NoseBrainTest(unittest.TestCase):
+
+ def test_nose_tools(self):
+ methods = test_utils.extract_node("""
+ from nose.tools import assert_equal
+ from nose.tools import assert_true
+ assert_equal = assert_equal #@
+ assert_true = assert_true #@
+ """)
+
+ assert_equal = next(methods[0].value.infer())
+ assert_true = next(methods[1].value.infer())
+
+ self.assertIsInstance(assert_equal, astroid.BoundMethod)
+ self.assertIsInstance(assert_true, astroid.BoundMethod)
+ self.assertEqual(assert_equal.qname(),
+ 'unittest.case.TestCase.assertEqual')
+ self.assertEqual(assert_true.qname(),
+ 'unittest.case.TestCase.assertTrue')
+class SixBrainTest(unittest.TestCase):
+
+ def test_attribute_access(self):
+ ast_nodes = test_utils.extract_node('''
+ import six
+ six.moves.http_client #@
+ six.moves.urllib_parse #@
+ six.moves.urllib_error #@
+ six.moves.urllib.request #@
+ ''')
+ http_client = next(ast_nodes[0].infer())
+ self.assertIsInstance(http_client, nodes.Module)
+ self.assertEqual(http_client.name,
+ 'http.client' if six.PY3 else 'httplib')
+
+ urllib_parse = next(ast_nodes[1].infer())
+ if six.PY3:
+ self.assertIsInstance(urllib_parse, nodes.Module)
+ self.assertEqual(urllib_parse.name, 'urllib.parse')
+ else:
+ # On Python 2, this is a fake module, the same behaviour
+ # being mimicked in brain's tip for six.moves.
+ self.assertIsInstance(urllib_parse, astroid.Instance)
+ urljoin = next(urllib_parse.igetattr('urljoin'))
+ urlencode = next(urllib_parse.igetattr('urlencode'))
+ if six.PY2:
+ # In reality it's a function, but our implementations
+ # transforms it into a method.
+ self.assertIsInstance(urljoin, astroid.BoundMethod)
+ self.assertEqual(urljoin.qname(), 'urlparse.urljoin')
+ self.assertIsInstance(urlencode, astroid.BoundMethod)
+ self.assertEqual(urlencode.qname(), 'urllib.urlencode')
+ else:
+ self.assertIsInstance(urljoin, nodes.Function)
+ self.assertEqual(urljoin.qname(), 'urllib.parse.urljoin')
+ self.assertIsInstance(urlencode, nodes.Function)
+ self.assertEqual(urlencode.qname(), 'urllib.parse.urlencode')
+
+ urllib_error = next(ast_nodes[2].infer())
+ if six.PY3:
+ self.assertIsInstance(urllib_error, nodes.Module)
+ self.assertEqual(urllib_error.name, 'urllib.error')
+ else:
+ # On Python 2, this is a fake module, the same behaviour
+ # being mimicked in brain's tip for six.moves.
+ self.assertIsInstance(urllib_error, astroid.Instance)
+ urlerror = next(urllib_error.igetattr('URLError'))
+ self.assertIsInstance(urlerror, nodes.Class)
+ content_too_short = next(urllib_error.igetattr('ContentTooShortError'))
+ self.assertIsInstance(content_too_short, nodes.Class)
+
+ urllib_request = next(ast_nodes[3].infer())
+ if six.PY3:
+ self.assertIsInstance(urllib_request, nodes.Module)
+ self.assertEqual(urllib_request.name, 'urllib.request')
+ else:
+ self.assertIsInstance(urllib_request, astroid.Instance)
+ urlopen = next(urllib_request.igetattr('urlopen'))
+ urlretrieve = next(urllib_request.igetattr('urlretrieve'))
+ if six.PY2:
+ # In reality it's a function, but our implementations
+ # transforms it into a method.
+ self.assertIsInstance(urlopen, astroid.BoundMethod)
+ self.assertEqual(urlopen.qname(), 'urllib2.urlopen')
+ self.assertIsInstance(urlretrieve, astroid.BoundMethod)
+ self.assertEqual(urlretrieve.qname(), 'urllib.urlretrieve')
+ else:
+ self.assertIsInstance(urlopen, nodes.Function)
+ self.assertEqual(urlopen.qname(), 'urllib.request.urlopen')
+ self.assertIsInstance(urlretrieve, nodes.Function)
+ self.assertEqual(urlretrieve.qname(), 'urllib.request.urlretrieve')
+
+ def test_from_imports(self):
+ ast_node = test_utils.extract_node('''
+ from six.moves import http_client
+ http_client.HTTPSConnection #@
+ ''')
+ inferred = next(ast_node.infer())
+ self.assertIsInstance(inferred, nodes.Class)
+ if six.PY3:
+ qname = 'http.client.HTTPSConnection'
+ else:
+ qname = 'httplib.HTTPSConnection'
+ self.assertEqual(inferred.qname(), qname)
+
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_builder.py astroid-1.3.8/astroid/tests/unittest_builder.py
--- astroid-1.0.1/astroid/tests/unittest_builder.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_builder.py 2015-08-02 19:35:55.000000000 +0000
@@ -0,0 +1,759 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""tests for the astroid builder and rebuilder module"""
+
+import os
+import sys
+import unittest
+
+from astroid import builder, nodes, InferenceError, NotFoundError
+from astroid.bases import YES, BUILTINS
+from astroid.manager import AstroidManager
+from astroid import test_utils
+from astroid.tests import resources
+
+MANAGER = AstroidManager()
+IS_PY3 = sys.version_info[0] == 3
+
+
+class FromToLineNoTest(unittest.TestCase):
+
+ def setUp(self):
+ self.astroid = resources.build_file('data/format.py')
+
+ def test_callfunc_lineno(self):
+ stmts = self.astroid.body
+ # on line 4:
+ # function('aeozrijz\
+ # earzer', hop)
+ discard = stmts[0]
+ self.assertIsInstance(discard, nodes.Discard)
+ self.assertEqual(discard.fromlineno, 4)
+ self.assertEqual(discard.tolineno, 5)
+ callfunc = discard.value
+ self.assertIsInstance(callfunc, nodes.CallFunc)
+ self.assertEqual(callfunc.fromlineno, 4)
+ self.assertEqual(callfunc.tolineno, 5)
+ name = callfunc.func
+ self.assertIsInstance(name, nodes.Name)
+ self.assertEqual(name.fromlineno, 4)
+ self.assertEqual(name.tolineno, 4)
+ strarg = callfunc.args[0]
+ self.assertIsInstance(strarg, nodes.Const)
+ if hasattr(sys, 'pypy_version_info'):
+ lineno = 4
+ else:
+ lineno = 5 # no way for this one in CPython (is 4 actually)
+ self.assertEqual(strarg.fromlineno, lineno)
+ self.assertEqual(strarg.tolineno, lineno)
+ namearg = callfunc.args[1]
+ self.assertIsInstance(namearg, nodes.Name)
+ self.assertEqual(namearg.fromlineno, 5)
+ self.assertEqual(namearg.tolineno, 5)
+ # on line 10:
+ # fonction(1,
+ # 2,
+ # 3,
+ # 4)
+ discard = stmts[2]
+ self.assertIsInstance(discard, nodes.Discard)
+ self.assertEqual(discard.fromlineno, 10)
+ self.assertEqual(discard.tolineno, 13)
+ callfunc = discard.value
+ self.assertIsInstance(callfunc, nodes.CallFunc)
+ self.assertEqual(callfunc.fromlineno, 10)
+ self.assertEqual(callfunc.tolineno, 13)
+ name = callfunc.func
+ self.assertIsInstance(name, nodes.Name)
+ self.assertEqual(name.fromlineno, 10)
+ self.assertEqual(name.tolineno, 10)
+ for i, arg in enumerate(callfunc.args):
+ self.assertIsInstance(arg, nodes.Const)
+ self.assertEqual(arg.fromlineno, 10+i)
+ self.assertEqual(arg.tolineno, 10+i)
+
+ def test_function_lineno(self):
+ stmts = self.astroid.body
+ # on line 15:
+ # def definition(a,
+ # b,
+ # c):
+ # return a + b + c
+ function = stmts[3]
+ self.assertIsInstance(function, nodes.Function)
+ self.assertEqual(function.fromlineno, 15)
+ self.assertEqual(function.tolineno, 18)
+ return_ = function.body[0]
+ self.assertIsInstance(return_, nodes.Return)
+ self.assertEqual(return_.fromlineno, 18)
+ self.assertEqual(return_.tolineno, 18)
+ if sys.version_info < (3, 0):
+ self.assertEqual(function.blockstart_tolineno, 17)
+ else:
+ self.skipTest('FIXME http://bugs.python.org/issue10445 '
+ '(no line number on function args)')
+
+ def test_decorated_function_lineno(self):
+ astroid = test_utils.build_module('''
+ @decorator
+ def function(
+ arg):
+ print (arg)
+ ''', __name__)
+ function = astroid['function']
+ self.assertEqual(function.fromlineno, 3) # XXX discussable, but that's what is expected by pylint right now
+ self.assertEqual(function.tolineno, 5)
+ self.assertEqual(function.decorators.fromlineno, 2)
+ self.assertEqual(function.decorators.tolineno, 2)
+ if sys.version_info < (3, 0):
+ self.assertEqual(function.blockstart_tolineno, 4)
+ else:
+ self.skipTest('FIXME http://bugs.python.org/issue10445 '
+ '(no line number on function args)')
+
+
+ def test_class_lineno(self):
+ stmts = self.astroid.body
+ # on line 20:
+ # class debile(dict,
+ # object):
+ # pass
+ class_ = stmts[4]
+ self.assertIsInstance(class_, nodes.Class)
+ self.assertEqual(class_.fromlineno, 20)
+ self.assertEqual(class_.tolineno, 22)
+ self.assertEqual(class_.blockstart_tolineno, 21)
+ pass_ = class_.body[0]
+ self.assertIsInstance(pass_, nodes.Pass)
+ self.assertEqual(pass_.fromlineno, 22)
+ self.assertEqual(pass_.tolineno, 22)
+
+ def test_if_lineno(self):
+ stmts = self.astroid.body
+ # on line 20:
+ # if aaaa: pass
+ # else:
+ # aaaa,bbbb = 1,2
+ # aaaa,bbbb = bbbb,aaaa
+ if_ = stmts[5]
+ self.assertIsInstance(if_, nodes.If)
+ self.assertEqual(if_.fromlineno, 24)
+ self.assertEqual(if_.tolineno, 27)
+ self.assertEqual(if_.blockstart_tolineno, 24)
+ self.assertEqual(if_.orelse[0].fromlineno, 26)
+ self.assertEqual(if_.orelse[1].tolineno, 27)
+
+ def test_for_while_lineno(self):
+ for code in ('''
+ for a in range(4):
+ print (a)
+ break
+ else:
+ print ("bouh")
+ ''', '''
+ while a:
+ print (a)
+ break
+ else:
+ print ("bouh")
+ '''):
+ astroid = test_utils.build_module(code, __name__)
+ stmt = astroid.body[0]
+ self.assertEqual(stmt.fromlineno, 2)
+ self.assertEqual(stmt.tolineno, 6)
+ self.assertEqual(stmt.blockstart_tolineno, 2)
+ self.assertEqual(stmt.orelse[0].fromlineno, 6) # XXX
+ self.assertEqual(stmt.orelse[0].tolineno, 6)
+
+ def test_try_except_lineno(self):
+ astroid = test_utils.build_module('''
+ try:
+ print (a)
+ except:
+ pass
+ else:
+ print ("bouh")
+ ''', __name__)
+ try_ = astroid.body[0]
+ self.assertEqual(try_.fromlineno, 2)
+ self.assertEqual(try_.tolineno, 7)
+ self.assertEqual(try_.blockstart_tolineno, 2)
+ self.assertEqual(try_.orelse[0].fromlineno, 7) # XXX
+ self.assertEqual(try_.orelse[0].tolineno, 7)
+ hdlr = try_.handlers[0]
+ self.assertEqual(hdlr.fromlineno, 4)
+ self.assertEqual(hdlr.tolineno, 5)
+ self.assertEqual(hdlr.blockstart_tolineno, 4)
+
+
+ def test_try_finally_lineno(self):
+ astroid = test_utils.build_module('''
+ try:
+ print (a)
+ finally:
+ print ("bouh")
+ ''', __name__)
+ try_ = astroid.body[0]
+ self.assertEqual(try_.fromlineno, 2)
+ self.assertEqual(try_.tolineno, 5)
+ self.assertEqual(try_.blockstart_tolineno, 2)
+ self.assertEqual(try_.finalbody[0].fromlineno, 5) # XXX
+ self.assertEqual(try_.finalbody[0].tolineno, 5)
+
+
+ def test_try_finally_25_lineno(self):
+ astroid = test_utils.build_module('''
+ try:
+ print (a)
+ except:
+ pass
+ finally:
+ print ("bouh")
+ ''', __name__)
+ try_ = astroid.body[0]
+ self.assertEqual(try_.fromlineno, 2)
+ self.assertEqual(try_.tolineno, 7)
+ self.assertEqual(try_.blockstart_tolineno, 2)
+ self.assertEqual(try_.finalbody[0].fromlineno, 7) # XXX
+ self.assertEqual(try_.finalbody[0].tolineno, 7)
+
+
+ def test_with_lineno(self):
+ astroid = test_utils.build_module('''
+ from __future__ import with_statement
+ with file("/tmp/pouet") as f:
+ print (f)
+ ''', __name__)
+ with_ = astroid.body[1]
+ self.assertEqual(with_.fromlineno, 3)
+ self.assertEqual(with_.tolineno, 4)
+ self.assertEqual(with_.blockstart_tolineno, 3)
+
+
+class BuilderTest(unittest.TestCase):
+
+ def setUp(self):
+ self.builder = builder.AstroidBuilder()
+
+ def test_data_build_null_bytes(self):
+ with self.assertRaises(builder.AstroidBuildingException):
+ self.builder.string_build('\x00')
+
+ def test_missing_newline(self):
+ """check that a file with no trailing new line is parseable"""
+ resources.build_file('data/noendingnewline.py')
+
+ def test_missing_file(self):
+ with self.assertRaises(builder.AstroidBuildingException):
+ resources.build_file('data/inexistant.py')
+
+ def test_inspect_build0(self):
+ """test astroid tree build from a living object"""
+ builtin_ast = MANAGER.ast_from_module_name(BUILTINS)
+ if not IS_PY3:
+ fclass = builtin_ast['file']
+ self.assertIn('name', fclass)
+ self.assertIn('mode', fclass)
+ self.assertIn('read', fclass)
+ self.assertTrue(fclass.newstyle)
+ self.assertTrue(fclass.pytype(), '%s.type' % BUILTINS)
+ self.assertIsInstance(fclass['read'], nodes.Function)
+ # check builtin function has args.args == None
+ dclass = builtin_ast['dict']
+ self.assertIsNone(dclass['has_key'].args.args)
+ # just check type and object are there
+ builtin_ast.getattr('type')
+ objectastroid = builtin_ast.getattr('object')[0]
+ self.assertIsInstance(objectastroid.getattr('__new__')[0], nodes.Function)
+ # check open file alias
+ builtin_ast.getattr('open')
+ # check 'help' is there (defined dynamically by site.py)
+ builtin_ast.getattr('help')
+ # check property has __init__
+ pclass = builtin_ast['property']
+ self.assertIn('__init__', pclass)
+ self.assertIsInstance(builtin_ast['None'], nodes.Const)
+ self.assertIsInstance(builtin_ast['True'], nodes.Const)
+ self.assertIsInstance(builtin_ast['False'], nodes.Const)
+ if IS_PY3:
+ self.assertIsInstance(builtin_ast['Exception'], nodes.Class)
+ self.assertIsInstance(builtin_ast['NotImplementedError'], nodes.Class)
+ else:
+ self.assertIsInstance(builtin_ast['Exception'], nodes.From)
+ self.assertIsInstance(builtin_ast['NotImplementedError'], nodes.From)
+
+ def test_inspect_build1(self):
+ time_ast = MANAGER.ast_from_module_name('time')
+ self.assertTrue(time_ast)
+ self.assertEqual(time_ast['time'].args.defaults, [])
+
+ def test_inspect_build2(self):
+ """test astroid tree build from a living object"""
+ try:
+ from mx import DateTime
+ except ImportError:
+ self.skipTest('test skipped: mxDateTime is not available')
+ else:
+ dt_ast = self.builder.inspect_build(DateTime)
+ dt_ast.getattr('DateTime')
+ # this one is failing since DateTimeType.__module__ = 'builtins' !
+ #dt_ast.getattr('DateTimeType')
+
+ def test_inspect_build3(self):
+ self.builder.inspect_build(unittest)
+
+ @test_utils.require_version(maxver='3.0')
+ def test_inspect_build_instance(self):
+ """test astroid tree build from a living object"""
+ import exceptions
+ builtin_ast = self.builder.inspect_build(exceptions)
+ fclass = builtin_ast['OSError']
+ # things like OSError.strerror are now (2.5) data descriptors on the
+ # class instead of entries in the __dict__ of an instance
+ container = fclass
+ self.assertIn('errno', container)
+ self.assertIn('strerror', container)
+ self.assertIn('filename', container)
+
+ def test_inspect_build_type_object(self):
+ builtin_ast = MANAGER.ast_from_module_name(BUILTINS)
+
+ infered = list(builtin_ast.igetattr('object'))
+ self.assertEqual(len(infered), 1)
+ infered = infered[0]
+ self.assertEqual(infered.name, 'object')
+ infered.as_string() # no crash test
+
+ infered = list(builtin_ast.igetattr('type'))
+ self.assertEqual(len(infered), 1)
+ infered = infered[0]
+ self.assertEqual(infered.name, 'type')
+ infered.as_string() # no crash test
+
+ def test_inspect_transform_module(self):
+ # ensure no cached version of the time module
+ MANAGER._mod_file_cache.pop(('time', None), None)
+ MANAGER.astroid_cache.pop('time', None)
+ def transform_time(node):
+ if node.name == 'time':
+ node.transformed = True
+ MANAGER.register_transform(nodes.Module, transform_time)
+ try:
+ time_ast = MANAGER.ast_from_module_name('time')
+ self.assertTrue(getattr(time_ast, 'transformed', False))
+ finally:
+ MANAGER.unregister_transform(nodes.Module, transform_time)
+
+ def test_package_name(self):
+ """test base properties and method of a astroid module"""
+ datap = resources.build_file('data/__init__.py', 'data')
+ self.assertEqual(datap.name, 'data')
+ self.assertEqual(datap.package, 1)
+ datap = resources.build_file('data/__init__.py', 'data.__init__')
+ self.assertEqual(datap.name, 'data')
+ self.assertEqual(datap.package, 1)
+
+ def test_yield_parent(self):
+ """check if we added discard nodes as yield parent (w/ compiler)"""
+ code = """
+ def yiell(): #@
+ yield 0
+ if noe:
+ yield more
+ """
+ func = test_utils.extract_node(code)
+ self.assertIsInstance(func, nodes.Function)
+ stmt = func.body[0]
+ self.assertIsInstance(stmt, nodes.Discard)
+ self.assertIsInstance(stmt.value, nodes.Yield)
+ self.assertIsInstance(func.body[1].body[0], nodes.Discard)
+ self.assertIsInstance(func.body[1].body[0].value, nodes.Yield)
+
+ def test_object(self):
+ obj_ast = self.builder.inspect_build(object)
+ self.assertIn('__setattr__', obj_ast)
+
+ def test_newstyle_detection(self):
+ data = '''
+ class A:
+ "old style"
+
+ class B(A):
+ "old style"
+
+ class C(object):
+ "new style"
+
+ class D(C):
+ "new style"
+
+ __metaclass__ = type
+
+ class E(A):
+ "old style"
+
+ class F:
+ "new style"
+ '''
+ mod_ast = test_utils.build_module(data, __name__)
+ if IS_PY3:
+ self.assertTrue(mod_ast['A'].newstyle)
+ self.assertTrue(mod_ast['B'].newstyle)
+ self.assertTrue(mod_ast['E'].newstyle)
+ else:
+ self.assertFalse(mod_ast['A'].newstyle)
+ self.assertFalse(mod_ast['B'].newstyle)
+ self.assertFalse(mod_ast['E'].newstyle)
+ self.assertTrue(mod_ast['C'].newstyle)
+ self.assertTrue(mod_ast['D'].newstyle)
+ self.assertTrue(mod_ast['F'].newstyle)
+
+ def test_globals(self):
+ data = '''
+ CSTE = 1
+
+ def update_global():
+ global CSTE
+ CSTE += 1
+
+ def global_no_effect():
+ global CSTE2
+ print (CSTE)
+ '''
+ astroid = test_utils.build_module(data, __name__)
+ self.assertEqual(len(astroid.getattr('CSTE')), 2)
+ self.assertIsInstance(astroid.getattr('CSTE')[0], nodes.AssName)
+ self.assertEqual(astroid.getattr('CSTE')[0].fromlineno, 2)
+ self.assertEqual(astroid.getattr('CSTE')[1].fromlineno, 6)
+ with self.assertRaises(NotFoundError):
+ astroid.getattr('CSTE2')
+ with self.assertRaises(InferenceError):
+ next(astroid['global_no_effect'].ilookup('CSTE2'))
+
+ def test_socket_build(self):
+ import socket
+ astroid = self.builder.module_build(socket)
+ # XXX just check the first one. Actually 3 objects are inferred (look at
+ # the socket module) but the last one as those attributes dynamically
+ # set and astroid is missing this.
+ for fclass in astroid.igetattr('socket'):
+ #print fclass.root().name, fclass.name, fclass.lineno
+ self.assertIn('connect', fclass)
+ self.assertIn('send', fclass)
+ self.assertIn('close', fclass)
+ break
+
+ def test_gen_expr_var_scope(self):
+ data = 'l = list(n for n in range(10))\n'
+ astroid = test_utils.build_module(data, __name__)
+ # n unavailable outside gen expr scope
+ self.assertNotIn('n', astroid)
+ # test n is inferable anyway
+ n = test_utils.get_name_node(astroid, 'n')
+ self.assertIsNot(n.scope(), astroid)
+ self.assertEqual([i.__class__ for i in n.infer()],
+ [YES.__class__])
+
+ def test_no_future_imports(self):
+ mod = test_utils.build_module("import sys")
+ self.assertEqual(set(), mod.future_imports)
+
+ def test_future_imports(self):
+ mod = test_utils.build_module("from __future__ import print_function")
+ self.assertEqual(set(['print_function']), mod.future_imports)
+
+ def test_two_future_imports(self):
+ mod = test_utils.build_module("""
+ from __future__ import print_function
+ from __future__ import absolute_import
+ """)
+ self.assertEqual(set(['print_function', 'absolute_import']), mod.future_imports)
+
+ def test_infered_build(self):
+ code = '''
+ class A: pass
+ A.type = "class"
+
+ def A_ass_type(self):
+ print (self)
+ A.ass_type = A_ass_type
+ '''
+ astroid = test_utils.build_module(code)
+ lclass = list(astroid.igetattr('A'))
+ self.assertEqual(len(lclass), 1)
+ lclass = lclass[0]
+ self.assertIn('ass_type', lclass.locals)
+ self.assertIn('type', lclass.locals)
+
+ def test_augassign_attr(self):
+ test_utils.build_module("""
+ class Counter:
+ v = 0
+ def inc(self):
+ self.v += 1
+ """, __name__)
+ # TODO: Check self.v += 1 generate AugAssign(AssAttr(...)),
+ # not AugAssign(GetAttr(AssName...))
+
+ def test_infered_dont_pollute(self):
+ code = '''
+ def func(a=None):
+ a.custom_attr = 0
+ def func2(a={}):
+ a.custom_attr = 0
+ '''
+ test_utils.build_module(code)
+ nonetype = nodes.const_factory(None)
+ self.assertNotIn('custom_attr', nonetype.locals)
+ self.assertNotIn('custom_attr', nonetype.instance_attrs)
+ nonetype = nodes.const_factory({})
+ self.assertNotIn('custom_attr', nonetype.locals)
+ self.assertNotIn('custom_attr', nonetype.instance_attrs)
+
+ def test_asstuple(self):
+ code = 'a, b = range(2)'
+ astroid = test_utils.build_module(code)
+ self.assertIn('b', astroid.locals)
+ code = '''
+ def visit_if(self, node):
+ node.test, body = node.tests[0]
+ '''
+ astroid = test_utils.build_module(code)
+ self.assertIn('body', astroid['visit_if'].locals)
+
+ def test_build_constants(self):
+ '''test expected values of constants after rebuilding'''
+ code = '''
+ def func():
+ return None
+ return
+ return 'None'
+ '''
+ astroid = test_utils.build_module(code)
+ none, nothing, chain = [ret.value for ret in astroid.body[0].body]
+ self.assertIsInstance(none, nodes.Const)
+ self.assertIsNone(none.value)
+ self.assertIsNone(nothing)
+ self.assertIsInstance(chain, nodes.Const)
+ self.assertEqual(chain.value, 'None')
+
+ def test_lgc_classproperty(self):
+ '''test expected values of constants after rebuilding'''
+ code = '''
+ from logilab.common.decorators import classproperty
+
+ class A(object):
+ @classproperty
+ def hop(cls): #@
+ return None
+ '''
+ method = test_utils.extract_node(code)
+ self.assertEqual('classmethod', method.type)
+
+
+class FileBuildTest(unittest.TestCase):
+ def setUp(self):
+ self.module = resources.build_file('data/module.py', 'data.module')
+
+ def test_module_base_props(self):
+ """test base properties and method of a astroid module"""
+ module = self.module
+ self.assertEqual(module.name, 'data.module')
+ self.assertEqual(module.doc, "test module for astroid\n")
+ self.assertEqual(module.fromlineno, 0)
+ self.assertIsNone(module.parent)
+ self.assertEqual(module.frame(), module)
+ self.assertEqual(module.root(), module)
+ self.assertEqual(module.file, os.path.abspath(resources.find('data/module.py')))
+ self.assertEqual(module.pure_python, 1)
+ self.assertEqual(module.package, 0)
+ self.assertFalse(module.is_statement)
+ self.assertEqual(module.statement(), module)
+ self.assertEqual(module.statement(), module)
+
+ def test_module_locals(self):
+ """test the 'locals' dictionary of a astroid module"""
+ module = self.module
+ _locals = module.locals
+ self.assertIs(_locals, module.globals)
+ keys = sorted(_locals.keys())
+ should = ['MY_DICT', 'YO', 'YOUPI',
+ '__revision__', 'global_access', 'modutils', 'four_args',
+ 'os', 'redirect', 'pb', 'LocalsVisitor', 'ASTWalker']
+ should.sort()
+ self.assertEqual(keys, should)
+
+ def test_function_base_props(self):
+ """test base properties and method of a astroid function"""
+ module = self.module
+ function = module['global_access']
+ self.assertEqual(function.name, 'global_access')
+ self.assertEqual(function.doc, 'function test')
+ self.assertEqual(function.fromlineno, 11)
+ self.assertTrue(function.parent)
+ self.assertEqual(function.frame(), function)
+ self.assertEqual(function.parent.frame(), module)
+ self.assertEqual(function.root(), module)
+ self.assertEqual([n.name for n in function.args.args], ['key', 'val'])
+ self.assertEqual(function.type, 'function')
+
+ def test_function_locals(self):
+ """test the 'locals' dictionary of a astroid function"""
+ _locals = self.module['global_access'].locals
+ self.assertEqual(len(_locals), 4)
+ keys = sorted(_locals.keys())
+ self.assertEqual(keys, ['i', 'key', 'local', 'val'])
+
+ def test_class_base_props(self):
+ """test base properties and method of a astroid class"""
+ module = self.module
+ klass = module['YO']
+ self.assertEqual(klass.name, 'YO')
+ self.assertEqual(klass.doc, 'hehe')
+ self.assertEqual(klass.fromlineno, 25)
+ self.assertTrue(klass.parent)
+ self.assertEqual(klass.frame(), klass)
+ self.assertEqual(klass.parent.frame(), module)
+ self.assertEqual(klass.root(), module)
+ self.assertEqual(klass.basenames, [])
+ if IS_PY3:
+ self.assertTrue(klass.newstyle)
+ else:
+ self.assertFalse(klass.newstyle)
+
+ def test_class_locals(self):
+ """test the 'locals' dictionary of a astroid class"""
+ module = self.module
+ klass1 = module['YO']
+ locals1 = klass1.locals
+ keys = sorted(locals1.keys())
+ self.assertEqual(keys, ['__init__', 'a'])
+ klass2 = module['YOUPI']
+ locals2 = klass2.locals
+ keys = locals2.keys()
+ self.assertEqual(sorted(keys),
+ ['__init__', 'class_attr', 'class_method',
+ 'method', 'static_method'])
+
+ def test_class_instance_attrs(self):
+ module = self.module
+ klass1 = module['YO']
+ klass2 = module['YOUPI']
+ self.assertEqual(list(klass1.instance_attrs.keys()), ['yo'])
+ self.assertEqual(list(klass2.instance_attrs.keys()), ['member'])
+
+ def test_class_basenames(self):
+ module = self.module
+ klass1 = module['YO']
+ klass2 = module['YOUPI']
+ self.assertEqual(klass1.basenames, [])
+ self.assertEqual(klass2.basenames, ['YO'])
+
+ def test_method_base_props(self):
+ """test base properties and method of a astroid method"""
+ klass2 = self.module['YOUPI']
+ # "normal" method
+ method = klass2['method']
+ self.assertEqual(method.name, 'method')
+ self.assertEqual([n.name for n in method.args.args], ['self'])
+ self.assertEqual(method.doc, 'method test')
+ self.assertEqual(method.fromlineno, 47)
+ self.assertEqual(method.type, 'method')
+ # class method
+ method = klass2['class_method']
+ self.assertEqual([n.name for n in method.args.args], ['cls'])
+ self.assertEqual(method.type, 'classmethod')
+ # static method
+ method = klass2['static_method']
+ self.assertEqual(method.args.args, [])
+ self.assertEqual(method.type, 'staticmethod')
+
+ def test_method_locals(self):
+ """test the 'locals' dictionary of a astroid method"""
+ method = self.module['YOUPI']['method']
+ _locals = method.locals
+ keys = sorted(_locals)
+ if sys.version_info < (3, 0):
+ self.assertEqual(len(_locals), 5)
+ self.assertEqual(keys, ['a', 'autre', 'b', 'local', 'self'])
+ else:# ListComp variables are no more accessible outside
+ self.assertEqual(len(_locals), 3)
+ self.assertEqual(keys, ['autre', 'local', 'self'])
+
+
+class ModuleBuildTest(resources.SysPathSetup, FileBuildTest):
+
+ def setUp(self):
+ super(ModuleBuildTest, self).setUp()
+ abuilder = builder.AstroidBuilder()
+ import data.module
+ self.module = abuilder.module_build(data.module, 'data.module')
+
+@unittest.skipIf(IS_PY3, "guess_encoding not used on Python 3")
+class TestGuessEncoding(unittest.TestCase):
+ def setUp(self):
+ self.guess_encoding = builder._guess_encoding
+
+ def testEmacs(self):
+ e = self.guess_encoding('# -*- coding: UTF-8 -*-')
+ self.assertEqual(e, 'UTF-8')
+ e = self.guess_encoding('# -*- coding:UTF-8 -*-')
+ self.assertEqual(e, 'UTF-8')
+ e = self.guess_encoding('''
+ ### -*- coding: ISO-8859-1 -*-
+ ''')
+ self.assertEqual(e, 'ISO-8859-1')
+ e = self.guess_encoding('''
+
+ ### -*- coding: ISO-8859-1 -*-
+ ''')
+ self.assertIsNone(e)
+
+ def testVim(self):
+ e = self.guess_encoding('# vim:fileencoding=UTF-8')
+ self.assertEqual(e, 'UTF-8')
+ e = self.guess_encoding('''
+ ### vim:fileencoding=ISO-8859-1
+ ''')
+ self.assertEqual(e, 'ISO-8859-1')
+ e = self.guess_encoding('''
+
+ ### vim:fileencoding= ISO-8859-1
+ ''')
+ self.assertIsNone(e)
+
+ def test_wrong_coding(self):
+ # setting "coding" varaible
+ e = self.guess_encoding("coding = UTF-8")
+ self.assertIsNone(e)
+ # setting a dictionnary entry
+ e = self.guess_encoding("coding:UTF-8")
+ self.assertIsNone(e)
+ # setting an arguement
+ e = self.guess_encoding("def do_something(a_word_with_coding=None):")
+ self.assertIsNone(e)
+
+ def testUTF8(self):
+ e = self.guess_encoding('\xef\xbb\xbf any UTF-8 data')
+ self.assertEqual(e, 'UTF-8')
+ e = self.guess_encoding(' any UTF-8 data \xef\xbb\xbf')
+ self.assertIsNone(e)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_inference.py astroid-1.3.8/astroid/tests/unittest_inference.py
--- astroid-1.0.1/astroid/tests/unittest_inference.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_inference.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,1644 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""tests for the astroid inference capabilities
+"""
+import sys
+from functools import partial
+import unittest
+
+import six
+
+from astroid import InferenceError, builder, nodes
+from astroid.inference import infer_end as inference_infer_end
+from astroid.bases import YES, Instance, BoundMethod, UnboundMethod,\
+ path_wrapper, BUILTINS
+from astroid import test_utils
+from astroid.tests import resources
+
+
+def get_node_of_class(start_from, klass):
+ return next(start_from.nodes_of_class(klass))
+
+builder = builder.AstroidBuilder()
+
+if sys.version_info < (3, 0):
+ EXC_MODULE = 'exceptions'
+else:
+ EXC_MODULE = BUILTINS
+
+
+class InferenceUtilsTest(unittest.TestCase):
+
+ def test_path_wrapper(self):
+ def infer_default(self, *args):
+ raise InferenceError
+ infer_default = path_wrapper(infer_default)
+ infer_end = path_wrapper(inference_infer_end)
+ with self.assertRaises(InferenceError):
+ next(infer_default(1))
+ self.assertEqual(next(infer_end(1)), 1)
+
+
+def _assertInferElts(node_type, self, node, elts):
+ infered = next(node.infer())
+ self.assertIsInstance(infered, node_type)
+ self.assertEqual(sorted(elt.value for elt in infered.elts),
+ elts)
+
+def partialmethod(func, arg):
+ """similar to functools.partial but return a lambda instead of a class so returned value may be
+ turned into a method.
+ """
+ return lambda *args, **kwargs: func(arg, *args, **kwargs)
+
+class InferenceTest(resources.SysPathSetup, unittest.TestCase):
+
+ # additional assertInfer* method for builtin types
+
+ def assertInferConst(self, node, expected):
+ infered = next(node.infer())
+ self.assertIsInstance(infered, nodes.Const)
+ self.assertEqual(infered.value, expected)
+
+ def assertInferDict(self, node, expected):
+ infered = next(node.infer())
+ self.assertIsInstance(infered, nodes.Dict)
+
+ elts = set([(key.value, value.value)
+ for (key, value) in infered.items])
+ self.assertEqual(sorted(elts), sorted(expected.items()))
+
+ assertInferTuple = partialmethod(_assertInferElts, nodes.Tuple)
+ assertInferList = partialmethod(_assertInferElts, nodes.List)
+ assertInferSet = partialmethod(_assertInferElts, nodes.Set)
+
+ CODE = '''
+ class C(object):
+ "new style"
+ attr = 4
+
+ def meth1(self, arg1, optarg=0):
+ var = object()
+ print ("yo", arg1, optarg)
+ self.iattr = "hop"
+ return var
+
+ def meth2(self):
+ self.meth1(*self.meth3)
+
+ def meth3(self, d=attr):
+ b = self.attr
+ c = self.iattr
+ return b, c
+
+ ex = Exception("msg")
+ v = C().meth1(1)
+ m_unbound = C.meth1
+ m_bound = C().meth1
+ a, b, c = ex, 1, "bonjour"
+ [d, e, f] = [ex, 1.0, ("bonjour", v)]
+ g, h = f
+ i, (j, k) = "glup", f
+
+ a, b= b, a # Gasp !
+ '''
+
+ ast = test_utils.build_module(CODE, __name__)
+
+ def test_module_inference(self):
+ infered = self.ast.infer()
+ obj = next(infered)
+ self.assertEqual(obj.name, __name__)
+ self.assertEqual(obj.root().name, __name__)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_class_inference(self):
+ infered = self.ast['C'].infer()
+ obj = next(infered)
+ self.assertEqual(obj.name, 'C')
+ self.assertEqual(obj.root().name, __name__)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_function_inference(self):
+ infered = self.ast['C']['meth1'].infer()
+ obj = next(infered)
+ self.assertEqual(obj.name, 'meth1')
+ self.assertEqual(obj.root().name, __name__)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_builtin_name_inference(self):
+ infered = self.ast['C']['meth1']['var'].infer()
+ var = next(infered)
+ self.assertEqual(var.name, 'object')
+ self.assertEqual(var.root().name, BUILTINS)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_tupleassign_name_inference(self):
+ infered = self.ast['a'].infer()
+ exc = next(infered)
+ self.assertIsInstance(exc, Instance)
+ self.assertEqual(exc.name, 'Exception')
+ self.assertEqual(exc.root().name, EXC_MODULE)
+ self.assertRaises(StopIteration, partial(next, infered))
+ infered = self.ast['b'].infer()
+ const = next(infered)
+ self.assertIsInstance(const, nodes.Const)
+ self.assertEqual(const.value, 1)
+ self.assertRaises(StopIteration, partial(next, infered))
+ infered = self.ast['c'].infer()
+ const = next(infered)
+ self.assertIsInstance(const, nodes.Const)
+ self.assertEqual(const.value, "bonjour")
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_listassign_name_inference(self):
+ infered = self.ast['d'].infer()
+ exc = next(infered)
+ self.assertIsInstance(exc, Instance)
+ self.assertEqual(exc.name, 'Exception')
+ self.assertEqual(exc.root().name, EXC_MODULE)
+ self.assertRaises(StopIteration, partial(next, infered))
+ infered = self.ast['e'].infer()
+ const = next(infered)
+ self.assertIsInstance(const, nodes.Const)
+ self.assertEqual(const.value, 1.0)
+ self.assertRaises(StopIteration, partial(next, infered))
+ infered = self.ast['f'].infer()
+ const = next(infered)
+ self.assertIsInstance(const, nodes.Tuple)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_advanced_tupleassign_name_inference1(self):
+ infered = self.ast['g'].infer()
+ const = next(infered)
+ self.assertIsInstance(const, nodes.Const)
+ self.assertEqual(const.value, "bonjour")
+ self.assertRaises(StopIteration, partial(next, infered))
+ infered = self.ast['h'].infer()
+ var = next(infered)
+ self.assertEqual(var.name, 'object')
+ self.assertEqual(var.root().name, BUILTINS)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_advanced_tupleassign_name_inference2(self):
+ infered = self.ast['i'].infer()
+ const = next(infered)
+ self.assertIsInstance(const, nodes.Const)
+ self.assertEqual(const.value, u"glup")
+ self.assertRaises(StopIteration, partial(next, infered))
+ infered = self.ast['j'].infer()
+ const = next(infered)
+ self.assertIsInstance(const, nodes.Const)
+ self.assertEqual(const.value, "bonjour")
+ self.assertRaises(StopIteration, partial(next, infered))
+ infered = self.ast['k'].infer()
+ var = next(infered)
+ self.assertEqual(var.name, 'object')
+ self.assertEqual(var.root().name, BUILTINS)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_swap_assign_inference(self):
+ infered = self.ast.locals['a'][1].infer()
+ const = next(infered)
+ self.assertIsInstance(const, nodes.Const)
+ self.assertEqual(const.value, 1)
+ self.assertRaises(StopIteration, partial(next, infered))
+ infered = self.ast.locals['b'][1].infer()
+ exc = next(infered)
+ self.assertIsInstance(exc, Instance)
+ self.assertEqual(exc.name, 'Exception')
+ self.assertEqual(exc.root().name, EXC_MODULE)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_getattr_inference1(self):
+ infered = self.ast['ex'].infer()
+ exc = next(infered)
+ self.assertIsInstance(exc, Instance)
+ self.assertEqual(exc.name, 'Exception')
+ self.assertEqual(exc.root().name, EXC_MODULE)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_getattr_inference2(self):
+ infered = get_node_of_class(self.ast['C']['meth2'], nodes.Getattr).infer()
+ meth1 = next(infered)
+ self.assertEqual(meth1.name, 'meth1')
+ self.assertEqual(meth1.root().name, __name__)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_getattr_inference3(self):
+ infered = self.ast['C']['meth3']['b'].infer()
+ const = next(infered)
+ self.assertIsInstance(const, nodes.Const)
+ self.assertEqual(const.value, 4)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_getattr_inference4(self):
+ infered = self.ast['C']['meth3']['c'].infer()
+ const = next(infered)
+ self.assertIsInstance(const, nodes.Const)
+ self.assertEqual(const.value, "hop")
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_callfunc_inference(self):
+ infered = self.ast['v'].infer()
+ meth1 = next(infered)
+ self.assertIsInstance(meth1, Instance)
+ self.assertEqual(meth1.name, 'object')
+ self.assertEqual(meth1.root().name, BUILTINS)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_unbound_method_inference(self):
+ infered = self.ast['m_unbound'].infer()
+ meth1 = next(infered)
+ self.assertIsInstance(meth1, UnboundMethod)
+ self.assertEqual(meth1.name, 'meth1')
+ self.assertEqual(meth1.parent.frame().name, 'C')
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_bound_method_inference(self):
+ infered = self.ast['m_bound'].infer()
+ meth1 = next(infered)
+ self.assertIsInstance(meth1, BoundMethod)
+ self.assertEqual(meth1.name, 'meth1')
+ self.assertEqual(meth1.parent.frame().name, 'C')
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_args_default_inference1(self):
+ optarg = test_utils.get_name_node(self.ast['C']['meth1'], 'optarg')
+ infered = optarg.infer()
+ obj1 = next(infered)
+ self.assertIsInstance(obj1, nodes.Const)
+ self.assertEqual(obj1.value, 0)
+ obj1 = next(infered)
+ self.assertIs(obj1, YES, obj1)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_args_default_inference2(self):
+ infered = self.ast['C']['meth3'].ilookup('d')
+ obj1 = next(infered)
+ self.assertIsInstance(obj1, nodes.Const)
+ self.assertEqual(obj1.value, 4)
+ obj1 = next(infered)
+ self.assertIs(obj1, YES, obj1)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_inference_restrictions(self):
+ infered = test_utils.get_name_node(self.ast['C']['meth1'], 'arg1').infer()
+ obj1 = next(infered)
+ self.assertIs(obj1, YES, obj1)
+ self.assertRaises(StopIteration, partial(next, infered))
+
+ def test_ancestors_inference(self):
+ code = '''
+ class A(object): #@
+ pass
+
+ class A(A): #@
+ pass
+ '''
+ a1, a2 = test_utils.extract_node(code, __name__)
+ a2_ancestors = list(a2.ancestors())
+ self.assertEqual(len(a2_ancestors), 2)
+ self.assertIs(a2_ancestors[0], a1)
+
+ def test_ancestors_inference2(self):
+ code = '''
+ class A(object): #@
+ pass
+
+ class B(A): #@
+ pass
+
+ class A(B): #@
+ pass
+ '''
+ a1, b, a2 = test_utils.extract_node(code, __name__)
+ a2_ancestors = list(a2.ancestors())
+ self.assertEqual(len(a2_ancestors), 3)
+ self.assertIs(a2_ancestors[0], b)
+ self.assertIs(a2_ancestors[1], a1)
+
+
+ def test_f_arg_f(self):
+ code = '''
+ def f(f=1):
+ return f
+
+ a = f()
+ '''
+ ast = test_utils.build_module(code, __name__)
+ a = ast['a']
+ a_infered = a.infered()
+ self.assertEqual(a_infered[0].value, 1)
+ self.assertEqual(len(a_infered), 1)
+
+ def test_exc_ancestors(self):
+ code = '''
+ def f():
+ raise __(NotImplementedError)
+ '''
+ error = test_utils.extract_node(code, __name__)
+ nie = error.infered()[0]
+ self.assertIsInstance(nie, nodes.Class)
+ nie_ancestors = [c.name for c in nie.ancestors()]
+ if sys.version_info < (3, 0):
+ self.assertEqual(nie_ancestors, ['RuntimeError', 'StandardError', 'Exception', 'BaseException', 'object'])
+ else:
+ self.assertEqual(nie_ancestors, ['RuntimeError', 'Exception', 'BaseException', 'object'])
+
+ def test_except_inference(self):
+ code = '''
+ try:
+ print (hop)
+ except NameError as ex:
+ ex1 = ex
+ except Exception as ex:
+ ex2 = ex
+ raise
+ '''
+ ast = test_utils.build_module(code, __name__)
+ ex1 = ast['ex1']
+ ex1_infer = ex1.infer()
+ ex1 = next(ex1_infer)
+ self.assertIsInstance(ex1, Instance)
+ self.assertEqual(ex1.name, 'NameError')
+ self.assertRaises(StopIteration, partial(next, ex1_infer))
+ ex2 = ast['ex2']
+ ex2_infer = ex2.infer()
+ ex2 = next(ex2_infer)
+ self.assertIsInstance(ex2, Instance)
+ self.assertEqual(ex2.name, 'Exception')
+ self.assertRaises(StopIteration, partial(next, ex2_infer))
+
+ def test_del1(self):
+ code = '''
+ del undefined_attr
+ '''
+ delete = test_utils.extract_node(code, __name__)
+ self.assertRaises(InferenceError, delete.infer)
+
+ def test_del2(self):
+ code = '''
+ a = 1
+ b = a
+ del a
+ c = a
+ a = 2
+ d = a
+ '''
+ ast = test_utils.build_module(code, __name__)
+ n = ast['b']
+ n_infer = n.infer()
+ infered = next(n_infer)
+ self.assertIsInstance(infered, nodes.Const)
+ self.assertEqual(infered.value, 1)
+ self.assertRaises(StopIteration, partial(next, n_infer))
+ n = ast['c']
+ n_infer = n.infer()
+ self.assertRaises(InferenceError, partial(next, n_infer))
+ n = ast['d']
+ n_infer = n.infer()
+ infered = next(n_infer)
+ self.assertIsInstance(infered, nodes.Const)
+ self.assertEqual(infered.value, 2)
+ self.assertRaises(StopIteration, partial(next, n_infer))
+
+ def test_builtin_types(self):
+ code = '''
+ l = [1]
+ t = (2,)
+ d = {}
+ s = ''
+ s2 = '_'
+ '''
+ ast = test_utils.build_module(code, __name__)
+ n = ast['l']
+ infered = next(n.infer())
+ self.assertIsInstance(infered, nodes.List)
+ self.assertIsInstance(infered, Instance)
+ self.assertEqual(infered.getitem(0).value, 1)
+ self.assertIsInstance(infered._proxied, nodes.Class)
+ self.assertEqual(infered._proxied.name, 'list')
+ self.assertIn('append', infered._proxied.locals)
+ n = ast['t']
+ infered = next(n.infer())
+ self.assertIsInstance(infered, nodes.Tuple)
+ self.assertIsInstance(infered, Instance)
+ self.assertEqual(infered.getitem(0).value, 2)
+ self.assertIsInstance(infered._proxied, nodes.Class)
+ self.assertEqual(infered._proxied.name, 'tuple')
+ n = ast['d']
+ infered = next(n.infer())
+ self.assertIsInstance(infered, nodes.Dict)
+ self.assertIsInstance(infered, Instance)
+ self.assertIsInstance(infered._proxied, nodes.Class)
+ self.assertEqual(infered._proxied.name, 'dict')
+ self.assertIn('get', infered._proxied.locals)
+ n = ast['s']
+ infered = next(n.infer())
+ self.assertIsInstance(infered, nodes.Const)
+ self.assertIsInstance(infered, Instance)
+ self.assertEqual(infered.name, 'str')
+ self.assertIn('lower', infered._proxied.locals)
+ n = ast['s2']
+ infered = next(n.infer())
+ self.assertEqual(infered.getitem(0).value, '_')
+
+ def test_builtin_types(self):
+ code = 's = {1}'
+ ast = test_utils.build_module(code, __name__)
+ n = ast['s']
+ infered = next(n.infer())
+ self.assertIsInstance(infered, nodes.Set)
+ self.assertIsInstance(infered, Instance)
+ self.assertEqual(infered.name, 'set')
+ self.assertIn('remove', infered._proxied.locals)
+
+ @test_utils.require_version(maxver='3.0')
+ def test_unicode_type(self):
+ code = '''u = u""'''
+ ast = test_utils.build_module(code, __name__)
+ n = ast['u']
+ infered = next(n.infer())
+ self.assertIsInstance(infered, nodes.Const)
+ self.assertIsInstance(infered, Instance)
+ self.assertEqual(infered.name, 'unicode')
+ self.assertIn('lower', infered._proxied.locals)
+
+ def test_descriptor_are_callable(self):
+ code = '''
+ class A:
+ statm = staticmethod(open)
+ clsm = classmethod('whatever')
+ '''
+ ast = test_utils.build_module(code, __name__)
+ statm = next(ast['A'].igetattr('statm'))
+ self.assertTrue(statm.callable())
+ clsm = next(ast['A'].igetattr('clsm'))
+ self.assertTrue(clsm.callable())
+
+ def test_bt_ancestor_crash(self):
+ code = '''
+ class Warning(Warning):
+ pass
+ '''
+ ast = test_utils.build_module(code, __name__)
+ w = ast['Warning']
+ ancestors = w.ancestors()
+ ancestor = next(ancestors)
+ self.assertEqual(ancestor.name, 'Warning')
+ self.assertEqual(ancestor.root().name, EXC_MODULE)
+ ancestor = next(ancestors)
+ self.assertEqual(ancestor.name, 'Exception')
+ self.assertEqual(ancestor.root().name, EXC_MODULE)
+ ancestor = next(ancestors)
+ self.assertEqual(ancestor.name, 'BaseException')
+ self.assertEqual(ancestor.root().name, EXC_MODULE)
+ ancestor = next(ancestors)
+ self.assertEqual(ancestor.name, 'object')
+ self.assertEqual(ancestor.root().name, BUILTINS)
+ self.assertRaises(StopIteration, partial(next, ancestors))
+
+ def test_qqch(self):
+ code = '''
+ from astroid.modutils import load_module_from_name
+ xxx = load_module_from_name('__pkginfo__')
+ '''
+ ast = test_utils.build_module(code, __name__)
+ xxx = ast['xxx']
+ self.assertSetEqual({n.__class__ for n in xxx.infered()},
+ {nodes.Const, YES.__class__})
+
+ def test_method_argument(self):
+ code = '''
+ class ErudiEntitySchema:
+ """a entity has a type, a set of subject and or object relations"""
+ def __init__(self, e_type, **kwargs):
+ kwargs['e_type'] = e_type.capitalize().encode()
+
+ def meth(self, e_type, *args, **kwargs):
+ kwargs['e_type'] = e_type.capitalize().encode()
+ print(args)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ arg = test_utils.get_name_node(ast['ErudiEntitySchema']['__init__'], 'e_type')
+ self.assertEqual([n.__class__ for n in arg.infer()],
+ [YES.__class__])
+ arg = test_utils.get_name_node(ast['ErudiEntitySchema']['__init__'], 'kwargs')
+ self.assertEqual([n.__class__ for n in arg.infer()],
+ [nodes.Dict])
+ arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'e_type')
+ self.assertEqual([n.__class__ for n in arg.infer()],
+ [YES.__class__])
+ arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'args')
+ self.assertEqual([n.__class__ for n in arg.infer()],
+ [nodes.Tuple])
+ arg = test_utils.get_name_node(ast['ErudiEntitySchema']['meth'], 'kwargs')
+ self.assertEqual([n.__class__ for n in arg.infer()],
+ [nodes.Dict])
+
+ def test_tuple_then_list(self):
+ code = '''
+ def test_view(rql, vid, tags=()):
+ tags = list(tags)
+ __(tags).append(vid)
+ '''
+ name = test_utils.extract_node(code, __name__)
+ it = name.infer()
+ tags = next(it)
+ self.assertIsInstance(tags, nodes.List)
+ self.assertEqual(tags.elts, [])
+ with self.assertRaises(StopIteration):
+ next(it)
+
+ def test_mulassign_inference(self):
+ code = '''
+ def first_word(line):
+ """Return the first word of a line"""
+
+ return line.split()[0]
+
+ def last_word(line):
+ """Return last word of a line"""
+
+ return line.split()[-1]
+
+ def process_line(word_pos):
+ """Silly function: returns (ok, callable) based on argument.
+
+ For test purpose only.
+ """
+
+ if word_pos > 0:
+ return (True, first_word)
+ elif word_pos < 0:
+ return (True, last_word)
+ else:
+ return (False, None)
+
+ if __name__ == '__main__':
+
+ line_number = 0
+ for a_line in file('test_callable.py'):
+ tupletest = process_line(line_number)
+ (ok, fct) = process_line(line_number)
+ if ok:
+ fct(a_line)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ self.assertEqual(len(list(ast['process_line'].infer_call_result(
+ None))), 3)
+ self.assertEqual(len(list(ast['tupletest'].infer())), 3)
+ values = ['Function(first_word)', 'Function(last_word)', 'Const(NoneType)']
+ self.assertEqual([str(infered)
+ for infered in ast['fct'].infer()], values)
+
+ def test_float_complex_ambiguity(self):
+ code = '''
+ def no_conjugate_member(magic_flag): #@
+ """should not raise E1101 on something.conjugate"""
+ if magic_flag:
+ something = 1.0
+ else:
+ something = 1.0j
+ if isinstance(something, float):
+ return something
+ return __(something).conjugate()
+ '''
+ func, retval = test_utils.extract_node(code, __name__)
+ self.assertEqual(
+ [i.value for i in func.ilookup('something')],
+ [1.0, 1.0j])
+ self.assertEqual(
+ [i.value for i in retval.infer()],
+ [1.0, 1.0j])
+
+ def test_lookup_cond_branches(self):
+ code = '''
+ def no_conjugate_member(magic_flag):
+ """should not raise E1101 on something.conjugate"""
+ something = 1.0
+ if magic_flag:
+ something = 1.0j
+ return something.conjugate()
+ '''
+ ast = test_utils.build_module(code, __name__)
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'something', -1).infer()], [1.0, 1.0j])
+
+
+ def test_simple_subscript(self):
+ code = '''
+ a = [1, 2, 3][0]
+ b = (1, 2, 3)[1]
+ c = (1, 2, 3)[-1]
+ d = a + b + c
+ print (d)
+ e = {'key': 'value'}
+ f = e['key']
+ print (f)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'a', -1).infer()], [1])
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'b', -1).infer()], [2])
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'c', -1).infer()], [3])
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'd', -1).infer()], [6])
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'f', -1).infer()], ['value'])
+
+ #def test_simple_tuple(self):
+ #"""test case for a simple tuple value"""
+ ## XXX tuple inference is not implemented ...
+ #code = """
+#a = (1,)
+#b = (22,)
+#some = a + b
+#"""
+ #ast = builder.string_build(code, __name__, __file__)
+ #self.assertEqual(ast['some'].infer.next().as_string(), "(1, 22)")
+
+ def test_simple_for(self):
+ code = '''
+ for a in [1, 2, 3]:
+ print (a)
+ for b,c in [(1,2), (3,4)]:
+ print (b)
+ print (c)
+
+ print ([(d,e) for e,d in ([1,2], [3,4])])
+ '''
+ ast = test_utils.build_module(code, __name__)
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'a', -1).infer()], [1, 2, 3])
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'b', -1).infer()], [1, 3])
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'c', -1).infer()], [2, 4])
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'd', -1).infer()], [2, 4])
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'e', -1).infer()], [1, 3])
+
+
+ def test_simple_for_genexpr(self):
+ code = '''
+ print ((d,e) for e,d in ([1,2], [3,4]))
+ '''
+ ast = test_utils.build_module(code, __name__)
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'd', -1).infer()], [2, 4])
+ self.assertEqual([i.value for i in
+ test_utils.get_name_node(ast, 'e', -1).infer()], [1, 3])
+
+
+ def test_builtin_help(self):
+ code = '''
+ help()
+ '''
+ # XXX failing since __builtin__.help assignment has
+ # been moved into a function...
+ node = test_utils.extract_node(code, __name__)
+ infered = list(node.func.infer())
+ self.assertEqual(len(infered), 1, infered)
+ self.assertIsInstance(infered[0], Instance)
+ self.assertEqual(infered[0].name, "_Helper")
+
+ def test_builtin_open(self):
+ code = '''
+ open("toto.txt")
+ '''
+ node = test_utils.extract_node(code, __name__).func
+ infered = list(node.infer())
+ self.assertEqual(len(infered), 1)
+ if hasattr(sys, 'pypy_version_info'):
+ self.assertIsInstance(infered[0], nodes.Class)
+ self.assertEqual(infered[0].name, 'file')
+ else:
+ self.assertIsInstance(infered[0], nodes.Function)
+ self.assertEqual(infered[0].name, 'open')
+
+ def test_callfunc_context_func(self):
+ code = '''
+ def mirror(arg=None):
+ return arg
+
+ un = mirror(1)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ infered = list(ast.igetattr('un'))
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Const)
+ self.assertEqual(infered[0].value, 1)
+
+ def test_callfunc_context_lambda(self):
+ code = '''
+ mirror = lambda x=None: x
+
+ un = mirror(1)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ infered = list(ast.igetattr('mirror'))
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Lambda)
+ infered = list(ast.igetattr('un'))
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Const)
+ self.assertEqual(infered[0].value, 1)
+
+ def test_factory_method(self):
+ code = '''
+ class Super(object):
+ @classmethod
+ def instance(cls):
+ return cls()
+
+ class Sub(Super):
+ def method(self):
+ print ('method called')
+
+ sub = Sub.instance()
+ '''
+ ast = test_utils.build_module(code, __name__)
+ infered = list(ast.igetattr('sub'))
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], Instance)
+ self.assertEqual(infered[0]._proxied.name, 'Sub')
+
+
+ def test_import_as(self):
+ code = '''
+ import os.path as osp
+ print (osp.dirname(__file__))
+
+ from os.path import exists as e
+ assert e(__file__)
+
+ from new import code as make_code
+ print (make_code)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ infered = list(ast.igetattr('osp'))
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Module)
+ self.assertEqual(infered[0].name, 'os.path')
+ infered = list(ast.igetattr('e'))
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Function)
+ self.assertEqual(infered[0].name, 'exists')
+ if sys.version_info >= (3, 0):
+ self.skipTest(' module has been removed')
+ infered = list(ast.igetattr('make_code'))
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], Instance)
+ self.assertEqual(str(infered[0]),
+ 'Instance of %s.type' % BUILTINS)
+
+ def _test_const_infered(self, node, value):
+ infered = list(node.infer())
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Const)
+ self.assertEqual(infered[0].value, value)
+
+ def test_unary_not(self):
+ for code in ('a = not (1,); b = not ()',
+ 'a = not {1:2}; b = not {}'):
+ ast = builder.string_build(code, __name__, __file__)
+ self._test_const_infered(ast['a'], False)
+ self._test_const_infered(ast['b'], True)
+
+ def test_binary_op_int_add(self):
+ ast = builder.string_build('a = 1 + 2', __name__, __file__)
+ self._test_const_infered(ast['a'], 3)
+
+ def test_binary_op_int_sub(self):
+ ast = builder.string_build('a = 1 - 2', __name__, __file__)
+ self._test_const_infered(ast['a'], -1)
+
+ def test_binary_op_float_div(self):
+ ast = builder.string_build('a = 1 / 2.', __name__, __file__)
+ self._test_const_infered(ast['a'], 1 / 2.)
+
+ def test_binary_op_str_mul(self):
+ ast = builder.string_build('a = "*" * 40', __name__, __file__)
+ self._test_const_infered(ast['a'], "*" * 40)
+
+ def test_binary_op_bitand(self):
+ ast = builder.string_build('a = 23&20', __name__, __file__)
+ self._test_const_infered(ast['a'], 23&20)
+
+ def test_binary_op_bitor(self):
+ ast = builder.string_build('a = 23|8', __name__, __file__)
+ self._test_const_infered(ast['a'], 23|8)
+
+ def test_binary_op_bitxor(self):
+ ast = builder.string_build('a = 23^9', __name__, __file__)
+ self._test_const_infered(ast['a'], 23^9)
+
+ def test_binary_op_shiftright(self):
+ ast = builder.string_build('a = 23 >>1', __name__, __file__)
+ self._test_const_infered(ast['a'], 23>>1)
+
+ def test_binary_op_shiftleft(self):
+ ast = builder.string_build('a = 23 <<1', __name__, __file__)
+ self._test_const_infered(ast['a'], 23<<1)
+
+
+ def test_binary_op_list_mul(self):
+ for code in ('a = [[]] * 2', 'a = 2 * [[]]'):
+ ast = builder.string_build(code, __name__, __file__)
+ infered = list(ast['a'].infer())
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.List)
+ self.assertEqual(len(infered[0].elts), 2)
+ self.assertIsInstance(infered[0].elts[0], nodes.List)
+ self.assertIsInstance(infered[0].elts[1], nodes.List)
+
+ def test_binary_op_list_mul_none(self):
+ 'test correct handling on list multiplied by None'
+ ast = builder.string_build('a = [1] * None\nb = [1] * "r"')
+ infered = ast['a'].infered()
+ self.assertEqual(len(infered), 1)
+ self.assertEqual(infered[0], YES)
+ infered = ast['b'].infered()
+ self.assertEqual(len(infered), 1)
+ self.assertEqual(infered[0], YES)
+
+
+ def test_binary_op_tuple_add(self):
+ ast = builder.string_build('a = (1,) + (2,)', __name__, __file__)
+ infered = list(ast['a'].infer())
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Tuple)
+ self.assertEqual(len(infered[0].elts), 2)
+ self.assertEqual(infered[0].elts[0].value, 1)
+ self.assertEqual(infered[0].elts[1].value, 2)
+
+ def test_binary_op_custom_class(self):
+ code = '''
+ class myarray:
+ def __init__(self, array):
+ self.array = array
+ def __mul__(self, x):
+ return myarray([2,4,6])
+ def astype(self):
+ return "ASTYPE"
+
+ def randint(maximum):
+ if maximum is not None:
+ return myarray([1,2,3]) * 2
+ else:
+ return int(5)
+
+ x = randint(1)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ infered = list(ast.igetattr('x'))
+ self.assertEqual(len(infered), 2)
+ value = [str(v) for v in infered]
+ # The __name__ trick here makes it work when invoked directly
+ # (__name__ == '__main__') and through pytest (__name__ ==
+ # 'unittest_inference')
+ self.assertEqual(value, ['Instance of %s.myarray' % __name__,
+ 'Instance of %s.int' % BUILTINS])
+
+ def test_nonregr_lambda_arg(self):
+ code = '''
+ def f(g = lambda: None):
+ __(g()).x
+'''
+ callfuncnode = test_utils.extract_node(code)
+ infered = list(callfuncnode.infer())
+ self.assertEqual(len(infered), 2, infered)
+ infered.remove(YES)
+ self.assertIsInstance(infered[0], nodes.Const)
+ self.assertIsNone(infered[0].value)
+
+ def test_nonregr_getitem_empty_tuple(self):
+ code = '''
+ def f(x):
+ a = ()[x]
+ '''
+ ast = test_utils.build_module(code, __name__)
+ infered = list(ast['f'].ilookup('a'))
+ self.assertEqual(len(infered), 1)
+ self.assertEqual(infered[0], YES)
+
+ def test_nonregr_instance_attrs(self):
+ """non regression for instance_attrs infinite loop : pylint / #4"""
+
+ code = """
+ class Foo(object):
+
+ def set_42(self):
+ self.attr = 42
+
+ class Bar(Foo):
+
+ def __init__(self):
+ self.attr = 41
+ """
+ ast = test_utils.build_module(code, __name__)
+ foo_class = ast['Foo']
+ bar_class = ast['Bar']
+ bar_self = ast['Bar']['__init__']['self']
+ assattr = bar_class.instance_attrs['attr'][0]
+ self.assertEqual(len(foo_class.instance_attrs['attr']), 1)
+ self.assertEqual(len(bar_class.instance_attrs['attr']), 1)
+ self.assertEqual(bar_class.instance_attrs, {'attr': [assattr]})
+ # call 'instance_attr' via 'Instance.getattr' to trigger the bug:
+ instance = bar_self.infered()[0]
+ instance.getattr('attr')
+ self.assertEqual(len(bar_class.instance_attrs['attr']), 1)
+ self.assertEqual(len(foo_class.instance_attrs['attr']), 1)
+ self.assertEqual(bar_class.instance_attrs, {'attr': [assattr]})
+
+ def test_python25_generator_exit(self):
+ sys.stderr = six.StringIO()
+ data = "b = {}[str(0)+''].a"
+ ast = builder.string_build(data, __name__, __file__)
+ list(ast['b'].infer())
+ output = sys.stderr.getvalue()
+ # I have no idea how to test for this in another way...
+ self.assertNotIn("RuntimeError", output, "Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in ignored")
+ sys.stderr = sys.__stderr__
+
+ def test_python25_relative_import(self):
+ data = "from ...logilab.common import date; print (date)"
+ # !! FIXME also this relative import would not work 'in real' (no __init__.py in test/)
+ # the test works since we pretend we have a package by passing the full modname
+ ast = builder.string_build(data, 'astroid.test.unittest_inference', __file__)
+ infered = next(test_utils.get_name_node(ast, 'date').infer())
+ self.assertIsInstance(infered, nodes.Module)
+ self.assertEqual(infered.name, 'logilab.common.date')
+
+ def test_python25_no_relative_import(self):
+ ast = resources.build_file('data/package/absimport.py')
+ self.assertTrue(ast.absolute_import_activated(), True)
+ infered = next(test_utils.get_name_node(ast, 'import_package_subpackage_module').infer())
+ # failed to import since absolute_import is activated
+ self.assertIs(infered, YES)
+
+ def test_nonregr_absolute_import(self):
+ ast = resources.build_file('data/absimp/string.py', 'data.absimp.string')
+ self.assertTrue(ast.absolute_import_activated(), True)
+ infered = next(test_utils.get_name_node(ast, 'string').infer())
+ self.assertIsInstance(infered, nodes.Module)
+ self.assertEqual(infered.name, 'string')
+ self.assertIn('ascii_letters', infered.locals)
+
+ def test_mechanize_open(self):
+ try:
+ import mechanize # pylint: disable=unused-variable
+ except ImportError:
+ self.skipTest('require mechanize installed')
+ data = '''
+ from mechanize import Browser
+ print(Browser)
+ b = Browser()
+ '''
+ ast = test_utils.build_module(data, __name__)
+ browser = next(test_utils.get_name_node(ast, 'Browser').infer())
+ self.assertIsInstance(browser, nodes.Class)
+ bopen = list(browser.igetattr('open'))
+ self.skipTest('the commit said: "huum, see that later"')
+ self.assertEqual(len(bopen), 1)
+ self.assertIsInstance(bopen[0], nodes.Function)
+ self.assertTrue(bopen[0].callable())
+ b = next(test_utils.get_name_node(ast, 'b').infer())
+ self.assertIsInstance(b, Instance)
+ bopen = list(b.igetattr('open'))
+ self.assertEqual(len(bopen), 1)
+ self.assertIsInstance(bopen[0], BoundMethod)
+ self.assertTrue(bopen[0].callable())
+
+ def test_property(self):
+ code = '''
+ from smtplib import SMTP
+ class SendMailController(object):
+
+ @property
+ def smtp(self):
+ return SMTP(mailhost, port)
+
+ @property
+ def me(self):
+ return self
+
+ my_smtp = SendMailController().smtp
+ my_me = SendMailController().me
+ '''
+ decorators = set(['%s.property' % BUILTINS])
+ ast = test_utils.build_module(code, __name__)
+ self.assertEqual(ast['SendMailController']['smtp'].decoratornames(),
+ decorators)
+ propinfered = list(ast.body[2].value.infer())
+ self.assertEqual(len(propinfered), 1)
+ propinfered = propinfered[0]
+ self.assertIsInstance(propinfered, Instance)
+ self.assertEqual(propinfered.name, 'SMTP')
+ self.assertEqual(propinfered.root().name, 'smtplib')
+ self.assertEqual(ast['SendMailController']['me'].decoratornames(),
+ decorators)
+ propinfered = list(ast.body[3].value.infer())
+ self.assertEqual(len(propinfered), 1)
+ propinfered = propinfered[0]
+ self.assertIsInstance(propinfered, Instance)
+ self.assertEqual(propinfered.name, 'SendMailController')
+ self.assertEqual(propinfered.root().name, __name__)
+
+
+ def test_im_func_unwrap(self):
+ code = '''
+ class EnvBasedTC:
+ def pactions(self):
+ pass
+ pactions = EnvBasedTC.pactions.im_func
+ print (pactions)
+
+ class EnvBasedTC2:
+ pactions = EnvBasedTC.pactions.im_func
+ print (pactions)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ pactions = test_utils.get_name_node(ast, 'pactions')
+ infered = list(pactions.infer())
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Function)
+ pactions = test_utils.get_name_node(ast['EnvBasedTC2'], 'pactions')
+ infered = list(pactions.infer())
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Function)
+
+ def test_augassign(self):
+ code = '''
+ a = 1
+ a += 2
+ print (a)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ infered = list(test_utils.get_name_node(ast, 'a').infer())
+
+ self.assertEqual(len(infered), 1)
+ self.assertIsInstance(infered[0], nodes.Const)
+ self.assertEqual(infered[0].value, 3)
+
+ def test_nonregr_func_arg(self):
+ code = '''
+ def foo(self, bar):
+ def baz():
+ pass
+ def qux():
+ return baz
+ spam = bar(None, qux)
+ print (spam)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ infered = list(test_utils.get_name_node(ast['foo'], 'spam').infer())
+ self.assertEqual(len(infered), 1)
+ self.assertIs(infered[0], YES)
+
+ def test_nonregr_func_global(self):
+ code = '''
+ active_application = None
+
+ def get_active_application():
+ global active_application
+ return active_application
+
+ class Application(object):
+ def __init__(self):
+ global active_application
+ active_application = self
+
+ class DataManager(object):
+ def __init__(self, app=None):
+ self.app = get_active_application()
+ def test(self):
+ p = self.app
+ print (p)
+ '''
+ ast = test_utils.build_module(code, __name__)
+ infered = list(Instance(ast['DataManager']).igetattr('app'))
+ self.assertEqual(len(infered), 2, infered) # None / Instance(Application)
+ infered = list(test_utils.get_name_node(ast['DataManager']['test'], 'p').infer())
+ self.assertEqual(len(infered), 2, infered)
+ for node in infered:
+ if isinstance(node, Instance) and node.name == 'Application':
+ break
+ else:
+ self.fail('expected to find an instance of Application in %s' % infered)
+
+ def test_list_inference(self):
+ """#20464"""
+ code = '''
+ import optparse
+
+ A = []
+ B = []
+
+ def test():
+ xyz = [
+ "foobar=%s" % options.ca,
+ ] + A + B
+
+ if options.bind is not None:
+ xyz.append("bind=%s" % options.bind)
+ return xyz
+
+ def main():
+ global options
+
+ parser = optparse.OptionParser()
+ (options, args) = parser.parse_args()
+
+ Z = test()
+ '''
+ ast = test_utils.build_module(code, __name__)
+ infered = list(ast['Z'].infer())
+ self.assertEqual(len(infered), 1, infered)
+ self.assertIsInstance(infered[0], Instance)
+ self.assertIsInstance(infered[0]._proxied, nodes.Class)
+ self.assertEqual(infered[0]._proxied.name, 'list')
+
+ def test__new__(self):
+ code = '''
+ class NewTest(object):
+ "doc"
+ def __new__(cls, arg):
+ self = object.__new__(cls)
+ self.arg = arg
+ return self
+
+ n = NewTest()
+ '''
+ ast = test_utils.build_module(code, __name__)
+ self.assertRaises(InferenceError, list, ast['NewTest'].igetattr('arg'))
+ n = next(ast['n'].infer())
+ infered = list(n.igetattr('arg'))
+ self.assertEqual(len(infered), 1, infered)
+
+
+ def test_two_parents_from_same_module(self):
+ code = '''
+ from data import nonregr
+ class Xxx(nonregr.Aaa, nonregr.Ccc):
+ "doc"
+ '''
+ ast = test_utils.build_module(code, __name__)
+ parents = list(ast['Xxx'].ancestors())
+ self.assertEqual(len(parents), 3, parents) # Aaa, Ccc, object
+
+ def test_pluggable_inference(self):
+ code = '''
+ from collections import namedtuple
+ A = namedtuple('A', ['a', 'b'])
+ B = namedtuple('B', 'a b')
+ '''
+ ast = test_utils.build_module(code, __name__)
+ aclass = ast['A'].infered()[0]
+ self.assertIsInstance(aclass, nodes.Class)
+ self.assertIn('a', aclass.instance_attrs)
+ self.assertIn('b', aclass.instance_attrs)
+ bclass = ast['B'].infered()[0]
+ self.assertIsInstance(bclass, nodes.Class)
+ self.assertIn('a', bclass.instance_attrs)
+ self.assertIn('b', bclass.instance_attrs)
+
+ def test_infer_arguments(self):
+ code = '''
+ class A(object):
+ def first(self, arg1, arg2):
+ return arg1
+ @classmethod
+ def method(cls, arg1, arg2):
+ return arg2
+ @classmethod
+ def empty(cls):
+ return 2
+ @staticmethod
+ def static(arg1, arg2):
+ return arg1
+ def empty_method(self):
+ return []
+ x = A().first(1, [])
+ y = A.method(1, [])
+ z = A.static(1, [])
+ empty = A.empty()
+ empty_list = A().empty_method()
+ '''
+ ast = test_utils.build_module(code, __name__)
+ int_node = ast['x'].infered()[0]
+ self.assertIsInstance(int_node, nodes.Const)
+ self.assertEqual(int_node.value, 1)
+ list_node = ast['y'].infered()[0]
+ self.assertIsInstance(list_node, nodes.List)
+ int_node = ast['z'].infered()[0]
+ self.assertIsInstance(int_node, nodes.Const)
+ self.assertEqual(int_node.value, 1)
+ empty = ast['empty'].infered()[0]
+ self.assertIsInstance(empty, nodes.Const)
+ self.assertEqual(empty.value, 2)
+ empty_list = ast['empty_list'].infered()[0]
+ self.assertIsInstance(empty_list, nodes.List)
+
+ def test_infer_variable_arguments(self):
+ code = '''
+ def test(*args, **kwargs):
+ vararg = args
+ kwarg = kwargs
+ '''
+ ast = test_utils.build_module(code, __name__)
+ func = ast['test']
+ vararg = func.body[0].value
+ kwarg = func.body[1].value
+
+ kwarg_infered = kwarg.infered()[0]
+ self.assertIsInstance(kwarg_infered, nodes.Dict)
+ self.assertIs(kwarg_infered.parent, func.args)
+
+ vararg_infered = vararg.infered()[0]
+ self.assertIsInstance(vararg_infered, nodes.Tuple)
+ self.assertIs(vararg_infered.parent, func.args)
+
+ def test_infer_nested(self):
+ code = """
+ def nested():
+ from threading import Thread
+
+ class NestedThread(Thread):
+ def __init__(self):
+ Thread.__init__(self)
+ """
+ # Test that inferring Thread.__init__ looks up in
+ # the nested scope.
+ ast = test_utils.build_module(code, __name__)
+ callfunc = next(ast.nodes_of_class(nodes.CallFunc))
+ func = callfunc.func
+ infered = func.infered()[0]
+ self.assertIsInstance(infered, UnboundMethod)
+
+ def test_instance_binary_operations(self):
+ code = """
+ class A(object):
+ def __mul__(self, other):
+ return 42
+ a = A()
+ b = A()
+ sub = a - b
+ mul = a * b
+ """
+ ast = test_utils.build_module(code, __name__)
+ sub = ast['sub'].infered()[0]
+ mul = ast['mul'].infered()[0]
+ self.assertIs(sub, YES)
+ self.assertIsInstance(mul, nodes.Const)
+ self.assertEqual(mul.value, 42)
+
+ def test_instance_binary_operations_parent(self):
+ code = """
+ class A(object):
+ def __mul__(self, other):
+ return 42
+ class B(A):
+ pass
+ a = B()
+ b = B()
+ sub = a - b
+ mul = a * b
+ """
+ ast = test_utils.build_module(code, __name__)
+ sub = ast['sub'].infered()[0]
+ mul = ast['mul'].infered()[0]
+ self.assertIs(sub, YES)
+ self.assertIsInstance(mul, nodes.Const)
+ self.assertEqual(mul.value, 42)
+
+ def test_instance_binary_operations_multiple_methods(self):
+ code = """
+ class A(object):
+ def __mul__(self, other):
+ return 42
+ class B(A):
+ def __mul__(self, other):
+ return [42]
+ a = B()
+ b = B()
+ sub = a - b
+ mul = a * b
+ """
+ ast = test_utils.build_module(code, __name__)
+ sub = ast['sub'].infered()[0]
+ mul = ast['mul'].infered()[0]
+ self.assertIs(sub, YES)
+ self.assertIsInstance(mul, nodes.List)
+ self.assertIsInstance(mul.elts[0], nodes.Const)
+ self.assertEqual(mul.elts[0].value, 42)
+
+ def test_infer_call_result_crash(self):
+ code = """
+ class A(object):
+ def __mul__(self, other):
+ return type.__new__()
+
+ a = A()
+ b = A()
+ c = a * b
+ """
+ ast = test_utils.build_module(code, __name__)
+ node = ast['c']
+ self.assertEqual(node.infered(), [YES])
+
+ def test_infer_empty_nodes(self):
+ # Should not crash when trying to infer EmptyNodes.
+ node = nodes.EmptyNode()
+ self.assertEqual(node.infered(), [YES])
+
+ def test_infinite_loop_for_decorators(self):
+ # Issue https://bitbucket.org/logilab/astroid/issue/50
+ # A decorator that returns itself leads to an infinite loop.
+ code = """
+ def decorator():
+ def wrapper():
+ return decorator()
+ return wrapper
+
+ @decorator()
+ def do_a_thing():
+ pass
+ """
+ ast = test_utils.build_module(code, __name__)
+ node = ast['do_a_thing']
+ self.assertEqual(node.type, 'function')
+
+ def test_no_infinite_ancestor_loop(self):
+ klass = test_utils.extract_node("""
+ import datetime
+
+ def method(self):
+ datetime.datetime = something()
+
+ class something(datetime.datetime): #@
+ pass
+ """)
+ self.assertIn(
+ 'object',
+ [base.name for base in klass.ancestors()])
+
+ def test_stop_iteration_leak(self):
+ code = """
+ class Test:
+ def __init__(self):
+ self.config = {0: self.config[0]}
+ self.config[0].test() #@
+ """
+ ast = test_utils.extract_node(code, __name__)
+ expr = ast.func.expr
+ self.assertRaises(InferenceError, next, expr.infer())
+
+ def test_tuple_builtin_inference(self):
+ code = """
+ var = (1, 2)
+ tuple() #@
+ tuple([1]) #@
+ tuple({2}) #@
+ tuple("abc") #@
+ tuple({1: 2}) #@
+ tuple(var) #@
+ tuple(tuple([1])) #@
+
+ tuple(None) #@
+ tuple(1) #@
+ tuple(1, 2) #@
+ """
+ ast = test_utils.extract_node(code, __name__)
+
+ self.assertInferTuple(ast[0], [])
+ self.assertInferTuple(ast[1], [1])
+ self.assertInferTuple(ast[2], [2])
+ self.assertInferTuple(ast[3], ["a", "b", "c"])
+ self.assertInferTuple(ast[4], [1])
+ self.assertInferTuple(ast[5], [1, 2])
+ self.assertInferTuple(ast[6], [1])
+
+ for node in ast[7:]:
+ infered = next(node.infer())
+ self.assertIsInstance(infered, Instance)
+ self.assertEqual(infered.qname(), "{}.tuple".format(BUILTINS))
+
+ def test_set_builtin_inference(self):
+ code = """
+ var = (1, 2)
+ set() #@
+ set([1, 2, 1]) #@
+ set({2, 3, 1}) #@
+ set("abcab") #@
+ set({1: 2}) #@
+ set(var) #@
+ set(tuple([1])) #@
+
+ set(set(tuple([4, 5, set([2])]))) #@
+ set(None) #@
+ set(1) #@
+ set(1, 2) #@
+ """
+ ast = test_utils.extract_node(code, __name__)
+
+ self.assertInferSet(ast[0], [])
+ self.assertInferSet(ast[1], [1, 2])
+ self.assertInferSet(ast[2], [1, 2, 3])
+ self.assertInferSet(ast[3], ["a", "b", "c"])
+ self.assertInferSet(ast[4], [1])
+ self.assertInferSet(ast[5], [1, 2])
+ self.assertInferSet(ast[6], [1])
+
+ for node in ast[7:]:
+ infered = next(node.infer())
+ self.assertIsInstance(infered, Instance)
+ self.assertEqual(infered.qname(), "{}.set".format(BUILTINS))
+
+ def test_list_builtin_inference(self):
+ code = """
+ var = (1, 2)
+ list() #@
+ list([1, 2, 1]) #@
+ list({2, 3, 1}) #@
+ list("abcab") #@
+ list({1: 2}) #@
+ list(var) #@
+ list(tuple([1])) #@
+
+ list(list(tuple([4, 5, list([2])]))) #@
+ list(None) #@
+ list(1) #@
+ list(1, 2) #@
+ """
+ ast = test_utils.extract_node(code, __name__)
+ self.assertInferList(ast[0], [])
+ self.assertInferList(ast[1], [1, 1, 2])
+ self.assertInferList(ast[2], [1, 2, 3])
+ self.assertInferList(ast[3], ["a", "a", "b", "b", "c"])
+ self.assertInferList(ast[4], [1])
+ self.assertInferList(ast[5], [1, 2])
+ self.assertInferList(ast[6], [1])
+
+ for node in ast[7:]:
+ infered = next(node.infer())
+ self.assertIsInstance(infered, Instance)
+ self.assertEqual(infered.qname(), "{}.list".format(BUILTINS))
+
+ @test_utils.require_version('3.0')
+ def test_builtin_inference_py3k(self):
+ code = """
+ list(b"abc") #@
+ tuple(b"abc") #@
+ set(b"abc") #@
+ """
+ ast = test_utils.extract_node(code, __name__)
+ self.assertInferList(ast[0], [97, 98, 99])
+ self.assertInferTuple(ast[1], [97, 98, 99])
+ self.assertInferSet(ast[2], [97, 98, 99])
+
+ def test_dict_inference(self):
+ code = """
+ dict() #@
+ dict(a=1, b=2, c=3) #@
+ dict([(1, 2), (2, 3)]) #@
+ dict([[1, 2], [2, 3]]) #@
+ dict([(1, 2), [2, 3]]) #@
+ dict([('a', 2)], b=2, c=3) #@
+ dict({1: 2}) #@
+ dict({'c': 2}, a=4, b=5) #@
+ def func():
+ return dict(a=1, b=2)
+ func() #@
+ var = {'x': 2, 'y': 3}
+ dict(var, a=1, b=2) #@
+
+ dict([1, 2, 3]) #@
+ dict([(1, 2), (1, 2, 3)]) #@
+ dict({1: 2}, {1: 2}) #@
+ dict({1: 2}, (1, 2)) #@
+ dict({1: 2}, (1, 2), a=4) #@
+ dict([(1, 2), ([4, 5], 2)]) #@
+ dict([None, None]) #@
+
+ def using_unknown_kwargs(**kwargs):
+ return dict(**kwargs)
+ using_unknown_kwargs(a=1, b=2) #@
+ """
+ ast = test_utils.extract_node(code, __name__)
+ self.assertInferDict(ast[0], {})
+ self.assertInferDict(ast[1], {'a': 1, 'b': 2, 'c': 3})
+ for i in range(2, 5):
+ self.assertInferDict(ast[i], {1: 2, 2: 3})
+ self.assertInferDict(ast[5], {'a': 2, 'b': 2, 'c': 3})
+ self.assertInferDict(ast[6], {1: 2})
+ self.assertInferDict(ast[7], {'c': 2, 'a': 4, 'b': 5})
+ self.assertInferDict(ast[8], {'a': 1, 'b': 2})
+ self.assertInferDict(ast[9], {'x': 2, 'y': 3, 'a': 1, 'b': 2})
+
+ for node in ast[10:]:
+ infered = next(node.infer())
+ self.assertIsInstance(infered, Instance)
+ self.assertEqual(infered.qname(), "{}.dict".format(BUILTINS))
+
+
+ def test_str_methods(self):
+ code = """
+ ' '.decode() #@
+
+ ' '.encode() #@
+ ' '.join('abcd') #@
+ ' '.replace('a', 'b') #@
+ ' '.format('a') #@
+ ' '.capitalize() #@
+ ' '.title() #@
+ ' '.lower() #@
+ ' '.upper() #@
+ ' '.swapcase() #@
+ ' '.strip() #@
+ ' '.rstrip() #@
+ ' '.lstrip() #@
+ ' '.rjust() #@
+ ' '.ljust() #@
+ ' '.center() #@
+
+ ' '.index() #@
+ ' '.find() #@
+ ' '.count() #@
+ """
+ ast = test_utils.extract_node(code, __name__)
+ self.assertInferConst(ast[0], u'')
+ for i in range(1, 16):
+ self.assertInferConst(ast[i], '')
+ for i in range(16, 19):
+ self.assertInferConst(ast[i], 0)
+
+ def test_unicode_methods(self):
+ code = """
+ u' '.encode() #@
+
+ u' '.decode() #@
+ u' '.join('abcd') #@
+ u' '.replace('a', 'b') #@
+ u' '.format('a') #@
+ u' '.capitalize() #@
+ u' '.title() #@
+ u' '.lower() #@
+ u' '.upper() #@
+ u' '.swapcase() #@
+ u' '.strip() #@
+ u' '.rstrip() #@
+ u' '.lstrip() #@
+ u' '.rjust() #@
+ u' '.ljust() #@
+ u' '.center() #@
+
+ u' '.index() #@
+ u' '.find() #@
+ u' '.count() #@
+ """
+ ast = test_utils.extract_node(code, __name__)
+ self.assertInferConst(ast[0], '')
+ for i in range(1, 16):
+ self.assertInferConst(ast[i], u'')
+ for i in range(16, 19):
+ self.assertInferConst(ast[i], 0)
+
+ def test_scope_lookup_same_attributes(self):
+ code = '''
+ import collections
+ class Second(collections.Counter):
+ def collections(self):
+ return "second"
+
+ '''
+ ast = test_utils.build_module(code, __name__)
+ bases = ast['Second'].bases[0]
+ inferred = next(bases.infer())
+ self.assertTrue(inferred)
+ self.assertIsInstance(inferred, nodes.Class)
+ self.assertEqual(inferred.qname(), 'collections.Counter')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_inspector.py astroid-1.3.8/astroid/tests/unittest_inspector.py
--- astroid-1.0.1/astroid/tests/unittest_inspector.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_inspector.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,94 @@
+# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE).
+# http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+"""
+ for the visitors.diadefs module
+"""
+
+import unittest
+
+
+from astroid import nodes, inspector
+from astroid.bases import Instance, YES
+from astroid.manager import AstroidManager, _silent_no_wrap
+from astroid.tests import resources
+
+MANAGER = AstroidManager()
+
+def astroid_wrapper(func, modname):
+ return func(modname)
+
+
+class LinkerTest(resources.SysPathSetup, unittest.TestCase):
+
+ def setUp(self):
+ super(LinkerTest, self).setUp()
+ self.project = MANAGER.project_from_files(
+ [resources.find('data')],
+ astroid_wrapper,
+ black_list=['joined_strings.py'])
+ self.linker = inspector.Linker(self.project)
+ self.linker.visit(self.project)
+
+ def test_class_implements(self):
+ klass = self.project.get_module('data.clientmodule_test')['Ancestor']
+ self.assertTrue(hasattr(klass, 'implements'))
+ self.assertEqual(len(klass.implements), 1)
+ self.assertTrue(isinstance(klass.implements[0], nodes.Class))
+ self.assertEqual(klass.implements[0].name, "Interface")
+ klass = self.project.get_module('data.clientmodule_test')['Specialization']
+ self.assertTrue(hasattr(klass, 'implements'))
+ self.assertEqual(len(klass.implements), 0)
+
+ def test_locals_assignment_resolution(self):
+ klass = self.project.get_module('data.clientmodule_test')['Specialization']
+ self.assertTrue(hasattr(klass, 'locals_type'))
+ type_dict = klass.locals_type
+ self.assertEqual(len(type_dict), 2)
+ keys = sorted(type_dict.keys())
+ self.assertEqual(keys, ['TYPE', 'top'])
+ self.assertEqual(len(type_dict['TYPE']), 1)
+ self.assertEqual(type_dict['TYPE'][0].value, 'final class')
+ self.assertEqual(len(type_dict['top']), 1)
+ self.assertEqual(type_dict['top'][0].value, 'class')
+
+ def test_instance_attrs_resolution(self):
+ klass = self.project.get_module('data.clientmodule_test')['Specialization']
+ self.assertTrue(hasattr(klass, 'instance_attrs_type'))
+ type_dict = klass.instance_attrs_type
+ self.assertEqual(len(type_dict), 3)
+ keys = sorted(type_dict.keys())
+ self.assertEqual(keys, ['_id', 'relation', 'toto'])
+ self.assertTrue(isinstance(type_dict['relation'][0], Instance), type_dict['relation'])
+ self.assertEqual(type_dict['relation'][0].name, 'DoNothing')
+ self.assertTrue(isinstance(type_dict['toto'][0], Instance), type_dict['toto'])
+ self.assertEqual(type_dict['toto'][0].name, 'Toto')
+ self.assertIs(type_dict['_id'][0], YES)
+
+
+class LinkerTest2(LinkerTest):
+
+ def setUp(self):
+ resources.SysPathSetup.setUp(self)
+ self.project = MANAGER.project_from_files(
+ [resources.find('data')],
+ func_wrapper=_silent_no_wrap,
+ black_list=['joined_strings.py'])
+ self.linker = inspector.Linker(self.project)
+ self.linker.visit(self.project)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_lookup.py astroid-1.3.8/astroid/tests/unittest_lookup.py
--- astroid-1.0.1/astroid/tests/unittest_lookup.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_lookup.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,354 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""tests for the astroid variable lookup capabilities
+"""
+import sys
+from functools import partial
+import unittest
+
+from astroid import nodes, InferenceError, NotFoundError, UnresolvableName
+from astroid.scoped_nodes import builtin_lookup
+from astroid.bases import YES
+from astroid import test_utils
+from astroid.tests import resources
+
+
+class LookupTest(resources.SysPathSetup, unittest.TestCase):
+
+ def setUp(self):
+ super(LookupTest, self).setUp()
+ self.module = resources.build_file('data/module.py', 'data.module')
+ self.module2 = resources.build_file('data/module2.py', 'data.module2')
+ self.nonregr = resources.build_file('data/nonregr.py', 'data.nonregr')
+
+ def test_limit(self):
+ code = '''
+ l = [a
+ for a,b in list]
+
+ a = 1
+ b = a
+ a = None
+
+ def func():
+ c = 1
+ '''
+ astroid = test_utils.build_module(code, __name__)
+ # a & b
+ a = next(astroid.nodes_of_class(nodes.Name))
+ self.assertEqual(a.lineno, 2)
+ if sys.version_info < (3, 0):
+ self.assertEqual(len(astroid.lookup('b')[1]), 2)
+ self.assertEqual(len(astroid.lookup('a')[1]), 3)
+ b = astroid.locals['b'][1]
+ else:
+ self.assertEqual(len(astroid.lookup('b')[1]), 1)
+ self.assertEqual(len(astroid.lookup('a')[1]), 2)
+ b = astroid.locals['b'][0]
+ stmts = a.lookup('a')[1]
+ self.assertEqual(len(stmts), 1)
+ self.assertEqual(b.lineno, 6)
+ b_infer = b.infer()
+ b_value = next(b_infer)
+ self.assertEqual(b_value.value, 1)
+ # c
+ self.assertRaises(StopIteration, partial(next, b_infer))
+ func = astroid.locals['func'][0]
+ self.assertEqual(len(func.lookup('c')[1]), 1)
+
+ def test_module(self):
+ astroid = test_utils.build_module('pass', __name__)
+ # built-in objects
+ none = next(astroid.ilookup('None'))
+ self.assertIsNone(none.value)
+ obj = next(astroid.ilookup('object'))
+ self.assertIsInstance(obj, nodes.Class)
+ self.assertEqual(obj.name, 'object')
+ self.assertRaises(InferenceError, partial(next, astroid.ilookup('YOAA')))
+
+ # XXX
+ self.assertEqual(len(list(self.nonregr.ilookup('enumerate'))), 2)
+
+ def test_class_ancestor_name(self):
+ code = '''
+ class A:
+ pass
+
+ class A(A):
+ pass
+ '''
+ astroid = test_utils.build_module(code, __name__)
+ cls1 = astroid.locals['A'][0]
+ cls2 = astroid.locals['A'][1]
+ name = next(cls2.nodes_of_class(nodes.Name))
+ self.assertEqual(next(name.infer()), cls1)
+
+ ### backport those test to inline code
+ def test_method(self):
+ method = self.module['YOUPI']['method']
+ my_dict = next(method.ilookup('MY_DICT'))
+ self.assertTrue(isinstance(my_dict, nodes.Dict), my_dict)
+ none = next(method.ilookup('None'))
+ self.assertIsNone(none.value)
+ self.assertRaises(InferenceError, partial(next, method.ilookup('YOAA')))
+
+
+ def test_function_argument_with_default(self):
+ make_class = self.module2['make_class']
+ base = next(make_class.ilookup('base'))
+ self.assertTrue(isinstance(base, nodes.Class), base.__class__)
+ self.assertEqual(base.name, 'YO')
+ self.assertEqual(base.root().name, 'data.module')
+
+ def test_class(self):
+ klass = self.module['YOUPI']
+ my_dict = next(klass.ilookup('MY_DICT'))
+ self.assertIsInstance(my_dict, nodes.Dict)
+ none = next(klass.ilookup('None'))
+ self.assertIsNone(none.value)
+ obj = next(klass.ilookup('object'))
+ self.assertIsInstance(obj, nodes.Class)
+ self.assertEqual(obj.name, 'object')
+ self.assertRaises(InferenceError, partial(next, klass.ilookup('YOAA')))
+
+ def test_inner_classes(self):
+ ddd = list(self.nonregr['Ccc'].ilookup('Ddd'))
+ self.assertEqual(ddd[0].name, 'Ddd')
+
+
+ def test_loopvar_hiding(self):
+ astroid = test_utils.build_module("""
+ x = 10
+ for x in range(5):
+ print (x)
+
+ if x > 0:
+ print ('#' * x)
+ """, __name__)
+ xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'x']
+ # inside the loop, only one possible assignment
+ self.assertEqual(len(xnames[0].lookup('x')[1]), 1)
+ # outside the loop, two possible assignments
+ self.assertEqual(len(xnames[1].lookup('x')[1]), 2)
+ self.assertEqual(len(xnames[2].lookup('x')[1]), 2)
+
+ def test_list_comps(self):
+ astroid = test_utils.build_module("""
+ print ([ i for i in range(10) ])
+ print ([ i for i in range(10) ])
+ print ( list( i for i in range(10) ) )
+ """, __name__)
+ xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i']
+ self.assertEqual(len(xnames[0].lookup('i')[1]), 1)
+ self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2)
+ self.assertEqual(len(xnames[1].lookup('i')[1]), 1)
+ self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3)
+ self.assertEqual(len(xnames[2].lookup('i')[1]), 1)
+ self.assertEqual(xnames[2].lookup('i')[1][0].lineno, 4)
+
+ def test_list_comp_target(self):
+ """test the list comprehension target"""
+ astroid = test_utils.build_module("""
+ ten = [ var for var in range(10) ]
+ var
+ """)
+ var = astroid.body[1].value
+ if sys.version_info < (3, 0):
+ self.assertEqual(var.infered(), [YES])
+ else:
+ self.assertRaises(UnresolvableName, var.infered)
+
+ def test_dict_comps(self):
+ astroid = test_utils.build_module("""
+ print ({ i: j for i in range(10) for j in range(10) })
+ print ({ i: j for i in range(10) for j in range(10) })
+ """, __name__)
+ xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i']
+ self.assertEqual(len(xnames[0].lookup('i')[1]), 1)
+ self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2)
+ self.assertEqual(len(xnames[1].lookup('i')[1]), 1)
+ self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3)
+
+ xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'j']
+ self.assertEqual(len(xnames[0].lookup('i')[1]), 1)
+ self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2)
+ self.assertEqual(len(xnames[1].lookup('i')[1]), 1)
+ self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3)
+
+ def test_set_comps(self):
+ astroid = test_utils.build_module("""
+ print ({ i for i in range(10) })
+ print ({ i for i in range(10) })
+ """, __name__)
+ xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i']
+ self.assertEqual(len(xnames[0].lookup('i')[1]), 1)
+ self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2)
+ self.assertEqual(len(xnames[1].lookup('i')[1]), 1)
+ self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3)
+
+ def test_set_comp_closure(self):
+ astroid = test_utils.build_module("""
+ ten = { var for var in range(10) }
+ var
+ """)
+ var = astroid.body[1].value
+ self.assertRaises(UnresolvableName, var.infered)
+
+ def test_generator_attributes(self):
+ tree = test_utils.build_module("""
+ def count():
+ "test"
+ yield 0
+
+ iterer = count()
+ num = iterer.next()
+ """)
+ next = tree.body[2].value.func # Getattr
+ gener = next.expr.infered()[0] # Generator
+ if sys.version_info < (3, 0):
+ self.assertIsInstance(gener.getattr('next')[0], nodes.Function)
+ else:
+ self.assertIsInstance(gener.getattr('__next__')[0], nodes.Function)
+ self.assertIsInstance(gener.getattr('send')[0], nodes.Function)
+ self.assertIsInstance(gener.getattr('throw')[0], nodes.Function)
+ self.assertIsInstance(gener.getattr('close')[0], nodes.Function)
+
+ def test_explicit___name__(self):
+ code = '''
+ class Pouet:
+ __name__ = "pouet"
+ p1 = Pouet()
+
+ class PouetPouet(Pouet): pass
+ p2 = Pouet()
+
+ class NoName: pass
+ p3 = NoName()
+ '''
+ astroid = test_utils.build_module(code, __name__)
+ p1 = next(astroid['p1'].infer())
+ self.assertTrue(p1.getattr('__name__'))
+ p2 = next(astroid['p2'].infer())
+ self.assertTrue(p2.getattr('__name__'))
+ self.assertTrue(astroid['NoName'].getattr('__name__'))
+ p3 = next(astroid['p3'].infer())
+ self.assertRaises(NotFoundError, p3.getattr, '__name__')
+
+
+ def test_function_module_special(self):
+ astroid = test_utils.build_module('''
+ def initialize(linter):
+ """initialize linter with checkers in this package """
+ package_load(linter, __path__[0])
+ ''', 'data.__init__')
+ path = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == '__path__'][0]
+ self.assertEqual(len(path.lookup('__path__')[1]), 1)
+
+
+ def test_builtin_lookup(self):
+ self.assertEqual(builtin_lookup('__dict__')[1], ())
+ intstmts = builtin_lookup('int')[1]
+ self.assertEqual(len(intstmts), 1)
+ self.assertIsInstance(intstmts[0], nodes.Class)
+ self.assertEqual(intstmts[0].name, 'int')
+ self.assertIs(intstmts[0], nodes.const_factory(1)._proxied)
+
+
+ def test_decorator_arguments_lookup(self):
+ code = '''
+ def decorator(value):
+ def wrapper(function):
+ return function
+ return wrapper
+
+ class foo:
+ member = 10 #@
+
+ @decorator(member) #This will cause pylint to complain
+ def test(self):
+ pass
+ '''
+ member = test_utils.extract_node(code, __name__).targets[0]
+ it = member.infer()
+ obj = next(it)
+ self.assertIsInstance(obj, nodes.Const)
+ self.assertEqual(obj.value, 10)
+ self.assertRaises(StopIteration, partial(next, it))
+
+
+ def test_inner_decorator_member_lookup(self):
+ code = '''
+ class FileA:
+ def decorator(bla):
+ return bla
+
+ @__(decorator)
+ def funcA():
+ return 4
+ '''
+ decname = test_utils.extract_node(code, __name__)
+ it = decname.infer()
+ obj = next(it)
+ self.assertIsInstance(obj, nodes.Function)
+ self.assertRaises(StopIteration, partial(next, it))
+
+
+ def test_static_method_lookup(self):
+ code = '''
+ class FileA:
+ @staticmethod
+ def funcA():
+ return 4
+
+
+ class Test:
+ FileA = [1,2,3]
+
+ def __init__(self):
+ print (FileA.funcA())
+ '''
+ astroid = test_utils.build_module(code, __name__)
+ it = astroid['Test']['__init__'].ilookup('FileA')
+ obj = next(it)
+ self.assertIsInstance(obj, nodes.Class)
+ self.assertRaises(StopIteration, partial(next, it))
+
+
+ def test_global_delete(self):
+ code = '''
+ def run2():
+ f = Frobble()
+
+ class Frobble:
+ pass
+ Frobble.mumble = True
+
+ del Frobble
+
+ def run1():
+ f = Frobble()
+ '''
+ astroid = test_utils.build_module(code, __name__)
+ stmts = astroid['run2'].lookup('Frobbel')[1]
+ self.assertEqual(len(stmts), 0)
+ stmts = astroid['run1'].lookup('Frobbel')[1]
+ self.assertEqual(len(stmts), 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_manager.py astroid-1.3.8/astroid/tests/unittest_manager.py
--- astroid-1.0.1/astroid/tests/unittest_manager.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_manager.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,263 @@
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+import os
+import sys
+import unittest
+
+from astroid.manager import AstroidManager, _silent_no_wrap
+from astroid.bases import BUILTINS
+from astroid.exceptions import AstroidBuildingException
+from astroid.tests import resources
+
+
+class AstroidManagerTest(resources.SysPathSetup,
+ resources.AstroidCacheSetupMixin,
+ unittest.TestCase):
+
+ @property
+ def project(self):
+ return self.manager.project_from_files(
+ [resources.find('data')],
+ _silent_no_wrap, 'data',
+ black_list=['joined_strings.py'])
+
+ def setUp(self):
+ super(AstroidManagerTest, self).setUp()
+ self.manager = AstroidManager()
+ self.manager.clear_cache(self._builtins) # take care of borg
+
+ def test_ast_from_file(self):
+ """check if the method return a good astroid object"""
+ import unittest
+ filepath = unittest.__file__
+ astroid = self.manager.ast_from_file(filepath)
+ self.assertEqual(astroid.name, 'unittest')
+ self.assertIn('unittest', self.manager.astroid_cache)
+
+ def test_ast_from_file_cache(self):
+ """check if the cache works"""
+ import unittest
+ filepath = unittest.__file__
+ self.manager.ast_from_file(filepath)
+ astroid = self.manager.ast_from_file('unhandledName', 'unittest')
+ self.assertEqual(astroid.name, 'unittest')
+ self.assertIn('unittest', self.manager.astroid_cache)
+
+ def test_ast_from_file_astro_builder(self):
+ """check if the source is at True, AstroidBuilder build a good astroid"""
+ import unittest
+ filepath = unittest.__file__
+ astroid = self.manager.ast_from_file(filepath, None, True, True)
+ self.assertEqual(astroid.name, 'unittest')
+ self.assertIn('unittest', self.manager.astroid_cache)
+
+ def test_ast_from_file_name_astro_builder_exception(self):
+ """check if an exception is thrown if we give a wrong filepath"""
+ self.assertRaises(AstroidBuildingException, self.manager.ast_from_file, 'unhandledName')
+
+ def test_do_not_expose_main(self):
+ obj = self.manager.ast_from_module_name('__main__')
+ self.assertEqual(obj.name, '__main__')
+ self.assertEqual(obj.items(), [])
+
+ def test_ast_from_module_name(self):
+ """check if the ast_from_module_name method return a good astroid"""
+ astroid = self.manager.ast_from_module_name('unittest')
+ self.assertEqual(astroid.name, 'unittest')
+ self.assertIn('unittest', self.manager.astroid_cache)
+
+ def test_ast_from_module_name_not_python_source(self):
+ """check if the ast_from_module_name method return a good astroid with a no python source module"""
+ astroid = self.manager.ast_from_module_name('time')
+ self.assertEqual(astroid.name, 'time')
+ self.assertIn('time', self.manager.astroid_cache)
+ self.assertEqual(astroid.pure_python, False)
+
+ def test_ast_from_module_name_astro_builder_exception(self):
+ """check if the method raise an exception if we give a wrong module"""
+ self.assertRaises(AstroidBuildingException, self.manager.ast_from_module_name, 'unhandledModule')
+
+ def _test_ast_from_zip(self, archive):
+ origpath = sys.path[:]
+ sys.modules.pop('mypypa', None)
+ archive_path = resources.find(archive)
+ sys.path.insert(0, archive_path)
+ try:
+ module = self.manager.ast_from_module_name('mypypa')
+ self.assertEqual(module.name, 'mypypa')
+ end = os.path.join(archive, 'mypypa')
+ self.assertTrue(module.file.endswith(end),
+ "%s doesn't endswith %s" % (module.file, end))
+ finally:
+ # remove the module, else after importing egg, we don't get the zip
+ if 'mypypa' in self.manager.astroid_cache:
+ del self.manager.astroid_cache['mypypa']
+ del self.manager._mod_file_cache[('mypypa', None)]
+ if archive_path in sys.path_importer_cache:
+ del sys.path_importer_cache[archive_path]
+ sys.path = origpath
+
+ def test_ast_from_module_name_egg(self):
+ self._test_ast_from_zip(
+ os.path.sep.join(['data', os.path.normcase('MyPyPa-0.1.0-py2.5.egg')])
+ )
+
+ def test_ast_from_module_name_zip(self):
+ self._test_ast_from_zip(
+ os.path.sep.join(['data', os.path.normcase('MyPyPa-0.1.0-py2.5.zip')])
+ )
+
+ def test_zip_import_data(self):
+ """check if zip_import_data works"""
+ filepath = resources.find('data/MyPyPa-0.1.0-py2.5.zip/mypypa')
+ astroid = self.manager.zip_import_data(filepath)
+ self.assertEqual(astroid.name, 'mypypa')
+
+ def test_zip_import_data_without_zipimport(self):
+ """check if zip_import_data return None without zipimport"""
+ self.assertEqual(self.manager.zip_import_data('path'), None)
+
+ def test_file_from_module(self):
+ """check if the unittest filepath is equals to the result of the method"""
+ if sys.version_info > (3, 0):
+ unittest_file = unittest.__file__
+ else:
+ unittest_file = unittest.__file__[:-1]
+ self.assertEqual(unittest_file,
+ self.manager.file_from_module_name('unittest', None)[0])
+
+ def test_file_from_module_name_astro_building_exception(self):
+ """check if the method launch a exception with a wrong module name"""
+ self.assertRaises(AstroidBuildingException, self.manager.file_from_module_name, 'unhandledModule', None)
+
+ def test_ast_from_module(self):
+ astroid = self.manager.ast_from_module(unittest)
+ self.assertEqual(astroid.pure_python, True)
+ import time
+ astroid = self.manager.ast_from_module(time)
+ self.assertEqual(astroid.pure_python, False)
+
+ def test_ast_from_module_cache(self):
+ """check if the module is in the cache manager"""
+ astroid = self.manager.ast_from_module(unittest)
+ self.assertEqual(astroid.name, 'unittest')
+ self.assertIn('unittest', self.manager.astroid_cache)
+
+ def test_ast_from_class(self):
+ astroid = self.manager.ast_from_class(int)
+ self.assertEqual(astroid.name, 'int')
+ self.assertEqual(astroid.parent.frame().name, BUILTINS)
+
+ astroid = self.manager.ast_from_class(object)
+ self.assertEqual(astroid.name, 'object')
+ self.assertEqual(astroid.parent.frame().name, BUILTINS)
+ self.assertIn('__setattr__', astroid)
+
+ def test_ast_from_class_with_module(self):
+ """check if the method works with the module name"""
+ astroid = self.manager.ast_from_class(int, int.__module__)
+ self.assertEqual(astroid.name, 'int')
+ self.assertEqual(astroid.parent.frame().name, BUILTINS)
+
+ astroid = self.manager.ast_from_class(object, object.__module__)
+ self.assertEqual(astroid.name, 'object')
+ self.assertEqual(astroid.parent.frame().name, BUILTINS)
+ self.assertIn('__setattr__', astroid)
+
+ def test_ast_from_class_attr_error(self):
+ """give a wrong class at the ast_from_class method"""
+ self.assertRaises(AstroidBuildingException, self.manager.ast_from_class, None)
+
+ def test_from_directory(self):
+ self.assertEqual(self.project.name, 'data')
+ self.assertEqual(self.project.path,
+ os.path.abspath(resources.find('data/__init__.py')))
+
+ def test_project_node(self):
+ expected = [
+ 'data',
+ 'data.SSL1',
+ 'data.SSL1.Connection1',
+ 'data.absimp',
+ 'data.absimp.sidepackage',
+ 'data.absimp.string',
+ 'data.absimport',
+ 'data.all',
+ 'data.appl',
+ 'data.appl.myConnection',
+ 'data.clientmodule_test',
+ 'data.descriptor_crash',
+ 'data.email',
+ 'data.find_test',
+ 'data.find_test.module',
+ 'data.find_test.module2',
+ 'data.find_test.noendingnewline',
+ 'data.find_test.nonregr',
+ 'data.format',
+ 'data.lmfp',
+ 'data.lmfp.foo',
+ 'data.module',
+ 'data.module1abs',
+ 'data.module1abs.core',
+ 'data.module2',
+ 'data.noendingnewline',
+ 'data.nonregr',
+ 'data.notall',
+ 'data.package',
+ 'data.package.absimport',
+ 'data.package.hello',
+ 'data.package.import_package_subpackage_module',
+ 'data.package.subpackage',
+ 'data.package.subpackage.module',
+ 'data.recursion',
+ 'data.suppliermodule_test',
+ 'data.unicode_package',
+ 'data.unicode_package.core']
+ self.assertListEqual(sorted(self.project.keys()), expected)
+
+ def testFailedImportHooks(self):
+ def hook(modname):
+ if modname == 'foo.bar':
+ return unittest
+ else:
+ raise AstroidBuildingException()
+
+ with self.assertRaises(AstroidBuildingException):
+ self.manager.ast_from_module_name('foo.bar')
+ self.manager.register_failed_import_hook(hook)
+ self.assertEqual(unittest, self.manager.ast_from_module_name('foo.bar'))
+ with self.assertRaises(AstroidBuildingException):
+ self.manager.ast_from_module_name('foo.bar.baz')
+ del self.manager._failed_import_hooks[0]
+
+
+class BorgAstroidManagerTC(unittest.TestCase):
+
+ def test_borg(self):
+ """test that the AstroidManager is really a borg, i.e. that two different
+ instances has same cache"""
+ first_manager = AstroidManager()
+ built = first_manager.ast_from_module_name(BUILTINS)
+
+ second_manager = AstroidManager()
+ second_built = second_manager.ast_from_module_name(BUILTINS)
+ self.assertIs(built, second_built)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_modutils.py astroid-1.3.8/astroid/tests/unittest_modutils.py
--- astroid-1.0.1/astroid/tests/unittest_modutils.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_modutils.py 2015-08-02 19:35:46.000000000 +0000
@@ -0,0 +1,262 @@
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option) any
+# later version.
+#
+# astroid is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""
+unit tests for module modutils (module manipulation utilities)
+"""
+import os
+import sys
+import unittest
+
+from logilab.common import configuration
+from astroid import modutils
+from astroid.tests import resources
+
+
+class ModuleFileTest(unittest.TestCase):
+ package = "mypypa"
+
+ def tearDown(self):
+ for k in list(sys.path_importer_cache.keys()):
+ if 'MyPyPa' in k:
+ del sys.path_importer_cache[k]
+
+ def test_find_zipped_module(self):
+ mtype, mfile = modutils._module_file(
+ [self.package], [resources.find('data/MyPyPa-0.1.0-py2.5.zip')])
+ self.assertEqual(mtype, modutils.PY_ZIPMODULE)
+ self.assertEqual(mfile.split(os.sep)[-3:], ["data", "MyPyPa-0.1.0-py2.5.zip", self.package])
+
+ def test_find_egg_module(self):
+ mtype, mfile = modutils._module_file(
+ [self.package], [resources.find('data/MyPyPa-0.1.0-py2.5.egg')])
+ self.assertEqual(mtype, modutils.PY_ZIPMODULE)
+ self.assertEqual(mfile.split(os.sep)[-3:], ["data", "MyPyPa-0.1.0-py2.5.egg", self.package])
+
+
+class LoadModuleFromNameTest(unittest.TestCase):
+ """ load a python module from it's name """
+
+ def test_knownValues_load_module_from_name_1(self):
+ self.assertEqual(modutils.load_module_from_name('sys'), sys)
+
+ def test_knownValues_load_module_from_name_2(self):
+ self.assertEqual(modutils.load_module_from_name('os.path'), os.path)
+
+ def test_raise_load_module_from_name_1(self):
+ self.assertRaises(ImportError,
+ modutils.load_module_from_name, 'os.path', use_sys=0)
+
+
+class GetModulePartTest(unittest.TestCase):
+ """given a dotted name return the module part of the name"""
+
+ def test_knownValues_get_module_part_1(self):
+ self.assertEqual(modutils.get_module_part('astroid.modutils'),
+ 'astroid.modutils')
+
+ def test_knownValues_get_module_part_2(self):
+ self.assertEqual(modutils.get_module_part('astroid.modutils.get_module_part'),
+ 'astroid.modutils')
+
+ def test_knownValues_get_module_part_3(self):
+ """relative import from given file"""
+ self.assertEqual(modutils.get_module_part('node_classes.AssName',
+ modutils.__file__), 'node_classes')
+
+ def test_knownValues_get_compiled_module_part(self):
+ self.assertEqual(modutils.get_module_part('math.log10'), 'math')
+ self.assertEqual(modutils.get_module_part('math.log10', __file__), 'math')
+
+ def test_knownValues_get_builtin_module_part(self):
+ self.assertEqual(modutils.get_module_part('sys.path'), 'sys')
+ self.assertEqual(modutils.get_module_part('sys.path', '__file__'), 'sys')
+
+ def test_get_module_part_exception(self):
+ self.assertRaises(ImportError, modutils.get_module_part, 'unknown.module',
+ modutils.__file__)
+
+
+class ModPathFromFileTest(unittest.TestCase):
+ """ given an absolute file path return the python module's path as a list """
+
+ def test_knownValues_modpath_from_file_1(self):
+ self.assertEqual(modutils.modpath_from_file(configuration.__file__),
+ ['logilab', 'common', 'configuration'])
+
+ def test_knownValues_modpath_from_file_2(self):
+ self.assertEqual(modutils.modpath_from_file('unittest_modutils.py',
+ {os.getcwd(): 'arbitrary.pkg'}),
+ ['arbitrary', 'pkg', 'unittest_modutils'])
+
+ def test_raise_modpath_from_file_Exception(self):
+ self.assertRaises(Exception, modutils.modpath_from_file, '/turlututu')
+
+
+class LoadModuleFromPathTest(resources.SysPathSetup, unittest.TestCase):
+
+ def test_do_not_load_twice(self):
+ modutils.load_module_from_modpath(['data', 'lmfp', 'foo'])
+ modutils.load_module_from_modpath(['data', 'lmfp'])
+ self.assertEqual(len(sys.just_once), 1)
+ del sys.just_once
+
+
+class FileFromModPathTest(resources.SysPathSetup, unittest.TestCase):
+ """given a mod path (i.e. splited module / package name), return the
+ corresponding file, giving priority to source file over precompiled file
+ if it exists"""
+
+ def test_site_packages(self):
+ self.assertEqual(os.path.realpath(modutils.file_from_modpath(['astroid', 'modutils'])),
+ os.path.realpath(modutils.__file__.replace('.pyc', '.py')))
+
+ def test_std_lib(self):
+ from os import path
+ self.assertEqual(os.path.realpath(modutils.file_from_modpath(['os', 'path']).replace('.pyc', '.py')),
+ os.path.realpath(path.__file__.replace('.pyc', '.py')))
+
+ def test_xmlplus(self):
+ try:
+ # don't fail if pyxml isn't installed
+ from xml.dom import ext
+ except ImportError:
+ pass
+ else:
+ self.assertEqual(os.path.realpath(modutils.file_from_modpath(['xml', 'dom', 'ext']).replace('.pyc', '.py')),
+ os.path.realpath(ext.__file__.replace('.pyc', '.py')))
+
+ def test_builtin(self):
+ self.assertEqual(modutils.file_from_modpath(['sys']),
+ None)
+
+
+ def test_unexisting(self):
+ self.assertRaises(ImportError, modutils.file_from_modpath, ['turlututu'])
+
+ def test_unicode_in_package_init(self):
+ # file_from_modpath should not crash when reading an __init__
+ # file with unicode characters.
+ modutils.file_from_modpath(["data", "unicode_package", "core"])
+
+
+class GetSourceFileTest(unittest.TestCase):
+
+ def test(self):
+ self.assertEqual(modutils.get_source_file(os.path.__file__),
+ os.path.normpath(os.path.__file__.replace('.pyc', '.py')))
+
+ def test_raise(self):
+ self.assertRaises(modutils.NoSourceFile, modutils.get_source_file, 'whatever')
+
+
+class StandardLibModuleTest(resources.SysPathSetup, unittest.TestCase):
+ """
+ return true if the module may be considered as a module from the standard
+ library
+ """
+
+ def test_builtins(self):
+ if sys.version_info < (3, 0):
+ self.assertEqual(modutils.is_standard_module('__builtin__'), True)
+ self.assertEqual(modutils.is_standard_module('builtins'), False)
+ else:
+ self.assertEqual(modutils.is_standard_module('__builtin__'), False)
+ self.assertEqual(modutils.is_standard_module('builtins'), True)
+
+ def test_builtin(self):
+ self.assertEqual(modutils.is_standard_module('sys'), True)
+
+ def test_nonstandard(self):
+ self.assertEqual(modutils.is_standard_module('logilab'), False)
+
+ def test_unknown(self):
+ self.assertEqual(modutils.is_standard_module('unknown'), False)
+
+ def test_builtin(self):
+ self.assertEqual(modutils.is_standard_module('marshal'), True)
+
+ def test_4(self):
+ self.assertEqual(modutils.is_standard_module('hashlib'), True)
+ self.assertEqual(modutils.is_standard_module('pickle'), True)
+ self.assertEqual(modutils.is_standard_module('email'), True)
+ self.assertEqual(modutils.is_standard_module('io'), sys.version_info >= (2, 6))
+ self.assertEqual(modutils.is_standard_module('StringIO'), sys.version_info < (3, 0))
+ self.assertEqual(modutils.is_standard_module('unicodedata'), True)
+
+ def test_custom_path(self):
+ datadir = resources.find('')
+ if datadir.startswith(modutils.EXT_LIB_DIR):
+ self.skipTest('known breakage of is_standard_module on installed package')
+ self.assertEqual(modutils.is_standard_module('data.module', (datadir,)), True)
+ self.assertEqual(modutils.is_standard_module('data.module', (os.path.abspath(datadir),)), True)
+
+ def test_failing_edge_cases(self):
+ from logilab import common
+ # using a subpackage/submodule path as std_path argument
+ self.assertEqual(modutils.is_standard_module('logilab.common', common.__path__), False)
+ # using a module + object name as modname argument
+ self.assertEqual(modutils.is_standard_module('sys.path'), True)
+ # this is because only the first package/module is considered
+ self.assertEqual(modutils.is_standard_module('sys.whatever'), True)
+ self.assertEqual(modutils.is_standard_module('logilab.whatever', common.__path__), False)
+
+
+class IsRelativeTest(unittest.TestCase):
+
+
+ def test_knownValues_is_relative_1(self):
+ import email
+ self.assertEqual(modutils.is_relative('utils', email.__path__[0]),
+ True)
+
+ def test_knownValues_is_relative_2(self):
+ from logilab.common import tree
+ self.assertEqual(modutils.is_relative('modutils', tree.__file__),
+ True)
+
+ def test_knownValues_is_relative_3(self):
+ import astroid
+ self.assertEqual(modutils.is_relative('astroid', astroid.__path__[0]),
+ False)
+
+
+class GetModuleFilesTest(unittest.TestCase):
+
+ def test_get_module_files_1(self):
+ """given a directory return a list of all available python module's files, even
+ in subdirectories
+ """
+ package = resources.find('data/find_test')
+ modules = set(modutils.get_module_files(package, []))
+ self.assertEqual(
+ modules,
+ {os.path.join(package, x) for x in ['__init__.py', 'module.py', 'module2.py', 'noendingnewline.py', 'nonregr.py']})
+
+ def test_load_module_set_attribute(self):
+ import logilab.common.fileutils
+ import logilab
+ del logilab.common.fileutils
+ del sys.modules['logilab.common.fileutils']
+ m = modutils.load_module_from_modpath(['logilab', 'common', 'fileutils'])
+ self.assertTrue(hasattr(logilab, 'common'))
+ self.assertTrue(hasattr(logilab.common, 'fileutils'))
+ self.assertTrue(m is logilab.common.fileutils)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_nodes.py astroid-1.3.8/astroid/tests/unittest_nodes.py
--- astroid-1.0.1/astroid/tests/unittest_nodes.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_nodes.py 2015-08-02 19:35:46.000000000 +0000
@@ -0,0 +1,459 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""tests for specific behaviour of astroid nodes
+"""
+import os
+import sys
+import unittest
+import textwrap
+
+from astroid.node_classes import unpack_infer
+from astroid.bases import BUILTINS, InferenceContext
+from astroid.exceptions import NotFoundError
+from astroid import bases
+from astroid import builder
+from astroid import nodes
+from astroid import test_utils
+from astroid.tests import resources
+
+abuilder = builder.AstroidBuilder()
+
+
+class AsStringTest(resources.SysPathSetup, unittest.TestCase):
+
+ def test_tuple_as_string(self):
+ def build(string):
+ return abuilder.string_build(string).body[0].value
+
+ self.assertEqual(build('1,').as_string(), '(1, )')
+ self.assertEqual(build('1, 2, 3').as_string(), '(1, 2, 3)')
+ self.assertEqual(build('(1, )').as_string(), '(1, )')
+ self.assertEqual(build('1, 2, 3').as_string(), '(1, 2, 3)')
+
+ def test_varargs_kwargs_as_string(self):
+ ast = abuilder.string_build('raise_string(*args, **kwargs)').body[0]
+ self.assertEqual(ast.as_string(), 'raise_string(*args, **kwargs)')
+
+ def test_module_as_string(self):
+ """check as_string on a whole module prepared to be returned identically
+ """
+ module = resources.build_file('data/module.py', 'data.module')
+ with open(resources.find('data/module.py'), 'r') as fobj:
+ self.assertMultiLineEqual(module.as_string(), fobj.read())
+
+ def test_module2_as_string(self):
+ """check as_string on a whole module prepared to be returned identically
+ """
+ module2 = resources.build_file('data/module2.py', 'data.module2')
+ with open(resources.find('data/module2.py'), 'r') as fobj:
+ self.assertMultiLineEqual(module2.as_string(), fobj.read())
+
+ def test_as_string(self):
+ """check as_string for python syntax >= 2.7"""
+ code = '''one_two = {1, 2}
+b = {v: k for (k, v) in enumerate('string')}
+cdd = {k for k in b}\n\n'''
+ ast = abuilder.string_build(code)
+ self.assertMultiLineEqual(ast.as_string(), code)
+
+ @test_utils.require_version('3.0')
+ def test_3k_as_string(self):
+ """check as_string for python 3k syntax"""
+ code = '''print()
+
+def function(var):
+ nonlocal counter
+ try:
+ hello
+ except NameError as nexc:
+ (*hell, o) = b'hello'
+ raise AttributeError from nexc
+\n'''
+ ast = abuilder.string_build(code)
+ self.assertEqual(ast.as_string(), code)
+
+ @test_utils.require_version('3.0')
+ @unittest.expectedFailure
+ def test_3k_annotations_and_metaclass(self):
+ code_annotations = textwrap.dedent('''
+ def function(var:int):
+ nonlocal counter
+
+ class Language(metaclass=Natural):
+ """natural language"""
+ ''')
+
+ ast = abuilder.string_build(code_annotations)
+ self.assertEqual(ast.as_string(), code_annotations)
+
+ def test_ellipsis(self):
+ ast = abuilder.string_build('a[...]').body[0]
+ self.assertEqual(ast.as_string(), 'a[...]')
+
+ def test_slices(self):
+ for code in ('a[0]', 'a[1:3]', 'a[:-1:step]', 'a[:,newaxis]',
+ 'a[newaxis,:]', 'del L[::2]', 'del A[1]', 'del Br[:]'):
+ ast = abuilder.string_build(code).body[0]
+ self.assertEqual(ast.as_string(), code)
+
+ def test_slice_and_subscripts(self):
+ code = """a[:1] = bord[2:]
+a[:1] = bord[2:]
+del bree[3:d]
+bord[2:]
+del av[d::f], a[df:]
+a[:1] = bord[2:]
+del SRC[::1,newaxis,1:]
+tous[vals] = 1010
+del thousand[key]
+del a[::2], a[:-1:step]
+del Fee.form[left:]
+aout.vals = miles.of_stuff
+del (ccok, (name.thing, foo.attrib.value)), Fee.form[left:]
+if all[1] == bord[0:]:
+ pass\n\n"""
+ ast = abuilder.string_build(code)
+ self.assertEqual(ast.as_string(), code)
+
+
+class _NodeTest(unittest.TestCase):
+ """test transformation of If Node"""
+ CODE = None
+
+ @property
+ def astroid(self):
+ try:
+ return self.__class__.__dict__['CODE_Astroid']
+ except KeyError:
+ astroid = test_utils.build_module(self.CODE)
+ self.__class__.CODE_Astroid = astroid
+ return astroid
+
+
+class IfNodeTest(_NodeTest):
+ """test transformation of If Node"""
+ CODE = """
+ if 0:
+ print()
+
+ if True:
+ print()
+ else:
+ pass
+
+ if "":
+ print()
+ elif []:
+ raise
+
+ if 1:
+ print()
+ elif True:
+ print()
+ elif func():
+ pass
+ else:
+ raise
+ """
+
+ def test_if_elif_else_node(self):
+ """test transformation for If node"""
+ self.assertEqual(len(self.astroid.body), 4)
+ for stmt in self.astroid.body:
+ self.assertIsInstance(stmt, nodes.If)
+ self.assertFalse(self.astroid.body[0].orelse) # simple If
+ self.assertIsInstance(self.astroid.body[1].orelse[0], nodes.Pass) # If / else
+ self.assertIsInstance(self.astroid.body[2].orelse[0], nodes.If) # If / elif
+ self.assertIsInstance(self.astroid.body[3].orelse[0].orelse[0], nodes.If)
+
+ def test_block_range(self):
+ # XXX ensure expected values
+ self.assertEqual(self.astroid.block_range(1), (0, 22))
+ self.assertEqual(self.astroid.block_range(10), (0, 22)) # XXX (10, 22) ?
+ self.assertEqual(self.astroid.body[1].block_range(5), (5, 6))
+ self.assertEqual(self.astroid.body[1].block_range(6), (6, 6))
+ self.assertEqual(self.astroid.body[1].orelse[0].block_range(7), (7, 8))
+ self.assertEqual(self.astroid.body[1].orelse[0].block_range(8), (8, 8))
+
+
+class TryExceptNodeTest(_NodeTest):
+ CODE = """
+ try:
+ print ('pouet')
+ except IOError:
+ pass
+ except UnicodeError:
+ print()
+ else:
+ print()
+ """
+
+ def test_block_range(self):
+ # XXX ensure expected values
+ self.assertEqual(self.astroid.body[0].block_range(1), (1, 8))
+ self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
+ self.assertEqual(self.astroid.body[0].block_range(3), (3, 8))
+ self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
+ self.assertEqual(self.astroid.body[0].block_range(5), (5, 5))
+ self.assertEqual(self.astroid.body[0].block_range(6), (6, 6))
+ self.assertEqual(self.astroid.body[0].block_range(7), (7, 7))
+ self.assertEqual(self.astroid.body[0].block_range(8), (8, 8))
+
+
+class TryFinallyNodeTest(_NodeTest):
+ CODE = """
+ try:
+ print ('pouet')
+ finally:
+ print ('pouet')
+ """
+
+ def test_block_range(self):
+ # XXX ensure expected values
+ self.assertEqual(self.astroid.body[0].block_range(1), (1, 4))
+ self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
+ self.assertEqual(self.astroid.body[0].block_range(3), (3, 4))
+ self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
+
+
+class TryExceptFinallyNodeTest(_NodeTest):
+ CODE = """
+ try:
+ print('pouet')
+ except Exception:
+ print ('oops')
+ finally:
+ print ('pouet')
+ """
+
+ def test_block_range(self):
+ # XXX ensure expected values
+ self.assertEqual(self.astroid.body[0].block_range(1), (1, 6))
+ self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
+ self.assertEqual(self.astroid.body[0].block_range(3), (3, 4))
+ self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
+ self.assertEqual(self.astroid.body[0].block_range(5), (5, 5))
+ self.assertEqual(self.astroid.body[0].block_range(6), (6, 6))
+
+
+class TryExcept2xNodeTest(_NodeTest):
+ CODE = """
+ try:
+ hello
+ except AttributeError, (retval, desc):
+ pass
+ """
+ def test_tuple_attribute(self):
+ if sys.version_info >= (3, 0):
+ self.skipTest('syntax removed from py3.x')
+ handler = self.astroid.body[0].handlers[0]
+ self.assertIsInstance(handler.name, nodes.Tuple)
+
+
+class ImportNodeTest(resources.SysPathSetup, unittest.TestCase):
+ def setUp(self):
+ super(ImportNodeTest, self).setUp()
+ self.module = resources.build_file('data/module.py', 'data.module')
+ self.module2 = resources.build_file('data/module2.py', 'data.module2')
+
+ def test_import_self_resolve(self):
+ myos = next(self.module2.igetattr('myos'))
+ self.assertTrue(isinstance(myos, nodes.Module), myos)
+ self.assertEqual(myos.name, 'os')
+ self.assertEqual(myos.qname(), 'os')
+ self.assertEqual(myos.pytype(), '%s.module' % BUILTINS)
+
+ def test_from_self_resolve(self):
+ pb = next(self.module.igetattr('pb'))
+ self.assertTrue(isinstance(pb, nodes.Class), pb)
+ self.assertEqual(pb.root().name, 'logilab.common.shellutils')
+ self.assertEqual(pb.qname(), 'logilab.common.shellutils.ProgressBar')
+ if pb.newstyle:
+ self.assertEqual(pb.pytype(), '%s.type' % BUILTINS)
+ else:
+ self.assertEqual(pb.pytype(), '%s.classobj' % BUILTINS)
+ abspath = next(self.module2.igetattr('abspath'))
+ self.assertTrue(isinstance(abspath, nodes.Function), abspath)
+ self.assertEqual(abspath.root().name, 'os.path')
+ self.assertEqual(abspath.qname(), 'os.path.abspath')
+ self.assertEqual(abspath.pytype(), '%s.function' % BUILTINS)
+
+ def test_real_name(self):
+ from_ = self.module['pb']
+ self.assertEqual(from_.real_name('pb'), 'ProgressBar')
+ imp_ = self.module['os']
+ self.assertEqual(imp_.real_name('os'), 'os')
+ self.assertRaises(NotFoundError, imp_.real_name, 'os.path')
+ imp_ = self.module['pb']
+ self.assertEqual(imp_.real_name('pb'), 'ProgressBar')
+ self.assertRaises(NotFoundError, imp_.real_name, 'ProgressBar')
+ imp_ = self.module2['YO']
+ self.assertEqual(imp_.real_name('YO'), 'YO')
+ self.assertRaises(NotFoundError, imp_.real_name, 'data')
+
+ def test_as_string(self):
+ ast = self.module['modutils']
+ self.assertEqual(ast.as_string(), "from astroid import modutils")
+ ast = self.module['pb']
+ self.assertEqual(ast.as_string(), "from logilab.common.shellutils import ProgressBar as pb")
+ ast = self.module['os']
+ self.assertEqual(ast.as_string(), "import os.path")
+ code = """from . import here
+from .. import door
+from .store import bread
+from ..cave import wine\n\n"""
+ ast = abuilder.string_build(code)
+ self.assertMultiLineEqual(ast.as_string(), code)
+
+ def test_bad_import_inference(self):
+ # Explication of bug
+ '''When we import PickleError from nonexistent, a call to the infer
+ method of this From node will be made by unpack_infer.
+ inference.infer_from will try to import this module, which will fail and
+ raise a InferenceException (by mixins.do_import_module). The infer_name
+ will catch this exception and yield and YES instead.
+ '''
+
+ code = '''
+ try:
+ from pickle import PickleError
+ except ImportError:
+ from nonexistent import PickleError
+
+ try:
+ pass
+ except PickleError:
+ pass
+ '''
+ astroid = test_utils.build_module(code)
+ handler_type = astroid.body[1].handlers[0].type
+
+ excs = list(unpack_infer(handler_type))
+ # The number of returned object can differ on Python 2
+ # and Python 3. In one version, an additional item will
+ # be returned, from the _pickle module, which is not
+ # present in the other version.
+ self.assertIsInstance(excs[0], nodes.Class)
+ self.assertEqual(excs[0].name, 'PickleError')
+ self.assertIs(excs[-1], bases.YES)
+
+ def test_absolute_import(self):
+ astroid = resources.build_file('data/absimport.py')
+ ctx = InferenceContext()
+ # will fail if absolute import failed
+ ctx.lookupname = 'message'
+ next(astroid['message'].infer(ctx))
+ ctx.lookupname = 'email'
+ m = next(astroid['email'].infer(ctx))
+ self.assertFalse(m.file.startswith(os.path.join('data', 'email.py')))
+
+ def test_more_absolute_import(self):
+ astroid = resources.build_file('data/module1abs/__init__.py', 'data.module1abs')
+ self.assertIn('sys', astroid.locals)
+
+
+class CmpNodeTest(unittest.TestCase):
+ def test_as_string(self):
+ ast = abuilder.string_build("a == 2").body[0]
+ self.assertEqual(ast.as_string(), "a == 2")
+
+
+class ConstNodeTest(unittest.TestCase):
+
+ def _test(self, value):
+ node = nodes.const_factory(value)
+ self.assertIsInstance(node._proxied, nodes.Class)
+ self.assertEqual(node._proxied.name, value.__class__.__name__)
+ self.assertIs(node.value, value)
+ self.assertTrue(node._proxied.parent)
+ self.assertEqual(node._proxied.root().name, value.__class__.__module__)
+
+ def test_none(self):
+ self._test(None)
+
+ def test_bool(self):
+ self._test(True)
+
+ def test_int(self):
+ self._test(1)
+
+ def test_float(self):
+ self._test(1.0)
+
+ def test_complex(self):
+ self._test(1.0j)
+
+ def test_str(self):
+ self._test('a')
+
+ def test_unicode(self):
+ self._test(u'a')
+
+
+class NameNodeTest(unittest.TestCase):
+ def test_assign_to_True(self):
+ """test that True and False assignements don't crash"""
+ code = """
+ True = False
+ def hello(False):
+ pass
+ del True
+ """
+ if sys.version_info >= (3, 0):
+ with self.assertRaises(SyntaxError):
+ test_utils.build_module(code)
+ else:
+ ast = test_utils.build_module(code)
+ ass_true = ast['True']
+ self.assertIsInstance(ass_true, nodes.AssName)
+ self.assertEqual(ass_true.name, "True")
+ del_true = ast.body[2].targets[0]
+ self.assertIsInstance(del_true, nodes.DelName)
+ self.assertEqual(del_true.name, "True")
+
+
+class ArgumentsNodeTC(unittest.TestCase):
+ def test_linenumbering(self):
+ ast = test_utils.build_module('''
+ def func(a,
+ b): pass
+ x = lambda x: None
+ ''')
+ self.assertEqual(ast['func'].args.fromlineno, 2)
+ self.assertFalse(ast['func'].args.is_statement)
+ xlambda = next(ast['x'].infer())
+ self.assertEqual(xlambda.args.fromlineno, 4)
+ self.assertEqual(xlambda.args.tolineno, 4)
+ self.assertFalse(xlambda.args.is_statement)
+ if sys.version_info < (3, 0):
+ self.assertEqual(ast['func'].args.tolineno, 3)
+ else:
+ self.skipTest('FIXME http://bugs.python.org/issue10445 '
+ '(no line number on function args)')
+
+ def test_builtin_fromlineno_missing(self):
+ cls = test_utils.extract_node('''
+ class Foo(Exception): #@
+ pass
+ ''')
+ new = cls.getattr('__new__')[-1]
+ self.assertEqual(new.args.fromlineno, 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_peephole.py astroid-1.3.8/astroid/tests/unittest_peephole.py
--- astroid-1.0.1/astroid/tests/unittest_peephole.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_peephole.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,120 @@
+# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+
+"""Tests for the astroid AST peephole optimizer."""
+
+import ast
+import textwrap
+import unittest
+
+import astroid
+from astroid import astpeephole
+from astroid import manager
+from astroid import test_utils
+from astroid.tests import resources
+
+
+MANAGER = manager.AstroidManager()
+
+
+class PeepholeOptimizer(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ MANAGER.optimize_ast = True
+
+ @classmethod
+ def tearDownClass(cls):
+ MANAGER.optimize_ast = False
+
+ def setUp(self):
+ self._optimizer = astpeephole.ASTPeepholeOptimizer()
+
+ @staticmethod
+ def _get_binops(code):
+ module = ast.parse(textwrap.dedent(code))
+ return [node.value for node in module.body
+ if isinstance(node, ast.Expr)]
+
+ @test_utils.require_version(maxver='3.0')
+ def test_optimize_binop_unicode(self):
+ nodes = self._get_binops("""
+ u"a" + u"b" + u"c"
+
+ u"a" + "c" + "b"
+ u"a" + b"c"
+ """)
+
+ result = self._optimizer.optimize_binop(nodes[0])
+ self.assertIsInstance(result, astroid.Const)
+ self.assertEqual(result.value, u"abc")
+
+ self.assertIsNone(self._optimizer.optimize_binop(nodes[1]))
+ self.assertIsNone(self._optimizer.optimize_binop(nodes[2]))
+
+ def test_optimize_binop(self):
+ nodes = self._get_binops("""
+ "a" + "b" + "c" + "d"
+ b"a" + b"b" + b"c" + b"d"
+ "a" + "b"
+
+ "a" + "b" + 1 + object
+ var = 4
+ "a" + "b" + var + "c"
+ "a" + "b" + "c" - "4"
+ "a" + "b" + "c" + "d".format()
+ "a" - "b"
+ "a"
+ 1 + 4 + 5 + 6
+ """)
+
+ result = self._optimizer.optimize_binop(nodes[0])
+ self.assertIsInstance(result, astroid.Const)
+ self.assertEqual(result.value, "abcd")
+
+ result = self._optimizer.optimize_binop(nodes[1])
+ self.assertIsInstance(result, astroid.Const)
+ self.assertEqual(result.value, b"abcd")
+
+ for node in nodes[2:]:
+ self.assertIsNone(self._optimizer.optimize_binop(node))
+
+ def test_big_binop_crash(self):
+ # Test that we don't fail on a lot of joined strings
+ # through the addition operator.
+ module = resources.build_file('data/joined_strings.py')
+ element = next(module['x'].infer())
+ self.assertIsInstance(element, astroid.Const)
+ self.assertEqual(len(element.value), 61660)
+
+ def test_optimisation_disabled(self):
+ try:
+ MANAGER.optimize_ast = False
+ module = test_utils.build_module("""
+ '1' + '2' + '3'
+ """)
+ self.assertIsInstance(module.body[0], astroid.Discard)
+ self.assertIsInstance(module.body[0].value, astroid.BinOp)
+ self.assertIsInstance(module.body[0].value.left, astroid.BinOp)
+ self.assertIsInstance(module.body[0].value.left.left,
+ astroid.Const)
+ finally:
+ MANAGER.optimize_ast = True
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_protocols.py astroid-1.3.8/astroid/tests/unittest_protocols.py
--- astroid-1.0.1/astroid/tests/unittest_protocols.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_protocols.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,153 @@
+# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+
+import unittest
+
+from astroid import YES
+from astroid.test_utils import extract_node, require_version
+from astroid import InferenceError
+from astroid.node_classes import AssName, Const, Name, Starred
+
+
+class ProtocolTests(unittest.TestCase):
+
+ def assertConstNodesEqual(self, nodes_list_expected, nodes_list_got):
+ self.assertEqual(len(nodes_list_expected), len(nodes_list_got))
+ for node in nodes_list_got:
+ self.assertIsInstance(node, Const)
+ for node, expected_value in zip(nodes_list_got, nodes_list_expected):
+ self.assertEqual(expected_value, node.value)
+
+ def assertNameNodesEqual(self, nodes_list_expected, nodes_list_got):
+ self.assertEqual(len(nodes_list_expected), len(nodes_list_got))
+ for node in nodes_list_got:
+ self.assertIsInstance(node, Name)
+ for node, expected_name in zip(nodes_list_got, nodes_list_expected):
+ self.assertEqual(expected_name, node.name)
+
+ def test_assigned_stmts_simple_for(self):
+ assign_stmts = extract_node("""
+ for a in (1, 2, 3): #@
+ pass
+
+ for b in range(3): #@
+ pass
+ """)
+
+ for1_assnode = next(assign_stmts[0].nodes_of_class(AssName))
+ assigned = list(for1_assnode.assigned_stmts())
+ self.assertConstNodesEqual([1, 2, 3], assigned)
+
+ for2_assnode = next(assign_stmts[1].nodes_of_class(AssName))
+ self.assertRaises(InferenceError,
+ list, for2_assnode.assigned_stmts())
+
+ @require_version(minver='3.0')
+ def test_assigned_stmts_starred_for(self):
+ assign_stmts = extract_node("""
+ for *a, b in ((1, 2, 3), (4, 5, 6, 7)): #@
+ pass
+ """)
+
+ for1_starred = next(assign_stmts.nodes_of_class(Starred))
+ assigned = list(for1_starred.assigned_stmts())
+ self.assertEqual(assigned, [])
+
+ def _get_starred_stmts(self, code, expected):
+ assign_stmt = extract_node("{} #@".format(code))
+ starred = next(assign_stmt.nodes_of_class(Starred))
+ return list(starred.assigned_stmts())
+
+ def _helper_starred_expected_const(self, code, expected):
+ stmts = self._get_starred_stmts(code, expected)
+ self.assertConstNodesEqual(expected, stmts)
+
+ def _helper_starred_expected(self, code, expected):
+ stmts = self._get_starred_stmts(code, expected)
+ self.assertEqual(expected, stmts)
+
+ def _helper_starred_inference_error(self, code):
+ assign_stmt = extract_node("{} #@".format(code))
+ starred = next(assign_stmt.nodes_of_class(Starred))
+ self.assertRaises(InferenceError, list, starred.assigned_stmts())
+
+ @require_version(minver='3.0')
+ def test_assigned_stmts_starred_assnames(self):
+ self._helper_starred_expected_const(
+ "a, *b = (1, 2, 3, 4) #@", [2, 3, 4])
+ self._helper_starred_expected_const(
+ "*a, b = (1, 2, 3) #@", [1, 2])
+ self._helper_starred_expected_const(
+ "a, *b, c = (1, 2, 3, 4, 5) #@",
+ [2, 3, 4])
+ self._helper_starred_expected_const(
+ "a, *b = (1, 2) #@", [2])
+ self._helper_starred_expected_const(
+ "*b, a = (1, 2) #@", [1])
+ self._helper_starred_expected_const(
+ "[*b] = (1, 2) #@", [1, 2])
+
+ @require_version(minver='3.0')
+ def test_assigned_stmts_starred_yes(self):
+ # Not something iterable and known
+ self._helper_starred_expected("a, *b = range(3) #@", [YES])
+ # Not something inferrable
+ self._helper_starred_expected("a, *b = balou() #@", [YES])
+ # In function, unknown.
+ self._helper_starred_expected("""
+ def test(arg):
+ head, *tail = arg #@""", [YES])
+ # These cases aren't worth supporting.
+ self._helper_starred_expected(
+ "a, (*b, c), d = (1, (2, 3, 4), 5) #@", [])
+
+ @require_version(minver='3.0')
+ def test_assign_stmts_starred_fails(self):
+ # Too many starred
+ self._helper_starred_inference_error("a, *b, *c = (1, 2, 3) #@")
+ # Too many lhs values
+ self._helper_starred_inference_error("a, *b, c = (1, 2) #@")
+ # Not in Assign or For
+ self._helper_starred_inference_error("[*b for b in (1, 2, 3)] #@")
+ # This could be solved properly, but it complicates needlessly the
+ # code for assigned_stmts, without oferring real benefit.
+ self._helper_starred_inference_error(
+ "(*a, b), (c, *d) = (1, 2, 3), (4, 5, 6) #@")
+
+ def test_assigned_stmts_assignments(self):
+ assign_stmts = extract_node("""
+ c = a #@
+
+ d, e = b, c #@
+ """)
+
+ simple_assnode = next(assign_stmts[0].nodes_of_class(AssName))
+ assigned = list(simple_assnode.assigned_stmts())
+ self.assertNameNodesEqual(['a'], assigned)
+
+ assnames = assign_stmts[1].nodes_of_class(AssName)
+ simple_mul_assnode_1 = next(assnames)
+ assigned = list(simple_mul_assnode_1.assigned_stmts())
+ self.assertNameNodesEqual(['b'], assigned)
+ simple_mul_assnode_2 = next(assnames)
+ assigned = list(simple_mul_assnode_2.assigned_stmts())
+ self.assertNameNodesEqual(['c'], assigned)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_python3.py astroid-1.3.8/astroid/tests/unittest_python3.py
--- astroid-1.0.1/astroid/tests/unittest_python3.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_python3.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,218 @@
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+from textwrap import dedent
+import unittest
+
+from astroid.node_classes import Assign, Discard, YieldFrom, Name, Const
+from astroid.builder import AstroidBuilder
+from astroid.scoped_nodes import Class, Function
+from astroid.test_utils import require_version
+
+
+class Python3TC(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.builder = AstroidBuilder()
+
+ @require_version('3.0')
+ def test_starred_notation(self):
+ astroid = self.builder.string_build("*a, b = [1, 2, 3]", 'test', 'test')
+
+ # Get the star node
+ node = next(next(next(astroid.get_children()).get_children()).get_children())
+
+ self.assertTrue(isinstance(node.ass_type(), Assign))
+
+ @require_version('3.3')
+ def test_yield_from(self):
+ body = dedent("""
+ def func():
+ yield from iter([1, 2])
+ """)
+ astroid = self.builder.string_build(body)
+ func = astroid.body[0]
+ self.assertIsInstance(func, Function)
+ yieldfrom_stmt = func.body[0]
+
+ self.assertIsInstance(yieldfrom_stmt, Discard)
+ self.assertIsInstance(yieldfrom_stmt.value, YieldFrom)
+ self.assertEqual(yieldfrom_stmt.as_string(),
+ 'yield from iter([1, 2])')
+
+ @require_version('3.3')
+ def test_yield_from_is_generator(self):
+ body = dedent("""
+ def func():
+ yield from iter([1, 2])
+ """)
+ astroid = self.builder.string_build(body)
+ func = astroid.body[0]
+ self.assertIsInstance(func, Function)
+ self.assertTrue(func.is_generator())
+
+ @require_version('3.3')
+ def test_yield_from_as_string(self):
+ body = dedent("""
+ def func():
+ yield from iter([1, 2])
+ value = yield from other()
+ """)
+ astroid = self.builder.string_build(body)
+ func = astroid.body[0]
+ self.assertEqual(func.as_string().strip(), body.strip())
+
+ # metaclass tests
+
+ @require_version('3.0')
+ def test_simple_metaclass(self):
+ astroid = self.builder.string_build("class Test(metaclass=type): pass")
+ klass = astroid.body[0]
+
+ metaclass = klass.metaclass()
+ self.assertIsInstance(metaclass, Class)
+ self.assertEqual(metaclass.name, 'type')
+
+ @require_version('3.0')
+ def test_metaclass_error(self):
+ astroid = self.builder.string_build("class Test(metaclass=typ): pass")
+ klass = astroid.body[0]
+ self.assertFalse(klass.metaclass())
+
+ @require_version('3.0')
+ def test_metaclass_imported(self):
+ astroid = self.builder.string_build(dedent("""
+ from abc import ABCMeta
+ class Test(metaclass=ABCMeta): pass"""))
+ klass = astroid.body[1]
+
+ metaclass = klass.metaclass()
+ self.assertIsInstance(metaclass, Class)
+ self.assertEqual(metaclass.name, 'ABCMeta')
+
+ @require_version('3.0')
+ def test_as_string(self):
+ body = dedent("""
+ from abc import ABCMeta
+ class Test(metaclass=ABCMeta): pass""")
+ astroid = self.builder.string_build(body)
+ klass = astroid.body[1]
+
+ self.assertEqual(klass.as_string(),
+ '\n\nclass Test(metaclass=ABCMeta):\n pass\n')
+
+ @require_version('3.0')
+ def test_old_syntax_works(self):
+ astroid = self.builder.string_build(dedent("""
+ class Test:
+ __metaclass__ = type
+ class SubTest(Test): pass
+ """))
+ klass = astroid['SubTest']
+ metaclass = klass.metaclass()
+ self.assertIsNone(metaclass)
+
+ @require_version('3.0')
+ def test_metaclass_yes_leak(self):
+ astroid = self.builder.string_build(dedent("""
+ # notice `ab` instead of `abc`
+ from ab import ABCMeta
+
+ class Meta(metaclass=ABCMeta): pass
+ """))
+ klass = astroid['Meta']
+ self.assertIsNone(klass.metaclass())
+
+ @require_version('3.0')
+ def test_parent_metaclass(self):
+ astroid = self.builder.string_build(dedent("""
+ from abc import ABCMeta
+ class Test(metaclass=ABCMeta): pass
+ class SubTest(Test): pass
+ """))
+ klass = astroid['SubTest']
+ self.assertTrue(klass.newstyle)
+ metaclass = klass.metaclass()
+ self.assertIsInstance(metaclass, Class)
+ self.assertEqual(metaclass.name, 'ABCMeta')
+
+ @require_version('3.0')
+ def test_metaclass_ancestors(self):
+ astroid = self.builder.string_build(dedent("""
+ from abc import ABCMeta
+
+ class FirstMeta(metaclass=ABCMeta): pass
+ class SecondMeta(metaclass=type):
+ pass
+
+ class Simple:
+ pass
+
+ class FirstImpl(FirstMeta): pass
+ class SecondImpl(FirstImpl): pass
+ class ThirdImpl(Simple, SecondMeta):
+ pass
+ """))
+ classes = {
+ 'ABCMeta': ('FirstImpl', 'SecondImpl'),
+ 'type': ('ThirdImpl', )
+ }
+ for metaclass, names in classes.items():
+ for name in names:
+ impl = astroid[name]
+ meta = impl.metaclass()
+ self.assertIsInstance(meta, Class)
+ self.assertEqual(meta.name, metaclass)
+
+ @require_version('3.0')
+ def test_annotation_support(self):
+ astroid = self.builder.string_build(dedent("""
+ def test(a: int, b: str, c: None, d, e,
+ *args: float, **kwargs: int)->int:
+ pass
+ """))
+ func = astroid['test']
+ self.assertIsInstance(func.args.varargannotation, Name)
+ self.assertEqual(func.args.varargannotation.name, 'float')
+ self.assertIsInstance(func.args.kwargannotation, Name)
+ self.assertEqual(func.args.kwargannotation.name, 'int')
+ self.assertIsInstance(func.returns, Name)
+ self.assertEqual(func.returns.name, 'int')
+ arguments = func.args
+ self.assertIsInstance(arguments.annotations[0], Name)
+ self.assertEqual(arguments.annotations[0].name, 'int')
+ self.assertIsInstance(arguments.annotations[1], Name)
+ self.assertEqual(arguments.annotations[1].name, 'str')
+ self.assertIsInstance(arguments.annotations[2], Const)
+ self.assertIsNone(arguments.annotations[2].value)
+ self.assertIsNone(arguments.annotations[3])
+ self.assertIsNone(arguments.annotations[4])
+
+ astroid = self.builder.string_build(dedent("""
+ def test(a: int=1, b: str=2):
+ pass
+ """))
+ func = astroid['test']
+ self.assertIsInstance(func.args.annotations[0], Name)
+ self.assertEqual(func.args.annotations[0].name, 'int')
+ self.assertIsInstance(func.args.annotations[1], Name)
+ self.assertEqual(func.args.annotations[1].name, 'str')
+ self.assertIsNone(func.returns)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_raw_building.py astroid-1.3.8/astroid/tests/unittest_raw_building.py
--- astroid-1.0.1/astroid/tests/unittest_raw_building.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_raw_building.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,48 @@
+import unittest
+
+from astroid.raw_building import (attach_dummy_node, build_module, build_class, build_function, build_from_import)
+
+class RawBuildingTC(unittest.TestCase):
+
+ def test_attach_dummy_node(self):
+ node = build_module('MyModule')
+ dummy = attach_dummy_node(node, 'DummyNode')
+ self.assertEqual(1, len(list(node.get_children())))
+
+ def test_build_module(self):
+ node = build_module('MyModule')
+ self.assertEqual(node.name, 'MyModule')
+ self.assertEqual(node.pure_python, False)
+ self.assertEqual(node.package, False)
+ self.assertEqual(node.parent, None)
+
+ def test_build_class(self):
+ node = build_class('MyClass')
+ self.assertEqual(node.name, 'MyClass')
+ self.assertEqual(node.doc, None)
+
+ def test_build_function(self):
+ node = build_function('MyFunction')
+ self.assertEqual(node.name, 'MyFunction')
+ self.assertEqual(node.doc, None)
+
+ def test_build_function_args(self):
+ args = ['myArgs1', 'myArgs2']
+ node = build_function('MyFunction', args)
+ self.assertEqual('myArgs1', node.args.args[0].name)
+ self.assertEqual('myArgs2', node.args.args[1].name)
+ self.assertEqual(2, len(node.args.args))
+
+ def test_build_function_defaults(self):
+ defaults = ['defaults1', 'defaults2']
+ node = build_function('MyFunction', None, defaults)
+ self.assertEqual(2, len(node.args.defaults))
+
+ def test_build_from_import(self):
+ names = ['exceptions, inference, inspector']
+ node = build_from_import('astroid', names)
+ self.assertEqual(len(names), len(node.names))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_regrtest.py astroid-1.3.8/astroid/tests/unittest_regrtest.py
--- astroid-1.0.1/astroid/tests/unittest_regrtest.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_regrtest.py 2015-08-02 20:37:37.000000000 +0000
@@ -0,0 +1,276 @@
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+import sys
+import unittest
+import textwrap
+
+import six
+
+from astroid import MANAGER, Instance, nodes
+from astroid.bases import BUILTINS
+from astroid.builder import AstroidBuilder
+from astroid.raw_building import build_module
+from astroid.manager import AstroidManager
+from astroid.test_utils import require_version, extract_node
+from astroid.tests import resources
+
+class NonRegressionTests(resources.AstroidCacheSetupMixin,
+ unittest.TestCase):
+
+ def setUp(self):
+ sys.path.insert(0, resources.find('data'))
+ MANAGER.always_load_extensions = True
+
+ def tearDown(self):
+ # Since we may have created a brainless manager, leading
+ # to a new cache builtin module and proxy classes in the constants,
+ # clear out the global manager cache.
+ MANAGER.clear_cache(self._builtins)
+ MANAGER.always_load_extensions = False
+ sys.path.pop(0)
+ sys.path_importer_cache.pop(resources.find('data'), None)
+
+ def brainless_manager(self):
+ manager = AstroidManager()
+ # avoid caching into the AstroidManager borg since we get problems
+ # with other tests :
+ manager.__dict__ = {}
+ manager.astroid_cache = {}
+ manager._mod_file_cache = {}
+ manager.transforms = {}
+ manager.clear_cache() # trigger proper bootstraping
+ return manager
+
+ def test_module_path(self):
+ man = self.brainless_manager()
+ mod = man.ast_from_module_name('package.import_package_subpackage_module')
+ package = next(mod.igetattr('package'))
+ self.assertEqual(package.name, 'package')
+ subpackage = next(package.igetattr('subpackage'))
+ self.assertIsInstance(subpackage, nodes.Module)
+ self.assertTrue(subpackage.package)
+ self.assertEqual(subpackage.name, 'package.subpackage')
+ module = next(subpackage.igetattr('module'))
+ self.assertEqual(module.name, 'package.subpackage.module')
+
+
+ def test_package_sidepackage(self):
+ manager = self.brainless_manager()
+ assert 'package.sidepackage' not in MANAGER.astroid_cache
+ package = manager.ast_from_module_name('absimp')
+ self.assertIsInstance(package, nodes.Module)
+ self.assertTrue(package.package)
+ subpackage = next(package.getattr('sidepackage')[0].infer())
+ self.assertIsInstance(subpackage, nodes.Module)
+ self.assertTrue(subpackage.package)
+ self.assertEqual(subpackage.name, 'absimp.sidepackage')
+
+
+ def test_living_property(self):
+ builder = AstroidBuilder()
+ builder._done = {}
+ builder._module = sys.modules[__name__]
+ builder.object_build(build_module('module_name', ''), Whatever)
+
+
+ def test_new_style_class_detection(self):
+ try:
+ import pygtk # pylint: disable=unused-variable
+ except ImportError:
+ self.skipTest('test skipped: pygtk is not available')
+ # XXX may fail on some pygtk version, because objects in
+ # gobject._gobject have __module__ set to gobject :(
+ builder = AstroidBuilder()
+ data = """
+import pygtk
+pygtk.require("2.6")
+import gobject
+
+class A(gobject.GObject):
+ pass
+"""
+ astroid = builder.string_build(data, __name__, __file__)
+ a = astroid['A']
+ self.assertTrue(a.newstyle)
+
+
+ def test_pylint_config_attr(self):
+ try:
+ from pylint import lint # pylint: disable=unused-variable
+ except ImportError:
+ self.skipTest('pylint not available')
+ mod = MANAGER.ast_from_module_name('pylint.lint')
+ pylinter = mod['PyLinter']
+ expect = ['OptionsManagerMixIn', 'object', 'MessagesHandlerMixIn',
+ 'ReportsHandlerMixIn', 'BaseTokenChecker', 'BaseChecker',
+ 'OptionsProviderMixIn']
+ self.assertListEqual([c.name for c in pylinter.ancestors()],
+ expect)
+ self.assertTrue(list(Instance(pylinter).getattr('config')))
+ infered = list(Instance(pylinter).igetattr('config'))
+ self.assertEqual(len(infered), 1)
+ self.assertEqual(infered[0].root().name, 'optparse')
+ self.assertEqual(infered[0].name, 'Values')
+
+ def test_numpy_crash(self):
+ """test don't crash on numpy"""
+ #a crash occured somewhere in the past, and an
+ # InferenceError instead of a crash was better, but now we even infer!
+ try:
+ import numpy # pylint: disable=unused-variable
+ except ImportError:
+ self.skipTest('test skipped: numpy is not available')
+ builder = AstroidBuilder()
+ data = """
+from numpy import multiply
+
+multiply(1, 2, 3)
+"""
+ astroid = builder.string_build(data, __name__, __file__)
+ callfunc = astroid.body[1].value.func
+ infered = callfunc.infered()
+ self.assertEqual(len(infered), 1)
+
+ @require_version('3.0')
+ def test_nameconstant(self):
+ # used to fail for Python 3.4
+ builder = AstroidBuilder()
+ astroid = builder.string_build("def test(x=True): pass")
+ default = astroid.body[0].args.args[0]
+ self.assertEqual(default.name, 'x')
+ self.assertEqual(next(default.infer()).value, True)
+
+ @require_version('2.7')
+ def test_with_infer_assnames(self):
+ builder = AstroidBuilder()
+ data = """
+with open('a.txt') as stream, open('b.txt'):
+ stream.read()
+"""
+ astroid = builder.string_build(data, __name__, __file__)
+ # Used to crash due to the fact that the second
+ # context manager didn't use an assignment name.
+ list(astroid.nodes_of_class(nodes.CallFunc))[-1].infered()
+
+ def test_recursion_regression_issue25(self):
+ builder = AstroidBuilder()
+ data = """
+import recursion as base
+
+_real_Base = base.Base
+
+class Derived(_real_Base):
+ pass
+
+def run():
+ base.Base = Derived
+"""
+ astroid = builder.string_build(data, __name__, __file__)
+ # Used to crash in _is_metaclass, due to wrong
+ # ancestors chain
+ classes = astroid.nodes_of_class(nodes.Class)
+ for klass in classes:
+ # triggers the _is_metaclass call
+ klass.type
+
+ def test_decorator_callchain_issue42(self):
+ builder = AstroidBuilder()
+ data = """
+
+def test():
+ def factory(func):
+ def newfunc():
+ func()
+ return newfunc
+ return factory
+
+@test()
+def crash():
+ pass
+"""
+ astroid = builder.string_build(data, __name__, __file__)
+ self.assertEqual(astroid['crash'].type, 'function')
+
+ def test_filter_stmts_scoping(self):
+ builder = AstroidBuilder()
+ data = """
+def test():
+ compiler = int()
+ class B(compiler.__class__):
+ pass
+ compiler = B()
+ return compiler
+"""
+ astroid = builder.string_build(data, __name__, __file__)
+ test = astroid['test']
+ result = next(test.infer_call_result(astroid))
+ self.assertIsInstance(result, Instance)
+ base = next(result._proxied.bases[0].infer())
+ self.assertEqual(base.name, 'int')
+
+ def test_ancestors_patching_class_recursion(self):
+ node = AstroidBuilder().string_build(textwrap.dedent("""
+ import string
+ Template = string.Template
+
+ class A(Template):
+ pass
+
+ class B(A):
+ pass
+
+ def test(x=False):
+ if x:
+ string.Template = A
+ else:
+ string.Template = B
+ """))
+ klass = node['A']
+ ancestors = list(klass.ancestors())
+ self.assertEqual(ancestors[0].qname(), 'string.Template')
+
+ def test_ancestors_yes_in_bases(self):
+ # Test for issue https://bitbucket.org/logilab/astroid/issue/84
+ # This used to crash astroid with a TypeError, because an YES
+ # node was present in the bases
+ node = extract_node("""
+ def with_metaclass(meta, *bases):
+ class metaclass(meta):
+ def __new__(cls, name, this_bases, d):
+ return meta(name, bases, d)
+ return type.__new__(metaclass, 'temporary_class', (), {})
+
+ import lala
+
+ class A(with_metaclass(object, lala.lala)): #@
+ pass
+ """)
+ ancestors = list(node.ancestors())
+ if six.PY3:
+ self.assertEqual(len(ancestors), 1)
+ self.assertEqual(ancestors[0].qname(),
+ "{}.object".format(BUILTINS))
+ else:
+ self.assertEqual(len(ancestors), 0)
+
+
+class Whatever(object):
+ a = property(lambda x: x, lambda x: x)
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_scoped_nodes.py astroid-1.3.8/astroid/tests/unittest_scoped_nodes.py
--- astroid-1.0.1/astroid/tests/unittest_scoped_nodes.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_scoped_nodes.py 2015-08-02 19:35:46.000000000 +0000
@@ -0,0 +1,1197 @@
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""tests for specific behaviour of astroid scoped nodes (i.e. module, class and
+function)
+"""
+import os
+import sys
+from functools import partial
+import unittest
+import warnings
+
+from astroid import YES, builder, nodes, scoped_nodes, \
+ InferenceError, NotFoundError, NoDefault, ResolveError
+from astroid.bases import BUILTINS, Instance, BoundMethod, UnboundMethod
+from astroid import __pkginfo__
+from astroid import test_utils
+from astroid.tests import resources
+
+
+def _test_dict_interface(self, node, test_attr):
+ self.assertIs(node[test_attr], node[test_attr])
+ self.assertIn(test_attr, node)
+ node.keys()
+ node.values()
+ node.items()
+ iter(node)
+
+
+class ModuleLoader(resources.SysPathSetup):
+ def setUp(self):
+ super(ModuleLoader, self).setUp()
+ self.module = resources.build_file('data/module.py', 'data.module')
+ self.module2 = resources.build_file('data/module2.py', 'data.module2')
+ self.nonregr = resources.build_file('data/nonregr.py', 'data.nonregr')
+ self.pack = resources.build_file('data/__init__.py', 'data')
+
+
+class ModuleNodeTest(ModuleLoader, unittest.TestCase):
+
+ def test_special_attributes(self):
+ self.assertEqual(len(self.module.getattr('__name__')), 1)
+ self.assertIsInstance(self.module.getattr('__name__')[0], nodes.Const)
+ self.assertEqual(self.module.getattr('__name__')[0].value, 'data.module')
+ self.assertEqual(len(self.module.getattr('__doc__')), 1)
+ self.assertIsInstance(self.module.getattr('__doc__')[0], nodes.Const)
+ self.assertEqual(self.module.getattr('__doc__')[0].value, 'test module for astroid\n')
+ self.assertEqual(len(self.module.getattr('__file__')), 1)
+ self.assertIsInstance(self.module.getattr('__file__')[0], nodes.Const)
+ self.assertEqual(self.module.getattr('__file__')[0].value,
+ os.path.abspath(resources.find('data/module.py')))
+ self.assertEqual(len(self.module.getattr('__dict__')), 1)
+ self.assertIsInstance(self.module.getattr('__dict__')[0], nodes.Dict)
+ self.assertRaises(NotFoundError, self.module.getattr, '__path__')
+ self.assertEqual(len(self.pack.getattr('__path__')), 1)
+ self.assertIsInstance(self.pack.getattr('__path__')[0], nodes.List)
+
+ def test_dict_interface(self):
+ _test_dict_interface(self, self.module, 'YO')
+
+ def test_getattr(self):
+ yo = self.module.getattr('YO')[0]
+ self.assertIsInstance(yo, nodes.Class)
+ self.assertEqual(yo.name, 'YO')
+ red = next(self.module.igetattr('redirect'))
+ self.assertIsInstance(red, nodes.Function)
+ self.assertEqual(red.name, 'four_args')
+ pb = next(self.module.igetattr('pb'))
+ self.assertIsInstance(pb, nodes.Class)
+ self.assertEqual(pb.name, 'ProgressBar')
+ # resolve packageredirection
+ mod = resources.build_file('data/appl/myConnection.py',
+ 'data.appl.myConnection')
+ ssl = next(mod.igetattr('SSL1'))
+ cnx = next(ssl.igetattr('Connection'))
+ self.assertEqual(cnx.__class__, nodes.Class)
+ self.assertEqual(cnx.name, 'Connection')
+ self.assertEqual(cnx.root().name, 'data.SSL1.Connection1')
+ self.assertEqual(len(self.nonregr.getattr('enumerate')), 2)
+ # raise ResolveError
+ self.assertRaises(InferenceError, self.nonregr.igetattr, 'YOAA')
+
+ def test_wildard_import_names(self):
+ m = resources.build_file('data/all.py', 'all')
+ self.assertEqual(m.wildcard_import_names(), ['Aaa', '_bla', 'name'])
+ m = resources.build_file('data/notall.py', 'notall')
+ res = sorted(m.wildcard_import_names())
+ self.assertEqual(res, ['Aaa', 'func', 'name', 'other'])
+
+ m = test_utils.build_module('''
+ from missing import tzop
+ trop = "test"
+ __all__ = (trop, "test1", tzop, 42)
+ ''')
+ res = sorted(m.wildcard_import_names())
+ self.assertEqual(res, ["test", "test1"])
+
+ m = test_utils.build_module('''
+ test = tzop = 42
+ __all__ = ('test', ) + ('tzop', )
+ ''')
+ res = sorted(m.wildcard_import_names())
+ self.assertEqual(res, ['test', 'tzop'])
+
+ def test_module_getattr(self):
+ data = '''
+ appli = application
+ appli += 2
+ del appli
+ '''
+ astroid = test_utils.build_module(data, __name__)
+ # test del statement not returned by getattr
+ self.assertEqual(len(astroid.getattr('appli')), 2,
+ astroid.getattr('appli'))
+
+ def test_relative_to_absolute_name(self):
+ # package
+ mod = nodes.Module('very.multi.package', 'doc')
+ mod.package = True
+ modname = mod.relative_to_absolute_name('utils', 1)
+ self.assertEqual(modname, 'very.multi.package.utils')
+ modname = mod.relative_to_absolute_name('utils', 2)
+ self.assertEqual(modname, 'very.multi.utils')
+ modname = mod.relative_to_absolute_name('utils', 0)
+ self.assertEqual(modname, 'very.multi.package.utils')
+ modname = mod.relative_to_absolute_name('', 1)
+ self.assertEqual(modname, 'very.multi.package')
+ # non package
+ mod = nodes.Module('very.multi.module', 'doc')
+ mod.package = False
+ modname = mod.relative_to_absolute_name('utils', 0)
+ self.assertEqual(modname, 'very.multi.utils')
+ modname = mod.relative_to_absolute_name('utils', 1)
+ self.assertEqual(modname, 'very.multi.utils')
+ modname = mod.relative_to_absolute_name('utils', 2)
+ self.assertEqual(modname, 'very.utils')
+ modname = mod.relative_to_absolute_name('', 1)
+ self.assertEqual(modname, 'very.multi')
+
+ def test_import_1(self):
+ data = '''from . import subpackage'''
+ sys.path.insert(0, resources.find('data'))
+ astroid = test_utils.build_module(data, 'package', 'data/package/__init__.py')
+ try:
+ m = astroid.import_module('', level=1)
+ self.assertEqual(m.name, 'package')
+ infered = list(astroid.igetattr('subpackage'))
+ self.assertEqual(len(infered), 1)
+ self.assertEqual(infered[0].name, 'package.subpackage')
+ finally:
+ del sys.path[0]
+
+
+ def test_import_2(self):
+ data = '''from . import subpackage as pouet'''
+ astroid = test_utils.build_module(data, 'package', 'data/package/__init__.py')
+ sys.path.insert(0, resources.find('data'))
+ try:
+ m = astroid.import_module('', level=1)
+ self.assertEqual(m.name, 'package')
+ infered = list(astroid.igetattr('pouet'))
+ self.assertEqual(len(infered), 1)
+ self.assertEqual(infered[0].name, 'package.subpackage')
+ finally:
+ del sys.path[0]
+
+
+ def test_file_stream_in_memory(self):
+ data = '''irrelevant_variable is irrelevant'''
+ astroid = test_utils.build_module(data, 'in_memory')
+ with warnings.catch_warnings(record=True):
+ self.assertEqual(astroid.file_stream.read().decode(), data)
+
+ def test_file_stream_physical(self):
+ path = resources.find('data/all.py')
+ astroid = builder.AstroidBuilder().file_build(path, 'all')
+ with open(path, 'rb') as file_io:
+ with warnings.catch_warnings(record=True):
+ self.assertEqual(astroid.file_stream.read(), file_io.read())
+
+ def test_file_stream_api(self):
+ path = resources.find('data/all.py')
+ astroid = builder.AstroidBuilder().file_build(path, 'all')
+ if __pkginfo__.numversion >= (1, 6):
+ # file_stream is slated for removal in astroid 1.6.
+ with self.assertRaises(AttributeError):
+ astroid.file_stream
+ else:
+ # Until astroid 1.6, Module.file_stream will emit
+ # PendingDeprecationWarning in 1.4, DeprecationWarning
+ # in 1.5 and finally it will be removed in 1.6, leaving
+ # only Module.stream as the recommended way to retrieve
+ # its file stream.
+ with warnings.catch_warnings(record=True) as cm:
+ warnings.simplefilter("always")
+ self.assertIsNot(astroid.file_stream, astroid.file_stream)
+ self.assertGreater(len(cm), 1)
+ self.assertEqual(cm[0].category, PendingDeprecationWarning)
+
+ def test_stream_api(self):
+ path = resources.find('data/all.py')
+ astroid = builder.AstroidBuilder().file_build(path, 'all')
+ stream = astroid.stream()
+ self.assertTrue(hasattr(stream, 'close'))
+ with stream:
+ with open(path, 'rb') as file_io:
+ self.assertEqual(stream.read(), file_io.read())
+
+
+class FunctionNodeTest(ModuleLoader, unittest.TestCase):
+
+ def test_special_attributes(self):
+ func = self.module2['make_class']
+ self.assertEqual(len(func.getattr('__name__')), 1)
+ self.assertIsInstance(func.getattr('__name__')[0], nodes.Const)
+ self.assertEqual(func.getattr('__name__')[0].value, 'make_class')
+ self.assertEqual(len(func.getattr('__doc__')), 1)
+ self.assertIsInstance(func.getattr('__doc__')[0], nodes.Const)
+ self.assertEqual(func.getattr('__doc__')[0].value, 'check base is correctly resolved to Concrete0')
+ self.assertEqual(len(self.module.getattr('__dict__')), 1)
+ self.assertIsInstance(self.module.getattr('__dict__')[0], nodes.Dict)
+
+ def test_dict_interface(self):
+ _test_dict_interface(self, self.module['global_access'], 'local')
+
+ def test_default_value(self):
+ func = self.module2['make_class']
+ self.assertIsInstance(func.args.default_value('base'), nodes.Getattr)
+ self.assertRaises(NoDefault, func.args.default_value, 'args')
+ self.assertRaises(NoDefault, func.args.default_value, 'kwargs')
+ self.assertRaises(NoDefault, func.args.default_value, 'any')
+ #self.assertIsInstance(func.mularg_class('args'), nodes.Tuple)
+ #self.assertIsInstance(func.mularg_class('kwargs'), nodes.Dict)
+ #self.assertIsNone(func.mularg_class('base'))
+
+ def test_navigation(self):
+ function = self.module['global_access']
+ self.assertEqual(function.statement(), function)
+ l_sibling = function.previous_sibling()
+ # check taking parent if child is not a stmt
+ self.assertIsInstance(l_sibling, nodes.Assign)
+ child = function.args.args[0]
+ self.assertIs(l_sibling, child.previous_sibling())
+ r_sibling = function.next_sibling()
+ self.assertIsInstance(r_sibling, nodes.Class)
+ self.assertEqual(r_sibling.name, 'YO')
+ self.assertIs(r_sibling, child.next_sibling())
+ last = r_sibling.next_sibling().next_sibling().next_sibling()
+ self.assertIsInstance(last, nodes.Assign)
+ self.assertIsNone(last.next_sibling())
+ first = l_sibling.previous_sibling().previous_sibling().previous_sibling().previous_sibling().previous_sibling()
+ self.assertIsNone(first.previous_sibling())
+
+ def test_nested_args(self):
+ if sys.version_info >= (3, 0):
+ self.skipTest("nested args has been removed in py3.x")
+ code = '''
+ def nested_args(a, (b, c, d)):
+ "nested arguments test"
+ '''
+ tree = test_utils.build_module(code)
+ func = tree['nested_args']
+ self.assertEqual(sorted(func.locals), ['a', 'b', 'c', 'd'])
+ self.assertEqual(func.args.format_args(), 'a, (b, c, d)')
+
+ def test_four_args(self):
+ func = self.module['four_args']
+ #self.assertEqual(func.args.args, ['a', ('b', 'c', 'd')])
+ local = sorted(func.keys())
+ self.assertEqual(local, ['a', 'b', 'c', 'd'])
+ self.assertEqual(func.type, 'function')
+
+ def test_format_args(self):
+ func = self.module2['make_class']
+ self.assertEqual(func.args.format_args(),
+ 'any, base=data.module.YO, *args, **kwargs')
+ func = self.module['four_args']
+ self.assertEqual(func.args.format_args(), 'a, b, c, d')
+
+ def test_is_generator(self):
+ self.assertTrue(self.module2['generator'].is_generator())
+ self.assertFalse(self.module2['not_a_generator'].is_generator())
+ self.assertFalse(self.module2['make_class'].is_generator())
+
+ def test_is_abstract(self):
+ method = self.module2['AbstractClass']['to_override']
+ self.assertTrue(method.is_abstract(pass_is_abstract=False))
+ self.assertEqual(method.qname(), 'data.module2.AbstractClass.to_override')
+ self.assertEqual(method.pytype(), '%s.instancemethod' % BUILTINS)
+ method = self.module2['AbstractClass']['return_something']
+ self.assertFalse(method.is_abstract(pass_is_abstract=False))
+ # non regression : test raise "string" doesn't cause an exception in is_abstract
+ func = self.module2['raise_string']
+ self.assertFalse(func.is_abstract(pass_is_abstract=False))
+
+ def test_is_abstract_decorated(self):
+ methods = test_utils.extract_node("""
+ import abc
+
+ class Klass(object):
+ @abc.abstractproperty
+ def prop(self): #@
+ pass
+
+ @abc.abstractmethod
+ def method1(self): #@
+ pass
+
+ some_other_decorator = lambda x: x
+ @some_other_decorator
+ def method2(self): #@
+ pass
+ """)
+ self.assertTrue(methods[0].is_abstract(pass_is_abstract=False))
+ self.assertTrue(methods[1].is_abstract(pass_is_abstract=False))
+ self.assertFalse(methods[2].is_abstract(pass_is_abstract=False))
+
+## def test_raises(self):
+## method = self.module2['AbstractClass']['to_override']
+## self.assertEqual([str(term) for term in method.raises()],
+## ["CallFunc(Name('NotImplementedError'), [], None, None)"] )
+
+## def test_returns(self):
+## method = self.module2['AbstractClass']['return_something']
+## # use string comp since Node doesn't handle __cmp__
+## self.assertEqual([str(term) for term in method.returns()],
+## ["Const('toto')", "Const(None)"])
+
+ def test_lambda_pytype(self):
+ data = '''
+ def f():
+ g = lambda: None
+ '''
+ astroid = test_utils.build_module(data)
+ g = list(astroid['f'].ilookup('g'))[0]
+ self.assertEqual(g.pytype(), '%s.function' % BUILTINS)
+
+ def test_lambda_qname(self):
+ astroid = test_utils.build_module('lmbd = lambda: None', __name__)
+ self.assertEqual('%s.' % __name__, astroid['lmbd'].parent.value.qname())
+
+ def test_is_method(self):
+ data = '''
+ class A:
+ def meth1(self):
+ return 1
+ @classmethod
+ def meth2(cls):
+ return 2
+ @staticmethod
+ def meth3():
+ return 3
+
+ def function():
+ return 0
+
+ @staticmethod
+ def sfunction():
+ return -1
+ '''
+ astroid = test_utils.build_module(data)
+ self.assertTrue(astroid['A']['meth1'].is_method())
+ self.assertTrue(astroid['A']['meth2'].is_method())
+ self.assertTrue(astroid['A']['meth3'].is_method())
+ self.assertFalse(astroid['function'].is_method())
+ self.assertFalse(astroid['sfunction'].is_method())
+
+ def test_argnames(self):
+ if sys.version_info < (3, 0):
+ code = 'def f(a, (b, c), *args, **kwargs): pass'
+ else:
+ code = 'def f(a, b, c, *args, **kwargs): pass'
+ astroid = test_utils.build_module(code, __name__)
+ self.assertEqual(astroid['f'].argnames(), ['a', 'b', 'c', 'args', 'kwargs'])
+
+ def test_return_nothing(self):
+ """test infered value on a function with empty return"""
+ data = '''
+ def func():
+ return
+
+ a = func()
+ '''
+ astroid = test_utils.build_module(data)
+ call = astroid.body[1].value
+ func_vals = call.infered()
+ self.assertEqual(len(func_vals), 1)
+ self.assertIsInstance(func_vals[0], nodes.Const)
+ self.assertIsNone(func_vals[0].value)
+
+ def test_func_instance_attr(self):
+ """test instance attributes for functions"""
+ data = """
+ def test():
+ print(test.bar)
+
+ test.bar = 1
+ test()
+ """
+ astroid = test_utils.build_module(data, 'mod')
+ func = astroid.body[2].value.func.infered()[0]
+ self.assertIsInstance(func, nodes.Function)
+ self.assertEqual(func.name, 'test')
+ one = func.getattr('bar')[0].infered()[0]
+ self.assertIsInstance(one, nodes.Const)
+ self.assertEqual(one.value, 1)
+
+ def test_type_builtin_descriptor_subclasses(self):
+ astroid = test_utils.build_module("""
+ class classonlymethod(classmethod):
+ pass
+ class staticonlymethod(staticmethod):
+ pass
+
+ class Node:
+ @classonlymethod
+ def clsmethod_subclass(cls):
+ pass
+ @classmethod
+ def clsmethod(cls):
+ pass
+ @staticonlymethod
+ def staticmethod_subclass(cls):
+ pass
+ @staticmethod
+ def stcmethod(cls):
+ pass
+ """)
+ node = astroid.locals['Node'][0]
+ self.assertEqual(node.locals['clsmethod_subclass'][0].type,
+ 'classmethod')
+ self.assertEqual(node.locals['clsmethod'][0].type,
+ 'classmethod')
+ self.assertEqual(node.locals['staticmethod_subclass'][0].type,
+ 'staticmethod')
+ self.assertEqual(node.locals['stcmethod'][0].type,
+ 'staticmethod')
+
+ def test_decorator_builtin_descriptors(self):
+ astroid = test_utils.build_module("""
+ def static_decorator(platform=None, order=50):
+ def wrapper(f):
+ f.cgm_module = True
+ f.cgm_module_order = order
+ f.cgm_module_platform = platform
+ return staticmethod(f)
+ return wrapper
+
+ def long_classmethod_decorator(platform=None, order=50):
+ def wrapper(f):
+ def wrapper2(f):
+ def wrapper3(f):
+ f.cgm_module = True
+ f.cgm_module_order = order
+ f.cgm_module_platform = platform
+ return classmethod(f)
+ return wrapper3(f)
+ return wrapper2(f)
+ return wrapper
+
+ def classmethod_decorator(platform=None):
+ def wrapper(f):
+ f.platform = platform
+ return classmethod(f)
+ return wrapper
+
+ def classmethod_wrapper(fn):
+ def wrapper(cls, *args, **kwargs):
+ result = fn(cls, *args, **kwargs)
+ return result
+
+ return classmethod(wrapper)
+
+ def staticmethod_wrapper(fn):
+ def wrapper(*args, **kwargs):
+ return fn(*args, **kwargs)
+ return staticmethod(wrapper)
+
+ class SomeClass(object):
+ @static_decorator()
+ def static(node, cfg):
+ pass
+ @classmethod_decorator()
+ def classmethod(cls):
+ pass
+ @static_decorator
+ def not_so_static(node):
+ pass
+ @classmethod_decorator
+ def not_so_classmethod(node):
+ pass
+ @classmethod_wrapper
+ def classmethod_wrapped(cls):
+ pass
+ @staticmethod_wrapper
+ def staticmethod_wrapped():
+ pass
+ @long_classmethod_decorator()
+ def long_classmethod(cls):
+ pass
+ """)
+ node = astroid.locals['SomeClass'][0]
+ self.assertEqual(node.locals['static'][0].type,
+ 'staticmethod')
+ self.assertEqual(node.locals['classmethod'][0].type,
+ 'classmethod')
+ self.assertEqual(node.locals['not_so_static'][0].type,
+ 'method')
+ self.assertEqual(node.locals['not_so_classmethod'][0].type,
+ 'method')
+ self.assertEqual(node.locals['classmethod_wrapped'][0].type,
+ 'classmethod')
+ self.assertEqual(node.locals['staticmethod_wrapped'][0].type,
+ 'staticmethod')
+ self.assertEqual(node.locals['long_classmethod'][0].type,
+ 'classmethod')
+
+
+class ClassNodeTest(ModuleLoader, unittest.TestCase):
+
+ def test_dict_interface(self):
+ _test_dict_interface(self, self.module['YOUPI'], 'method')
+
+ def test_cls_special_attributes_1(self):
+ cls = self.module['YO']
+ self.assertEqual(len(cls.getattr('__bases__')), 1)
+ self.assertEqual(len(cls.getattr('__name__')), 1)
+ self.assertIsInstance(cls.getattr('__name__')[0], nodes.Const)
+ self.assertEqual(cls.getattr('__name__')[0].value, 'YO')
+ self.assertEqual(len(cls.getattr('__doc__')), 1)
+ self.assertIsInstance(cls.getattr('__doc__')[0], nodes.Const)
+ self.assertEqual(cls.getattr('__doc__')[0].value, 'hehe')
+ self.assertEqual(len(cls.getattr('__module__')), 1)
+ self.assertIsInstance(cls.getattr('__module__')[0], nodes.Const)
+ self.assertEqual(cls.getattr('__module__')[0].value, 'data.module')
+ self.assertEqual(len(cls.getattr('__dict__')), 1)
+ if not cls.newstyle:
+ self.assertRaises(NotFoundError, cls.getattr, '__mro__')
+ for cls in (nodes.List._proxied, nodes.Const(1)._proxied):
+ self.assertEqual(len(cls.getattr('__bases__')), 1)
+ self.assertEqual(len(cls.getattr('__name__')), 1)
+ self.assertEqual(len(cls.getattr('__doc__')), 1, (cls, cls.getattr('__doc__')))
+ self.assertEqual(cls.getattr('__doc__')[0].value, cls.doc)
+ self.assertEqual(len(cls.getattr('__module__')), 1)
+ self.assertEqual(len(cls.getattr('__dict__')), 1)
+ self.assertEqual(len(cls.getattr('__mro__')), 1)
+
+ def test_cls_special_attributes_2(self):
+ astroid = test_utils.build_module('''
+ class A: pass
+ class B: pass
+
+ A.__bases__ += (B,)
+ ''', __name__)
+ self.assertEqual(len(astroid['A'].getattr('__bases__')), 2)
+ self.assertIsInstance(astroid['A'].getattr('__bases__')[0], nodes.Tuple)
+ self.assertIsInstance(astroid['A'].getattr('__bases__')[1], nodes.AssAttr)
+
+ def test_instance_special_attributes(self):
+ for inst in (Instance(self.module['YO']), nodes.List(), nodes.Const(1)):
+ self.assertRaises(NotFoundError, inst.getattr, '__mro__')
+ self.assertRaises(NotFoundError, inst.getattr, '__bases__')
+ self.assertRaises(NotFoundError, inst.getattr, '__name__')
+ self.assertEqual(len(inst.getattr('__dict__')), 1)
+ self.assertEqual(len(inst.getattr('__doc__')), 1)
+
+ def test_navigation(self):
+ klass = self.module['YO']
+ self.assertEqual(klass.statement(), klass)
+ l_sibling = klass.previous_sibling()
+ self.assertTrue(isinstance(l_sibling, nodes.Function), l_sibling)
+ self.assertEqual(l_sibling.name, 'global_access')
+ r_sibling = klass.next_sibling()
+ self.assertIsInstance(r_sibling, nodes.Class)
+ self.assertEqual(r_sibling.name, 'YOUPI')
+
+ def test_local_attr_ancestors(self):
+ klass2 = self.module['YOUPI']
+ it = klass2.local_attr_ancestors('__init__')
+ anc_klass = next(it)
+ self.assertIsInstance(anc_klass, nodes.Class)
+ self.assertEqual(anc_klass.name, 'YO')
+ if sys.version_info[0] == 2:
+ self.assertRaises(StopIteration, partial(next, it))
+ else:
+ anc_klass = next(it)
+ self.assertIsInstance(anc_klass, nodes.Class)
+ self.assertEqual(anc_klass.name, 'object')
+ self.assertRaises(StopIteration, partial(next, it))
+
+ it = klass2.local_attr_ancestors('method')
+ self.assertRaises(StopIteration, partial(next, it))
+
+ def test_instance_attr_ancestors(self):
+ klass2 = self.module['YOUPI']
+ it = klass2.instance_attr_ancestors('yo')
+ anc_klass = next(it)
+ self.assertIsInstance(anc_klass, nodes.Class)
+ self.assertEqual(anc_klass.name, 'YO')
+ self.assertRaises(StopIteration, partial(next, it))
+ klass2 = self.module['YOUPI']
+ it = klass2.instance_attr_ancestors('member')
+ self.assertRaises(StopIteration, partial(next, it))
+
+ def test_methods(self):
+ expected_methods = {'__init__', 'class_method', 'method', 'static_method'}
+ klass2 = self.module['YOUPI']
+ methods = {m.name for m in klass2.methods()}
+ self.assertTrue(
+ methods.issuperset(expected_methods))
+ methods = {m.name for m in klass2.mymethods()}
+ self.assertSetEqual(expected_methods, methods)
+ klass2 = self.module2['Specialization']
+ methods = {m.name for m in klass2.mymethods()}
+ self.assertSetEqual(set([]), methods)
+ method_locals = klass2.local_attr('method')
+ self.assertEqual(len(method_locals), 1)
+ self.assertEqual(method_locals[0].name, 'method')
+ self.assertRaises(NotFoundError, klass2.local_attr, 'nonexistant')
+ methods = {m.name for m in klass2.methods()}
+ self.assertTrue(methods.issuperset(expected_methods))
+
+ #def test_rhs(self):
+ # my_dict = self.module['MY_DICT']
+ # self.assertIsInstance(my_dict.rhs(), nodes.Dict)
+ # a = self.module['YO']['a']
+ # value = a.rhs()
+ # self.assertIsInstance(value, nodes.Const)
+ # self.assertEqual(value.value, 1)
+
+ @unittest.skipIf(sys.version_info[0] >= 3, "Python 2 class semantics required.")
+ def test_ancestors(self):
+ klass = self.module['YOUPI']
+ self.assertEqual(['YO'], [a.name for a in klass.ancestors()])
+ klass = self.module2['Specialization']
+ self.assertEqual(['YOUPI', 'YO'], [a.name for a in klass.ancestors()])
+
+ @unittest.skipIf(sys.version_info[0] < 3, "Python 3 class semantics required.")
+ def test_ancestors_py3(self):
+ klass = self.module['YOUPI']
+ self.assertEqual(['YO', 'object'], [a.name for a in klass.ancestors()])
+ klass = self.module2['Specialization']
+ self.assertEqual(['YOUPI', 'YO', 'object'], [a.name for a in klass.ancestors()])
+
+ def test_type(self):
+ klass = self.module['YOUPI']
+ self.assertEqual(klass.type, 'class')
+ klass = self.module2['Metaclass']
+ self.assertEqual(klass.type, 'metaclass')
+ klass = self.module2['MyException']
+ self.assertEqual(klass.type, 'exception')
+ klass = self.module2['MyIFace']
+ self.assertEqual(klass.type, 'interface')
+ klass = self.module2['MyError']
+ self.assertEqual(klass.type, 'exception')
+ # the following class used to be detected as a metaclass
+ # after the fix which used instance._proxied in .ancestors(),
+ # when in fact it is a normal class
+ klass = self.module2['NotMetaclass']
+ self.assertEqual(klass.type, 'class')
+
+ def test_interfaces(self):
+ for klass, interfaces in (('Concrete0', ['MyIFace']),
+ ('Concrete1', ['MyIFace', 'AnotherIFace']),
+ ('Concrete2', ['MyIFace', 'AnotherIFace']),
+ ('Concrete23', ['MyIFace', 'AnotherIFace'])):
+ klass = self.module2[klass]
+ self.assertEqual([i.name for i in klass.interfaces()],
+ interfaces)
+
+ def test_concat_interfaces(self):
+ astroid = test_utils.build_module('''
+ class IMachin: pass
+
+ class Correct2:
+ """docstring"""
+ __implements__ = (IMachin,)
+
+ class BadArgument:
+ """docstring"""
+ __implements__ = (IMachin,)
+
+ class InterfaceCanNowBeFound:
+ """docstring"""
+ __implements__ = BadArgument.__implements__ + Correct2.__implements__
+ ''')
+ self.assertEqual([i.name for i in astroid['InterfaceCanNowBeFound'].interfaces()],
+ ['IMachin'])
+
+ def test_inner_classes(self):
+ eee = self.nonregr['Ccc']['Eee']
+ self.assertEqual([n.name for n in eee.ancestors()], ['Ddd', 'Aaa', 'object'])
+
+
+ def test_classmethod_attributes(self):
+ data = '''
+ class WebAppObject(object):
+ def registered(cls, application):
+ cls.appli = application
+ cls.schema = application.schema
+ cls.config = application.config
+ return cls
+ registered = classmethod(registered)
+ '''
+ astroid = test_utils.build_module(data, __name__)
+ cls = astroid['WebAppObject']
+ self.assertEqual(sorted(cls.locals.keys()),
+ ['appli', 'config', 'registered', 'schema'])
+
+
+ def test_class_getattr(self):
+ data = '''
+ class WebAppObject(object):
+ appli = application
+ appli += 2
+ del self.appli
+ '''
+ astroid = test_utils.build_module(data, __name__)
+ cls = astroid['WebAppObject']
+ # test del statement not returned by getattr
+ self.assertEqual(len(cls.getattr('appli')), 2)
+
+
+ def test_instance_getattr(self):
+ data = '''
+ class WebAppObject(object):
+ def __init__(self, application):
+ self.appli = application
+ self.appli += 2
+ del self.appli
+ '''
+ astroid = test_utils.build_module(data)
+ inst = Instance(astroid['WebAppObject'])
+ # test del statement not returned by getattr
+ self.assertEqual(len(inst.getattr('appli')), 2)
+
+
+ def test_instance_getattr_with_class_attr(self):
+ data = '''
+ class Parent:
+ aa = 1
+ cc = 1
+
+ class Klass(Parent):
+ aa = 0
+ bb = 0
+
+ def incr(self, val):
+ self.cc = self.aa
+ if val > self.aa:
+ val = self.aa
+ if val < self.bb:
+ val = self.bb
+ self.aa += val
+ '''
+ astroid = test_utils.build_module(data)
+ inst = Instance(astroid['Klass'])
+ self.assertEqual(len(inst.getattr('aa')), 3, inst.getattr('aa'))
+ self.assertEqual(len(inst.getattr('bb')), 1, inst.getattr('bb'))
+ self.assertEqual(len(inst.getattr('cc')), 2, inst.getattr('cc'))
+
+
+ def test_getattr_method_transform(self):
+ data = '''
+ class Clazz(object):
+
+ def m1(self, value):
+ self.value = value
+ m2 = m1
+
+ def func(arg1, arg2):
+ "function that will be used as a method"
+ return arg1.value + arg2
+
+ Clazz.m3 = func
+ inst = Clazz()
+ inst.m4 = func
+ '''
+ astroid = test_utils.build_module(data)
+ cls = astroid['Clazz']
+ # test del statement not returned by getattr
+ for method in ('m1', 'm2', 'm3'):
+ inferred = list(cls.igetattr(method))
+ self.assertEqual(len(inferred), 1)
+ self.assertIsInstance(inferred[0], UnboundMethod)
+ inferred = list(Instance(cls).igetattr(method))
+ self.assertEqual(len(inferred), 1)
+ self.assertIsInstance(inferred[0], BoundMethod)
+ inferred = list(Instance(cls).igetattr('m4'))
+ self.assertEqual(len(inferred), 1)
+ self.assertIsInstance(inferred[0], nodes.Function)
+
+ def test_getattr_from_grandpa(self):
+ data = '''
+ class Future:
+ attr = 1
+
+ class Present(Future):
+ pass
+
+ class Past(Present):
+ pass
+ '''
+ astroid = test_utils.build_module(data)
+ past = astroid['Past']
+ attr = past.getattr('attr')
+ self.assertEqual(len(attr), 1)
+ attr1 = attr[0]
+ self.assertIsInstance(attr1, nodes.AssName)
+ self.assertEqual(attr1.name, 'attr')
+
+ def test_function_with_decorator_lineno(self):
+ data = '''
+ @f(a=2,
+ b=3)
+ def g1(x):
+ print(x)
+
+ @f(a=2,
+ b=3)
+ def g2():
+ pass
+ '''
+ astroid = test_utils.build_module(data)
+ self.assertEqual(astroid['g1'].fromlineno, 4)
+ self.assertEqual(astroid['g1'].tolineno, 5)
+ self.assertEqual(astroid['g2'].fromlineno, 9)
+ self.assertEqual(astroid['g2'].tolineno, 10)
+
+ @test_utils.require_version(maxver='3.0')
+ def test_simple_metaclass(self):
+ astroid = test_utils.build_module("""
+ class Test(object):
+ __metaclass__ = type
+ """)
+ klass = astroid['Test']
+ metaclass = klass.metaclass()
+ self.assertIsInstance(metaclass, scoped_nodes.Class)
+ self.assertEqual(metaclass.name, 'type')
+
+ def test_metaclass_error(self):
+ astroid = test_utils.build_module("""
+ class Test(object):
+ __metaclass__ = typ
+ """)
+ klass = astroid['Test']
+ self.assertFalse(klass.metaclass())
+
+ @test_utils.require_version(maxver='3.0')
+ def test_metaclass_imported(self):
+ astroid = test_utils.build_module("""
+ from abc import ABCMeta
+ class Test(object):
+ __metaclass__ = ABCMeta
+ """)
+ klass = astroid['Test']
+
+ metaclass = klass.metaclass()
+ self.assertIsInstance(metaclass, scoped_nodes.Class)
+ self.assertEqual(metaclass.name, 'ABCMeta')
+
+ def test_metaclass_yes_leak(self):
+ astroid = test_utils.build_module("""
+ # notice `ab` instead of `abc`
+ from ab import ABCMeta
+
+ class Meta(object):
+ __metaclass__ = ABCMeta
+ """)
+ klass = astroid['Meta']
+ self.assertIsNone(klass.metaclass())
+
+ @test_utils.require_version(maxver='3.0')
+ def test_newstyle_and_metaclass_good(self):
+ astroid = test_utils.build_module("""
+ from abc import ABCMeta
+ class Test:
+ __metaclass__ = ABCMeta
+ """)
+ klass = astroid['Test']
+ self.assertTrue(klass.newstyle)
+ self.assertEqual(klass.metaclass().name, 'ABCMeta')
+ astroid = test_utils.build_module("""
+ from abc import ABCMeta
+ __metaclass__ = ABCMeta
+ class Test:
+ pass
+ """)
+ klass = astroid['Test']
+ self.assertTrue(klass.newstyle)
+ self.assertEqual(klass.metaclass().name, 'ABCMeta')
+
+ @test_utils.require_version(maxver='3.0')
+ def test_nested_metaclass(self):
+ astroid = test_utils.build_module("""
+ from abc import ABCMeta
+ class A(object):
+ __metaclass__ = ABCMeta
+ class B: pass
+
+ __metaclass__ = ABCMeta
+ class C:
+ __metaclass__ = type
+ class D: pass
+ """)
+ a = astroid['A']
+ b = a.locals['B'][0]
+ c = astroid['C']
+ d = c.locals['D'][0]
+ self.assertEqual(a.metaclass().name, 'ABCMeta')
+ self.assertFalse(b.newstyle)
+ self.assertIsNone(b.metaclass())
+ self.assertEqual(c.metaclass().name, 'type')
+ self.assertEqual(d.metaclass().name, 'ABCMeta')
+
+ @test_utils.require_version(maxver='3.0')
+ def test_parent_metaclass(self):
+ astroid = test_utils.build_module("""
+ from abc import ABCMeta
+ class Test:
+ __metaclass__ = ABCMeta
+ class SubTest(Test): pass
+ """)
+ klass = astroid['SubTest']
+ self.assertTrue(klass.newstyle)
+ metaclass = klass.metaclass()
+ self.assertIsInstance(metaclass, scoped_nodes.Class)
+ self.assertEqual(metaclass.name, 'ABCMeta')
+
+ @test_utils.require_version(maxver='3.0')
+ def test_metaclass_ancestors(self):
+ astroid = test_utils.build_module("""
+ from abc import ABCMeta
+
+ class FirstMeta(object):
+ __metaclass__ = ABCMeta
+
+ class SecondMeta(object):
+ __metaclass__ = type
+
+ class Simple(object):
+ pass
+
+ class FirstImpl(FirstMeta): pass
+ class SecondImpl(FirstImpl): pass
+ class ThirdImpl(Simple, SecondMeta):
+ pass
+ """)
+ classes = {
+ 'ABCMeta': ('FirstImpl', 'SecondImpl'),
+ 'type': ('ThirdImpl', )
+ }
+ for metaclass, names in classes.items():
+ for name in names:
+ impl = astroid[name]
+ meta = impl.metaclass()
+ self.assertIsInstance(meta, nodes.Class)
+ self.assertEqual(meta.name, metaclass)
+
+ def test_metaclass_type(self):
+ klass = test_utils.extract_node("""
+ def with_metaclass(meta, base=object):
+ return meta("NewBase", (base, ), {})
+
+ class ClassWithMeta(with_metaclass(type)): #@
+ pass
+ """)
+ self.assertEqual(
+ ['NewBase', 'object'],
+ [base.name for base in klass.ancestors()])
+
+ def test_metaclass_generator_hack(self):
+ klass = test_utils.extract_node("""
+ import six
+
+ class WithMeta(six.with_metaclass(type, object)): #@
+ pass
+ """)
+ self.assertEqual(
+ ['object'],
+ [base.name for base in klass.ancestors()])
+ self.assertEqual(
+ 'type', klass.metaclass().name)
+
+ def test_nonregr_infer_callresult(self):
+ astroid = test_utils.build_module("""
+ class Delegate(object):
+ def __get__(self, obj, cls):
+ return getattr(obj._subject, self.attribute)
+
+ class CompositeBuilder(object):
+ __call__ = Delegate()
+
+ builder = CompositeBuilder(result, composite)
+ tgts = builder()
+ """)
+ instance = astroid['tgts']
+ # used to raise "'_Yes' object is not iterable", see
+ # https://bitbucket.org/logilab/astroid/issue/17
+ self.assertEqual(list(instance.infer()), [YES])
+
+ def test_slots(self):
+ astroid = test_utils.build_module("""
+ from collections import deque
+ from textwrap import dedent
+
+ class First(object):
+ __slots__ = ("a", "b", 1)
+ class Second(object):
+ __slots__ = "a"
+ class Third(object):
+ __slots__ = deque(["a", "b", "c"])
+ class Fourth(object):
+ __slots__ = {"a": "a", "b": "b"}
+ class Fifth(object):
+ __slots__ = list
+ class Sixth(object):
+ __slots__ = ""
+ class Seventh(object):
+ __slots__ = dedent.__name__
+ class Eight(object):
+ __slots__ = ("parens")
+ class Ninth(object):
+ pass
+ class Ten(object):
+ __slots__ = dict({"a": "b", "c": "d"})
+ """)
+ first = astroid['First']
+ first_slots = first.slots()
+ self.assertEqual(len(first_slots), 2)
+ self.assertIsInstance(first_slots[0], nodes.Const)
+ self.assertIsInstance(first_slots[1], nodes.Const)
+ self.assertEqual(first_slots[0].value, "a")
+ self.assertEqual(first_slots[1].value, "b")
+
+ second_slots = astroid['Second'].slots()
+ self.assertEqual(len(second_slots), 1)
+ self.assertIsInstance(second_slots[0], nodes.Const)
+ self.assertEqual(second_slots[0].value, "a")
+
+ third_slots = astroid['Third'].slots()
+ self.assertIsNone(third_slots)
+
+ fourth_slots = astroid['Fourth'].slots()
+ self.assertEqual(len(fourth_slots), 2)
+ self.assertIsInstance(fourth_slots[0], nodes.Const)
+ self.assertIsInstance(fourth_slots[1], nodes.Const)
+ self.assertEqual(fourth_slots[0].value, "a")
+ self.assertEqual(fourth_slots[1].value, "b")
+
+ fifth_slots = astroid['Fifth'].slots()
+ self.assertIsNone(fifth_slots)
+
+ sixth_slots = astroid['Sixth'].slots()
+ self.assertIsNone(sixth_slots)
+
+ seventh_slots = astroid['Seventh'].slots()
+ self.assertIsNone(seventh_slots)
+
+ eight_slots = astroid['Eight'].slots()
+ self.assertEqual(len(eight_slots), 1)
+ self.assertIsInstance(eight_slots[0], nodes.Const)
+ self.assertEqual(eight_slots[0].value, "parens")
+
+ self.assertIsNone(astroid['Ninth'].slots())
+
+ tenth_slots = astroid['Ten'].slots()
+ self.assertEqual(len(tenth_slots), 2)
+ self.assertEqual(
+ [slot.value for slot in tenth_slots],
+ ["a", "c"])
+
+ @test_utils.require_version(maxver='3.0')
+ def test_slots_py2(self):
+ module = test_utils.build_module("""
+ class UnicodeSlots(object):
+ __slots__ = (u"a", u"b", "c")
+ """)
+ slots = module['UnicodeSlots'].slots()
+ self.assertEqual(len(slots), 3)
+ self.assertEqual(slots[0].value, "a")
+ self.assertEqual(slots[1].value, "b")
+ self.assertEqual(slots[2].value, "c")
+
+ @test_utils.require_version(maxver='3.0')
+ def test_slots_py2_not_implemented(self):
+ module = test_utils.build_module("""
+ class OldStyle:
+ __slots__ = ("a", "b")
+ """)
+ msg = "The concept of slots is undefined for old-style classes."
+ with self.assertRaises(NotImplementedError) as cm:
+ module['OldStyle'].slots()
+ self.assertEqual(str(cm.exception), msg)
+
+ def assertEqualMro(self, klass, expected_mro):
+ self.assertEqual(
+ [member.name for member in klass.mro()],
+ expected_mro)
+
+ @test_utils.require_version(maxver='3.0')
+ def test_no_mro_for_old_style(self):
+ node = test_utils.extract_node("""
+ class Old: pass""")
+ with self.assertRaises(NotImplementedError) as cm:
+ node.mro()
+ self.assertEqual(str(cm.exception), "Could not obtain mro for "
+ "old-style classes.")
+
+ def test_mro(self):
+ astroid = test_utils.build_module("""
+ class C(object): pass
+ class D(dict, C): pass
+
+ class A1(object): pass
+ class B1(A1): pass
+ class C1(A1): pass
+ class D1(B1, C1): pass
+ class E1(C1, B1): pass
+ class F1(D1, E1): pass
+ class G1(E1, D1): pass
+
+ class Boat(object): pass
+ class DayBoat(Boat): pass
+ class WheelBoat(Boat): pass
+ class EngineLess(DayBoat): pass
+ class SmallMultihull(DayBoat): pass
+ class PedalWheelBoat(EngineLess, WheelBoat): pass
+ class SmallCatamaran(SmallMultihull): pass
+ class Pedalo(PedalWheelBoat, SmallCatamaran): pass
+
+ class OuterA(object):
+ class Inner(object):
+ pass
+ class OuterB(OuterA):
+ class Inner(OuterA.Inner):
+ pass
+ class OuterC(OuterA):
+ class Inner(OuterA.Inner):
+ pass
+ class OuterD(OuterC):
+ class Inner(OuterC.Inner, OuterB.Inner):
+ pass
+
+ """)
+ self.assertEqualMro(astroid['D'], ['D', 'dict', 'C', 'object'])
+ self.assertEqualMro(astroid['D1'], ['D1', 'B1', 'C1', 'A1', 'object'])
+ self.assertEqualMro(astroid['E1'], ['E1', 'C1', 'B1', 'A1', 'object'])
+ with self.assertRaises(ResolveError) as cm:
+ astroid['F1'].mro()
+ self.assertEqual(str(cm.exception),
+ "Cannot create a consistent method resolution order "
+ "for bases (B1, C1, A1, object), "
+ "(C1, B1, A1, object)")
+
+ with self.assertRaises(ResolveError) as cm:
+ astroid['G1'].mro()
+ self.assertEqual(str(cm.exception),
+ "Cannot create a consistent method resolution order "
+ "for bases (C1, B1, A1, object), "
+ "(B1, C1, A1, object)")
+
+ self.assertEqualMro(
+ astroid['PedalWheelBoat'],
+ ["PedalWheelBoat", "EngineLess",
+ "DayBoat", "WheelBoat", "Boat", "object"])
+
+ self.assertEqualMro(
+ astroid["SmallCatamaran"],
+ ["SmallCatamaran", "SmallMultihull", "DayBoat", "Boat", "object"])
+
+ self.assertEqualMro(
+ astroid["Pedalo"],
+ ["Pedalo", "PedalWheelBoat", "EngineLess", "SmallCatamaran",
+ "SmallMultihull", "DayBoat", "WheelBoat", "Boat", "object"])
+
+ self.assertEqualMro(
+ astroid['OuterD']['Inner'],
+ ['Inner', 'Inner', 'Inner', 'Inner', 'object'])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff -Nru astroid-1.0.1/astroid/tests/unittest_utils.py astroid-1.3.8/astroid/tests/unittest_utils.py
--- astroid-1.0.1/astroid/tests/unittest_utils.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/tests/unittest_utils.py 2015-03-09 22:00:27.000000000 +0000
@@ -0,0 +1,102 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+import unittest
+
+from astroid import builder, nodes
+from astroid.node_classes import are_exclusive
+
+builder = builder.AstroidBuilder()
+
+class AreExclusiveTC(unittest.TestCase):
+ def test_not_exclusive(self):
+ astroid = builder.string_build("""
+x = 10
+for x in range(5):
+ print (x)
+
+if x > 0:
+ print ('#' * x)
+ """, __name__, __file__)
+ xass1 = astroid.locals['x'][0]
+ assert xass1.lineno == 2
+ xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'x']
+ assert len(xnames) == 3
+ assert xnames[1].lineno == 6
+ self.assertEqual(are_exclusive(xass1, xnames[1]), False)
+ self.assertEqual(are_exclusive(xass1, xnames[2]), False)
+
+ def test_if(self):
+ astroid = builder.string_build('''
+
+if 1:
+ a = 1
+ a = 2
+elif 2:
+ a = 12
+ a = 13
+else:
+ a = 3
+ a = 4
+ ''')
+ a1 = astroid.locals['a'][0]
+ a2 = astroid.locals['a'][1]
+ a3 = astroid.locals['a'][2]
+ a4 = astroid.locals['a'][3]
+ a5 = astroid.locals['a'][4]
+ a6 = astroid.locals['a'][5]
+ self.assertEqual(are_exclusive(a1, a2), False)
+ self.assertEqual(are_exclusive(a1, a3), True)
+ self.assertEqual(are_exclusive(a1, a5), True)
+ self.assertEqual(are_exclusive(a3, a5), True)
+ self.assertEqual(are_exclusive(a3, a4), False)
+ self.assertEqual(are_exclusive(a5, a6), False)
+
+ def test_try_except(self):
+ astroid = 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 = astroid.locals['exclusive_func2'][0]
+ f2 = astroid.locals['exclusive_func2'][1]
+ f3 = astroid.locals['exclusive_func2'][2]
+ f4 = astroid.locals['exclusive_func2'][3]
+ self.assertEqual(are_exclusive(f1, f2), True)
+ self.assertEqual(are_exclusive(f1, f3), True)
+ self.assertEqual(are_exclusive(f1, f4), False)
+ self.assertEqual(are_exclusive(f2, f4), True)
+ self.assertEqual(are_exclusive(f3, f4), True)
+ self.assertEqual(are_exclusive(f3, f2), True)
+
+ self.assertEqual(are_exclusive(f2, f1), True)
+ self.assertEqual(are_exclusive(f4, f1), False)
+ self.assertEqual(are_exclusive(f4, f2), True)
+
+if __name__ == '__main__':
+ unittest.main()
+
diff -Nru astroid-1.0.1/astroid/test_utils.py astroid-1.3.8/astroid/test_utils.py
--- astroid-1.0.1/astroid/test_utils.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/test_utils.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,218 @@
+"""Utility functions for test code that uses astroid ASTs as input."""
+import functools
+import sys
+import textwrap
+
+from astroid import nodes
+from astroid import builder
+# The name of the transient function that is used to
+# wrap expressions to be extracted when calling
+# extract_node.
+_TRANSIENT_FUNCTION = '__'
+
+# The comment used to select a statement to be extracted
+# when calling extract_node.
+_STATEMENT_SELECTOR = '#@'
+
+
+def _extract_expressions(node):
+ """Find expressions in a call to _TRANSIENT_FUNCTION and extract them.
+
+ The function walks the AST recursively to search for expressions that
+ are wrapped into a call to _TRANSIENT_FUNCTION. If it finds such an
+ expression, it completely removes the function call node from the tree,
+ replacing it by the wrapped expression inside the parent.
+
+ :param node: An astroid node.
+ :type node: astroid.bases.NodeNG
+ :yields: The sequence of wrapped expressions on the modified tree
+ expression can be found.
+ """
+ if (isinstance(node, nodes.CallFunc)
+ and isinstance(node.func, nodes.Name)
+ and node.func.name == _TRANSIENT_FUNCTION):
+ real_expr = node.args[0]
+ real_expr.parent = node.parent
+ # Search for node in all _astng_fields (the fields checked when
+ # get_children is called) of its parent. Some of those fields may
+ # be lists or tuples, in which case the elements need to be checked.
+ # When we find it, replace it by real_expr, so that the AST looks
+ # like no call to _TRANSIENT_FUNCTION ever took place.
+ for name in node.parent._astroid_fields:
+ child = getattr(node.parent, name)
+ if isinstance(child, (list, tuple)):
+ for idx, compound_child in enumerate(child):
+ if compound_child is node:
+ child[idx] = real_expr
+ elif child is node:
+ setattr(node.parent, name, real_expr)
+ yield real_expr
+ else:
+ for child in node.get_children():
+ for result in _extract_expressions(child):
+ yield result
+
+
+def _find_statement_by_line(node, line):
+ """Extracts the statement on a specific line from an AST.
+
+ If the line number of node matches line, it will be returned;
+ otherwise its children are iterated and the function is called
+ recursively.
+
+ :param node: An astroid node.
+ :type node: astroid.bases.NodeNG
+ :param line: The line number of the statement to extract.
+ :type line: int
+ :returns: The statement on the line, or None if no statement for the line
+ can be found.
+ :rtype: astroid.bases.NodeNG or None
+ """
+ if isinstance(node, (nodes.Class, nodes.Function)):
+ # This is an inaccuracy in the AST: the nodes that can be
+ # decorated do not carry explicit information on which line
+ # the actual definition (class/def), but .fromline seems to
+ # be close enough.
+ node_line = node.fromlineno
+ else:
+ node_line = node.lineno
+
+ if node_line == line:
+ return node
+
+ for child in node.get_children():
+ result = _find_statement_by_line(child, line)
+ if result:
+ return result
+
+ return None
+
+def extract_node(code, module_name=''):
+ """Parses some Python code as a module and extracts a designated AST node.
+
+ Statements:
+ To extract one or more statement nodes, append #@ to the end of the line
+
+ Examples:
+ >>> def x():
+ >>> def y():
+ >>> return 1 #@
+
+ The return statement will be extracted.
+
+ >>> class X(object):
+ >>> def meth(self): #@
+ >>> pass
+
+ The funcion object 'meth' will be extracted.
+
+ Expressions:
+ To extract arbitrary expressions, surround them with the fake
+ function call __(...). After parsing, the surrounded expression
+ will be returned and the whole AST (accessible via the returned
+ node's parent attribute) will look like the function call was
+ never there in the first place.
+
+ Examples:
+ >>> a = __(1)
+
+ The const node will be extracted.
+
+ >>> def x(d=__(foo.bar)): pass
+
+ The node containing the default argument will be extracted.
+
+ >>> def foo(a, b):
+ >>> return 0 < __(len(a)) < b
+
+ The node containing the function call 'len' will be extracted.
+
+ If no statements or expressions are selected, the last toplevel
+ statement will be returned.
+
+ If the selected statement is a discard statement, (i.e. an expression
+ turned into a statement), the wrapped expression is returned instead.
+
+ For convenience, singleton lists are unpacked.
+
+ :param str code: A piece of Python code that is parsed as
+ a module. Will be passed through textwrap.dedent first.
+ :param str module_name: The name of the module.
+ :returns: The designated node from the parse tree, or a list of nodes.
+ :rtype: astroid.bases.NodeNG, or a list of nodes.
+ """
+ def _extract(node):
+ if isinstance(node, nodes.Discard):
+ return node.value
+ else:
+ return node
+
+ requested_lines = []
+ for idx, line in enumerate(code.splitlines()):
+ if line.strip().endswith(_STATEMENT_SELECTOR):
+ requested_lines.append(idx + 1)
+
+ tree = build_module(code, module_name=module_name)
+ extracted = []
+ if requested_lines:
+ for line in requested_lines:
+ extracted.append(_find_statement_by_line(tree, line))
+
+ # Modifies the tree.
+ extracted.extend(_extract_expressions(tree))
+
+ if not extracted:
+ extracted.append(tree.body[-1])
+
+ extracted = [_extract(node) for node in extracted]
+ if len(extracted) == 1:
+ return extracted[0]
+ else:
+ return extracted
+
+
+def build_module(code, module_name='', path=None):
+ """Parses a string module with a builder.
+ :param code: The code for the module.
+ :type code: str
+ :param module_name: The name for the module
+ :type module_name: str
+ :param path: The path for the module
+ :type module_name: str
+ :returns: The module AST.
+ :rtype: astroid.bases.NodeNG
+ """
+ code = textwrap.dedent(code)
+ return builder.AstroidBuilder(None).string_build(code, modname=module_name, path=path)
+
+
+def require_version(minver=None, maxver=None):
+ """ Compare version of python interpreter to the given one. Skip the test
+ if older.
+ """
+ def parse(string, default=None):
+ string = string or default
+ try:
+ return tuple(int(v) for v in string.split('.'))
+ except ValueError:
+ raise ValueError('%s is not a correct version : should be X.Y[.Z].' % version)
+
+ def check_require_version(f):
+ current = sys.version_info[:3]
+ if parse(minver, "0") < current <= parse(maxver, "4"):
+ return f
+ else:
+ str_version = '.'.join(str(v) for v in sys.version_info)
+ @functools.wraps(f)
+ def new_f(self, *args, **kwargs):
+ if minver is not None:
+ self.skipTest('Needs Python > %s. Current version is %s.' % (minver, str_version))
+ elif maxver is not None:
+ self.skipTest('Needs Python <= %s. Current version is %s.' % (maxver, str_version))
+ return new_f
+
+
+ return check_require_version
+
+def get_name_node(start_from, name, index=0):
+ return [n for n in start_from.nodes_of_class(nodes.Name) if n.name == name][index]
diff -Nru astroid-1.0.1/astroid/utils.py astroid-1.3.8/astroid/utils.py
--- astroid-1.0.1/astroid/utils.py 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/astroid/utils.py 2015-08-02 18:37:18.000000000 +0000
@@ -0,0 +1,239 @@
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with astroid. If not, see .
+"""this module contains some utilities to navigate in the tree or to
+extract information from it
+"""
+from __future__ import print_function
+
+__docformat__ = "restructuredtext en"
+
+from astroid.exceptions import AstroidBuildingException
+from astroid.builder import parse
+
+
+class ASTWalker(object):
+ """a walker visiting a tree in preorder, calling on the handler:
+
+ * visit_ on entering a node, where class name is the class of
+ the node in lower case
+
+ * leave_ on leaving a node, where class name is the class of
+ the node in lower case
+ """
+
+ def __init__(self, handler):
+ self.handler = handler
+ self._cache = {}
+
+ def walk(self, node, _done=None):
+ """walk on the tree from , getting callbacks from handler"""
+ if _done is None:
+ _done = set()
+ if node in _done:
+ raise AssertionError((id(node), node, node.parent))
+ _done.add(node)
+ self.visit(node)
+ for child_node in node.get_children():
+ self.handler.set_context(node, child_node)
+ assert child_node is not node
+ self.walk(child_node, _done)
+ self.leave(node)
+ assert node.parent is not node
+
+ def get_callbacks(self, node):
+ """get callbacks from handler for the visited node"""
+ klass = node.__class__
+ methods = self._cache.get(klass)
+ if methods is None:
+ handler = self.handler
+ kid = klass.__name__.lower()
+ e_method = getattr(handler, 'visit_%s' % kid,
+ getattr(handler, 'visit_default', None))
+ l_method = getattr(handler, 'leave_%s' % kid,
+ getattr(handler, 'leave_default', None))
+ self._cache[klass] = (e_method, l_method)
+ else:
+ e_method, l_method = methods
+ return e_method, l_method
+
+ def visit(self, node):
+ """walk on the tree from , getting callbacks from handler"""
+ method = self.get_callbacks(node)[0]
+ if method is not None:
+ method(node)
+
+ def leave(self, node):
+ """walk on the tree from , getting callbacks from handler"""
+ method = self.get_callbacks(node)[1]
+ if method is not None:
+ method(node)
+
+
+class LocalsVisitor(ASTWalker):
+ """visit a project by traversing the locals dictionary"""
+ def __init__(self):
+ ASTWalker.__init__(self, self)
+ self._visited = {}
+
+ def visit(self, node):
+ """launch the visit starting from the given node"""
+ if node in self._visited:
+ return
+ self._visited[node] = 1 # FIXME: use set ?
+ methods = self.get_callbacks(node)
+ if methods[0] is not None:
+ methods[0](node)
+ if 'locals' in node.__dict__: # skip Instance and other proxy
+ for local_node in node.values():
+ self.visit(local_node)
+ if methods[1] is not None:
+ return methods[1](node)
+
+
+def _check_children(node):
+ """a helper function to check children - parent relations"""
+ for child in node.get_children():
+ ok = False
+ if child is None:
+ print("Hm, child of %s is None" % node)
+ continue
+ if not hasattr(child, 'parent'):
+ print(" ERROR: %s has child %s %x with no parent" % (
+ node, child, id(child)))
+ elif not child.parent:
+ print(" ERROR: %s has child %s %x with parent %r" % (
+ node, child, id(child), child.parent))
+ elif child.parent is not node:
+ print(" ERROR: %s %x has child %s %x with wrong parent %s" % (
+ node, id(node), child, id(child), child.parent))
+ else:
+ ok = True
+ if not ok:
+ print("lines;", node.lineno, child.lineno)
+ print("of module", node.root(), node.root().name)
+ raise AstroidBuildingException
+ _check_children(child)
+
+
+class TreeTester(object):
+ '''A helper class to see _ast tree and compare with astroid tree
+
+ indent: string for tree indent representation
+ lineno: bool to tell if we should print the line numbers
+
+ >>> tester = TreeTester('print')
+ >>> print tester.native_tree_repr()
+
+
+ . body = [
+ .
+ . . nl = True
+ . ]
+ >>> print tester.astroid_tree_repr()
+ Module()
+ body = [
+ Print()
+ dest =
+ values = [
+ ]
+ ]
+ '''
+
+ indent = '. '
+ lineno = False
+
+ def __init__(self, sourcecode):
+ self._string = ''
+ self.sourcecode = sourcecode
+ self._ast_node = None
+ self.build_ast()
+
+ def build_ast(self):
+ """build the _ast tree from the source code"""
+ self._ast_node = parse(self.sourcecode)
+
+ def native_tree_repr(self, node=None, indent=''):
+ """get a nice representation of the _ast tree"""
+ self._string = ''
+ if node is None:
+ node = self._ast_node
+ self._native_repr_tree(node, indent)
+ return self._string
+
+
+ def _native_repr_tree(self, node, indent, _done=None):
+ """recursive method for the native tree representation"""
+ from _ast import Load as _Load, Store as _Store, Del as _Del
+ from _ast import AST as Node
+ if _done is None:
+ _done = set()
+ if node in _done:
+ self._string += '\nloop in tree: %r (%s)' % (
+ node, getattr(node, 'lineno', None))
+ return
+ _done.add(node)
+ self._string += '\n' + indent + '<%s>' % node.__class__.__name__
+ indent += self.indent
+ if not hasattr(node, '__dict__'):
+ self._string += '\n' + self.indent + " ** node has no __dict__ " + str(node)
+ return
+ node_dict = node.__dict__
+ if hasattr(node, '_attributes'):
+ for a in node._attributes:
+ attr = node_dict[a]
+ if attr is None:
+ continue
+ if a in ("lineno", "col_offset") and not self.lineno:
+ continue
+ self._string += '\n' + indent + a + " = " + repr(attr)
+ for field in node._fields or ():
+ attr = node_dict[field]
+ if attr is None:
+ continue
+ if isinstance(attr, list):
+ if not attr:
+ continue
+ self._string += '\n' + indent + field + ' = ['
+ for elt in attr:
+ self._native_repr_tree(elt, indent, _done)
+ self._string += '\n' + indent + ']'
+ continue
+ if isinstance(attr, (_Load, _Store, _Del)):
+ continue
+ if isinstance(attr, Node):
+ self._string += '\n' + indent + field + " = "
+ self._native_repr_tree(attr, indent, _done)
+ else:
+ self._string += '\n' + indent + field + " = " + repr(attr)
+
+
+ def build_astroid_tree(self):
+ """build astroid tree from the _ast tree
+ """
+ from astroid.builder import AstroidBuilder
+ tree = AstroidBuilder().string_build(self.sourcecode)
+ return tree
+
+ def astroid_tree_repr(self, ids=False):
+ """build the astroid tree and return a nice tree representation"""
+ mod = self.build_astroid_tree()
+ return mod.repr_tree(ids)
+
+
+__all__ = ('LocalsVisitor', 'ASTWalker',)
+
diff -Nru astroid-1.0.1/astroid.egg-info/PKG-INFO astroid-1.3.8/astroid.egg-info/PKG-INFO
--- astroid-1.0.1/astroid.egg-info/PKG-INFO 2013-10-18 15:34:18.000000000 +0000
+++ astroid-1.3.8/astroid.egg-info/PKG-INFO 2015-08-02 20:40:00.000000000 +0000
@@ -1,71 +1,80 @@
-Metadata-Version: 1.1
-Name: astroid
-Version: 1.0.1
-Summary: rebuild a new abstract syntax tree from Python's ast
-Home-page: http://bitbucket.org/logilab/astroid
-Author: Logilab
-Author-email: python-projects@lists.logilab.org
-License: LGPL
-Description: Astroid
- =======
-
- What's this?
- ------------
-
- The aim of this module is to provide a common base representation of
- python source code for projects such as pychecker, pyreverse,
- pylint... Well, actually the development of this library is essentially
- governed by pylint's needs. It used to be called logilab-astng.
-
- It provides a compatible representation which comes from the `_ast`
- module. It rebuilds the tree generated by the builtin _ast module by
- recursively walking down the AST and building an extended ast. The new
- node classes have additional methods and attributes for different
- usages. They include some support for static inference and local name
- scopes. Furthermore, astroid builds partial trees by inspecting living
- objects.
-
- Main modules are:
-
- * `bases`, `node_classses` and `scoped_nodes` contain the classes for the
- different type of nodes of the tree.
-
- * the `manager` contains a high level object to get astroid trees from
- source files and living objects. It maintains a cache of previously
- constructed tree for quick access.
-
-
- Installation
- ------------
-
- Extract the tarball, jump into the created directory and run::
-
- python setup.py install
-
- For installation options, see::
-
- python setup.py install --help
-
-
- If you have any questions, please mail the code-quality@python.org
- mailing list for support. See
- http://mail.python.org/mailman/listinfo/code-quality for subscription
- information and archives. You may find older archives at
- http://lists.logilab.org/mailman/listinfo/python-projects .
-
- Test
- ----
-
- Tests are in the 'test' subdirectory. To launch the whole tests suite
- at once, you may use the 'pytest' utility from logilab-common (simply
- type 'pytest' from within this directory) or if you're running python
- >= 2.7, using discover, for instance::
-
- python -m unittest discover -p "unittest*.py"
-
-Platform: UNKNOWN
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: Software Development :: Quality Assurance
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 3
+Metadata-Version: 1.1
+Name: astroid
+Version: 1.3.8
+Summary: A abstract syntax tree for Python with inference support.
+Home-page: http://bitbucket.org/logilab/astroid
+Author: Logilab
+Author-email: pylint-dev@lists.logilab.org
+License: LGPL
+Description: .. image:: https://drone.io/bitbucket.org/logilab/astroid/status.png
+ :alt: drone.io Build Status
+ :target: https://drone.io/bitbucket.org/logilab/astroid
+
+ Astroid
+ =======
+
+ What's this?
+ ------------
+
+ The aim of this module is to provide a common base representation of
+ python source code for projects such as pychecker, pyreverse,
+ pylint... Well, actually the development of this library is essentially
+ governed by pylint's needs. It used to be called logilab-astng.
+
+ It provides a compatible representation which comes from the `_ast`
+ module. It rebuilds the tree generated by the builtin _ast module by
+ recursively walking down the AST and building an extended ast. The new
+ node classes have additional methods and attributes for different
+ usages. They include some support for static inference and local name
+ scopes. Furthermore, astroid builds partial trees by inspecting living
+ objects.
+
+ Main modules are:
+
+ * `bases`, `node_classses` and `scoped_nodes` contain the classes for the
+ different type of nodes of the tree.
+
+ * the `manager` contains a high level object to get astroid trees from
+ source files and living objects. It maintains a cache of previously
+ constructed tree for quick access.
+
+
+ Installation
+ ------------
+
+ Extract the tarball, jump into the created directory and run::
+
+ python setup.py install
+
+ For installation options, see::
+
+ python setup.py install --help
+
+
+ If you have any questions, please mail the code-quality@python.org
+ mailing list for support. See
+ http://mail.python.org/mailman/listinfo/code-quality for subscription
+ information and archives. You may find older archives at
+ http://lists.logilab.org/mailman/listinfo/python-projects .
+
+ Python Versions
+ ---------------
+
+ astroid is compatible with Python 2.7 as well as 3.3 and later. astroid uses
+ the same code base for both Python versions, using six.
+
+ Test
+ ----
+
+ Tests are in the 'test' subdirectory. To launch the whole tests suite
+ at once, you may use the 'pytest' utility from logilab-common (simply
+ type 'pytest' from within this directory) or using unittest discover::
+
+ python -m unittest discover -p "unittest*.py"
+
+Platform: UNKNOWN
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Software Development :: Quality Assurance
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
diff -Nru astroid-1.0.1/astroid.egg-info/requires.txt astroid-1.3.8/astroid.egg-info/requires.txt
--- astroid-1.0.1/astroid.egg-info/requires.txt 2013-10-18 15:34:18.000000000 +0000
+++ astroid-1.3.8/astroid.egg-info/requires.txt 2015-08-02 20:40:00.000000000 +0000
@@ -1 +1,2 @@
-logilab-common >= 0.60.0
\ No newline at end of file
+logilab-common>=0.63.0
+six
diff -Nru astroid-1.0.1/astroid.egg-info/SOURCES.txt astroid-1.3.8/astroid.egg-info/SOURCES.txt
--- astroid-1.0.1/astroid.egg-info/SOURCES.txt 2013-10-18 15:34:18.000000000 +0000
+++ astroid-1.3.8/astroid.egg-info/SOURCES.txt 2015-08-02 20:40:00.000000000 +0000
@@ -3,90 +3,138 @@
ChangeLog
MANIFEST.in
README
-README.Python3
+setup.cfg
setup.py
-./__init__.py
-./__pkginfo__.py
-./as_string.py
-./bases.py
-./builder.py
-./exceptions.py
-./inference.py
-./inspector.py
-./manager.py
-./mixins.py
-./node_classes.py
-./nodes.py
-./protocols.py
-./raw_building.py
-./rebuilder.py
-./scoped_nodes.py
-./test_utils.py
-./utils.py
-./test/unittest_brain.py
-./test/unittest_builder.py
-./test/unittest_inference.py
-./test/unittest_inspector.py
-./test/unittest_lookup.py
-./test/unittest_manager.py
-./test/unittest_nodes.py
-./test/unittest_python3.py
-./test/unittest_regrtest.py
-./test/unittest_scoped_nodes.py
-./test/unittest_utils.py
-./test/data/__init__.py
-./test/data/absimport.py
-./test/data/all.py
-./test/data/email.py
-./test/data/format.py
-./test/data/module.py
-./test/data/module2.py
-./test/data/noendingnewline.py
-./test/data/nonregr.py
-./test/data/notall.py
-./test/data/SSL1/Connection1.py
-./test/data/SSL1/__init__.py
-./test/data/appl/__init__.py
-./test/data/appl/myConnection.py
-./test/data2/__init__.py
-./test/data2/clientmodule_test.py
-./test/data2/suppliermodule_test.py
+tox.ini
+astroid/__init__.py
+astroid/__pkginfo__.py
+astroid/as_string.py
+astroid/astpeephole.py
+astroid/bases.py
+astroid/builder.py
+astroid/exceptions.py
+astroid/inference.py
+astroid/inspector.py
+astroid/manager.py
+astroid/mixins.py
+astroid/modutils.py
+astroid/node_classes.py
+astroid/nodes.py
+astroid/protocols.py
+astroid/raw_building.py
+astroid/rebuilder.py
+astroid/scoped_nodes.py
+astroid/test_utils.py
+astroid/utils.py
astroid.egg-info/PKG-INFO
astroid.egg-info/SOURCES.txt
astroid.egg-info/dependency_links.txt
astroid.egg-info/requires.txt
astroid.egg-info/top_level.txt
-brain/py2gi.py
-brain/py2mechanize.py
-brain/py2qt4.py
-brain/py2stdlib.py
-test/fulltest.sh
-test/data/MyPyPa-0.1.0-py2.5.egg
-test/data/MyPyPa-0.1.0-py2.5.zip
-test/data/__init__.py
-test/data/absimport.py
-test/data/all.py
-test/data/email.py
-test/data/format.py
-test/data/module.py
-test/data/module2.py
-test/data/noendingnewline.py
-test/data/nonregr.py
-test/data/notall.py
-test/data/SSL1/Connection1.py
-test/data/SSL1/__init__.py
-test/data/appl/__init__.py
-test/data/appl/myConnection.py
-test/data2/__init__.py
-test/data2/clientmodule_test.py
-test/data2/suppliermodule_test.py
-test/regrtest_data/descriptor_crash.py
-test/regrtest_data/absimp/__init__.py
-test/regrtest_data/absimp/string.py
-test/regrtest_data/absimp/sidepackage/__init__.py
-test/regrtest_data/package/__init__.py
-test/regrtest_data/package/absimport.py
-test/regrtest_data/package/hello.py
-test/regrtest_data/package/import_package_subpackage_module.py
-test/regrtest_data/package/subpackage/__init__.py
-test/regrtest_data/package/subpackage/module.py
\ No newline at end of file
+astroid/brain/builtin_inference.py
+astroid/brain/py2gi.py
+astroid/brain/py2mechanize.py
+astroid/brain/py2pytest.py
+astroid/brain/py2qt4.py
+astroid/brain/py2stdlib.py
+astroid/brain/pynose.py
+astroid/brain/pysix_moves.py
+astroid/tests/__init__.py
+astroid/tests/resources.py
+astroid/tests/unittest_brain.py
+astroid/tests/unittest_builder.py
+astroid/tests/unittest_inference.py
+astroid/tests/unittest_inspector.py
+astroid/tests/unittest_lookup.py
+astroid/tests/unittest_manager.py
+astroid/tests/unittest_modutils.py
+astroid/tests/unittest_nodes.py
+astroid/tests/unittest_peephole.py
+astroid/tests/unittest_protocols.py
+astroid/tests/unittest_python3.py
+astroid/tests/unittest_raw_building.py
+astroid/tests/unittest_regrtest.py
+astroid/tests/unittest_scoped_nodes.py
+astroid/tests/unittest_utils.py
+astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg
+astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip
+astroid/tests/testdata/python2/data/__init__.py
+astroid/tests/testdata/python2/data/absimport.py
+astroid/tests/testdata/python2/data/all.py
+astroid/tests/testdata/python2/data/clientmodule_test.py
+astroid/tests/testdata/python2/data/descriptor_crash.py
+astroid/tests/testdata/python2/data/email.py
+astroid/tests/testdata/python2/data/format.py
+astroid/tests/testdata/python2/data/joined_strings.py
+astroid/tests/testdata/python2/data/module.py
+astroid/tests/testdata/python2/data/module2.py
+astroid/tests/testdata/python2/data/noendingnewline.py
+astroid/tests/testdata/python2/data/nonregr.py
+astroid/tests/testdata/python2/data/notall.py
+astroid/tests/testdata/python2/data/recursion.py
+astroid/tests/testdata/python2/data/suppliermodule_test.py
+astroid/tests/testdata/python2/data/SSL1/Connection1.py
+astroid/tests/testdata/python2/data/SSL1/__init__.py
+astroid/tests/testdata/python2/data/absimp/__init__.py
+astroid/tests/testdata/python2/data/absimp/string.py
+astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py
+astroid/tests/testdata/python2/data/appl/__init__.py
+astroid/tests/testdata/python2/data/appl/myConnection.py
+astroid/tests/testdata/python2/data/find_test/__init__.py
+astroid/tests/testdata/python2/data/find_test/module.py
+astroid/tests/testdata/python2/data/find_test/module2.py
+astroid/tests/testdata/python2/data/find_test/noendingnewline.py
+astroid/tests/testdata/python2/data/find_test/nonregr.py
+astroid/tests/testdata/python2/data/lmfp/__init__.py
+astroid/tests/testdata/python2/data/lmfp/foo.py
+astroid/tests/testdata/python2/data/module1abs/__init__.py
+astroid/tests/testdata/python2/data/module1abs/core.py
+astroid/tests/testdata/python2/data/package/__init__.py
+astroid/tests/testdata/python2/data/package/absimport.py
+astroid/tests/testdata/python2/data/package/hello.py
+astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py
+astroid/tests/testdata/python2/data/package/subpackage/__init__.py
+astroid/tests/testdata/python2/data/package/subpackage/module.py
+astroid/tests/testdata/python2/data/unicode_package/__init__.py
+astroid/tests/testdata/python2/data/unicode_package/core/__init__.py
+astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg
+astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip
+astroid/tests/testdata/python3/data/__init__.py
+astroid/tests/testdata/python3/data/absimport.py
+astroid/tests/testdata/python3/data/all.py
+astroid/tests/testdata/python3/data/clientmodule_test.py
+astroid/tests/testdata/python3/data/descriptor_crash.py
+astroid/tests/testdata/python3/data/email.py
+astroid/tests/testdata/python3/data/format.py
+astroid/tests/testdata/python3/data/joined_strings.py
+astroid/tests/testdata/python3/data/module.py
+astroid/tests/testdata/python3/data/module2.py
+astroid/tests/testdata/python3/data/noendingnewline.py
+astroid/tests/testdata/python3/data/nonregr.py
+astroid/tests/testdata/python3/data/notall.py
+astroid/tests/testdata/python3/data/recursion.py
+astroid/tests/testdata/python3/data/suppliermodule_test.py
+astroid/tests/testdata/python3/data/SSL1/Connection1.py
+astroid/tests/testdata/python3/data/SSL1/__init__.py
+astroid/tests/testdata/python3/data/absimp/__init__.py
+astroid/tests/testdata/python3/data/absimp/string.py
+astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py
+astroid/tests/testdata/python3/data/appl/__init__.py
+astroid/tests/testdata/python3/data/appl/myConnection.py
+astroid/tests/testdata/python3/data/find_test/__init__.py
+astroid/tests/testdata/python3/data/find_test/module.py
+astroid/tests/testdata/python3/data/find_test/module2.py
+astroid/tests/testdata/python3/data/find_test/noendingnewline.py
+astroid/tests/testdata/python3/data/find_test/nonregr.py
+astroid/tests/testdata/python3/data/lmfp/__init__.py
+astroid/tests/testdata/python3/data/lmfp/foo.py
+astroid/tests/testdata/python3/data/module1abs/__init__.py
+astroid/tests/testdata/python3/data/module1abs/core.py
+astroid/tests/testdata/python3/data/package/__init__.py
+astroid/tests/testdata/python3/data/package/absimport.py
+astroid/tests/testdata/python3/data/package/hello.py
+astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py
+astroid/tests/testdata/python3/data/package/subpackage/__init__.py
+astroid/tests/testdata/python3/data/package/subpackage/module.py
+astroid/tests/testdata/python3/data/unicode_package/__init__.py
+astroid/tests/testdata/python3/data/unicode_package/core/__init__.py
\ No newline at end of file
diff -Nru astroid-1.0.1/bases.py astroid-1.3.8/bases.py
--- astroid-1.0.1/bases.py 2013-07-29 15:04:24.000000000 +0000
+++ astroid-1.3.8/bases.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,612 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""This module contains base classes and functions for the nodes and some
-inference utils.
-"""
-
-__docformat__ = "restructuredtext en"
-
-import sys
-from contextlib import contextmanager
-
-from astroid.exceptions import (InferenceError, AstroidError, NotFoundError,
- UnresolvableName, UseInferenceDefault)
-
-
-if sys.version_info >= (3, 0):
- BUILTINS = 'builtins'
-else:
- BUILTINS = '__builtin__'
-
-
-class Proxy(object):
- """a simple proxy object"""
-
- _proxied = None # proxied object may be set by class or by instance
-
- def __init__(self, proxied=None):
- if proxied is not None:
- self._proxied = proxied
-
- def __getattr__(self, name):
- if name == '_proxied':
- return getattr(self.__class__, '_proxied')
- if name in self.__dict__:
- return self.__dict__[name]
- return getattr(self._proxied, name)
-
- def infer(self, context=None):
- yield self
-
-
-# Inference ##################################################################
-
-class InferenceContext(object):
- __slots__ = ('path', 'lookupname', 'callcontext', 'boundnode')
-
- def __init__(self, path=None):
- if path is None:
- self.path = set()
- else:
- self.path = path
- self.lookupname = None
- self.callcontext = None
- self.boundnode = None
-
- def push(self, node):
- name = self.lookupname
- if (node, name) in self.path:
- raise StopIteration()
- self.path.add( (node, name) )
-
- def clone(self):
- # XXX copy lookupname/callcontext ?
- clone = InferenceContext(self.path)
- clone.callcontext = self.callcontext
- clone.boundnode = self.boundnode
- return clone
-
- @contextmanager
- def restore_path(self):
- path = set(self.path)
- yield
- self.path = path
-
-def copy_context(context):
- if context is not None:
- return context.clone()
- else:
- return InferenceContext()
-
-
-def _infer_stmts(stmts, context, frame=None):
- """return an iterator on statements inferred by each statement in
- """
- stmt = None
- infered = False
- if context is not None:
- name = context.lookupname
- context = context.clone()
- else:
- name = None
- context = InferenceContext()
- for stmt in stmts:
- if stmt is YES:
- yield stmt
- infered = True
- continue
- context.lookupname = stmt._infer_name(frame, name)
- try:
- for infered in stmt.infer(context):
- yield infered
- infered = True
- except UnresolvableName:
- continue
- except InferenceError:
- yield YES
- infered = True
- if not infered:
- raise InferenceError(str(stmt))
-
-
-# special inference objects (e.g. may be returned as nodes by .infer()) #######
-
-class _Yes(object):
- """a yes object"""
- def __repr__(self):
- return 'YES'
- def __getattribute__(self, name):
- if name == 'next':
- raise AttributeError('next method should not be called')
- if name.startswith('__') and name.endswith('__'):
- # to avoid inspection pb
- return super(_Yes, self).__getattribute__(name)
- return self
- def __call__(self, *args, **kwargs):
- return self
-
-
-YES = _Yes()
-
-
-class Instance(Proxy):
- """a special node representing a class instance"""
- def getattr(self, name, context=None, lookupclass=True):
- try:
- values = self._proxied.instance_attr(name, context)
- except NotFoundError:
- if name == '__class__':
- return [self._proxied]
- if lookupclass:
- # class attributes not available through the instance
- # unless they are explicitly defined
- if name in ('__name__', '__bases__', '__mro__', '__subclasses__'):
- return self._proxied.local_attr(name)
- return self._proxied.getattr(name, context)
- raise NotFoundError(name)
- # since we've no context information, return matching class members as
- # well
- if lookupclass:
- try:
- return values + self._proxied.getattr(name, context)
- except NotFoundError:
- pass
- return values
-
- def igetattr(self, name, context=None):
- """inferred getattr"""
- try:
- # XXX frame should be self._proxied, or not ?
- get_attr = self.getattr(name, context, lookupclass=False)
- return _infer_stmts(self._wrap_attr(get_attr, context), context,
- frame=self)
- except NotFoundError:
- try:
- # fallback to class'igetattr since it has some logic to handle
- # descriptors
- return self._wrap_attr(self._proxied.igetattr(name, context),
- context)
- except NotFoundError:
- raise InferenceError(name)
-
- def _wrap_attr(self, attrs, context=None):
- """wrap bound methods of attrs in a InstanceMethod proxies"""
- for attr in attrs:
- if isinstance(attr, UnboundMethod):
- if BUILTINS + '.property' in attr.decoratornames():
- for infered in attr.infer_call_result(self, context):
- yield infered
- else:
- yield BoundMethod(attr, self)
- else:
- yield attr
-
- def infer_call_result(self, caller, context=None):
- """infer what a class instance is returning when called"""
- infered = False
- for node in self._proxied.igetattr('__call__', context):
- for res in node.infer_call_result(caller, context):
- infered = True
- yield res
- if not infered:
- raise InferenceError()
-
- def __repr__(self):
- return '' % (self._proxied.root().name,
- self._proxied.name,
- id(self))
- def __str__(self):
- return 'Instance of %s.%s' % (self._proxied.root().name,
- self._proxied.name)
-
- def callable(self):
- try:
- self._proxied.getattr('__call__')
- return True
- except NotFoundError:
- return False
-
- def pytype(self):
- return self._proxied.qname()
-
- def display_type(self):
- return 'Instance of'
-
-
-class UnboundMethod(Proxy):
- """a special node representing a method not bound to an instance"""
- def __repr__(self):
- frame = self._proxied.parent.frame()
- return '<%s %s of %s at 0x%s' % (self.__class__.__name__,
- self._proxied.name,
- frame.qname(), id(self))
-
- def is_bound(self):
- return False
-
- def getattr(self, name, context=None):
- if name == 'im_func':
- return [self._proxied]
- return super(UnboundMethod, self).getattr(name, context)
-
- def igetattr(self, name, context=None):
- if name == 'im_func':
- return iter((self._proxied,))
- return super(UnboundMethod, self).igetattr(name, context)
-
- def infer_call_result(self, caller, context):
- # If we're unbound method __new__ of builtin object, the result is an
- # instance of the class given as first argument.
- if (self._proxied.name == '__new__' and
- self._proxied.parent.frame().qname() == '%s.object' % BUILTINS):
- return (x is YES and x or Instance(x) for x in caller.args[0].infer())
- return self._proxied.infer_call_result(caller, context)
-
-
-class BoundMethod(UnboundMethod):
- """a special node representing a method bound to an instance"""
- def __init__(self, proxy, bound):
- UnboundMethod.__init__(self, proxy)
- self.bound = bound
-
- def is_bound(self):
- return True
-
- def infer_call_result(self, caller, context):
- context = context.clone()
- context.boundnode = self.bound
- return self._proxied.infer_call_result(caller, context)
-
-
-class Generator(Instance):
- """a special node representing a generator.
-
- Proxied class is set once for all in raw_building.
- """
- def callable(self):
- return False
-
- def pytype(self):
- return '%s.generator' % BUILTINS
-
- def display_type(self):
- return 'Generator'
-
- def __repr__(self):
- return '' % (self._proxied.name, self.lineno, id(self))
-
- def __str__(self):
- return 'Generator(%s)' % (self._proxied.name)
-
-
-# decorators ##################################################################
-
-def path_wrapper(func):
- """return the given infer function wrapped to handle the path"""
- def wrapped(node, context=None, _func=func, **kwargs):
- """wrapper function handling context"""
- if context is None:
- context = InferenceContext()
- context.push(node)
- yielded = set()
- for res in _func(node, context, **kwargs):
- # unproxy only true instance, not const, tuple, dict...
- if res.__class__ is Instance:
- ares = res._proxied
- else:
- ares = res
- if not ares in yielded:
- yield res
- yielded.add(ares)
- return wrapped
-
-def yes_if_nothing_infered(func):
- def wrapper(*args, **kwargs):
- infered = False
- for node in func(*args, **kwargs):
- infered = True
- yield node
- if not infered:
- yield YES
- return wrapper
-
-def raise_if_nothing_infered(func):
- def wrapper(*args, **kwargs):
- infered = False
- for node in func(*args, **kwargs):
- infered = True
- yield node
- if not infered:
- raise InferenceError()
- return wrapper
-
-
-# Node ######################################################################
-
-class NodeNG(object):
- """Base Class for all Astroid node classes.
-
- It represents a node of the new abstract syntax tree.
- """
- is_statement = False
- optional_assign = False # True for For (and for Comprehension if py <3.0)
- is_function = False # True for Function nodes
- # attributes below are set by the builder module or by raw factories
- lineno = None
- fromlineno = None
- tolineno = None
- col_offset = None
- # parent node in the tree
- parent = None
- # attributes containing child node(s) redefined in most concrete classes:
- _astroid_fields = ()
- # instance specific inference function infer(node, context)
- _explicit_inference = None
-
- def infer(self, context=None, **kwargs):
- """main interface to the interface system, return a generator on infered
- values.
-
- If the instance has some explicit inference function set, it will be
- called instead of the default interface.
- """
- if self._explicit_inference is not None:
- # explicit_inference is not bound, give it self explicitly
- try:
- return self._explicit_inference(self, context, **kwargs)
- except UseInferenceDefault:
- pass
- return self._infer(context, **kwargs)
-
- def _repr_name(self):
- """return self.name or self.attrname or '' for nice representation"""
- return getattr(self, 'name', getattr(self, 'attrname', ''))
-
- def __str__(self):
- return '%s(%s)' % (self.__class__.__name__, self._repr_name())
-
- def __repr__(self):
- return '<%s(%s) l.%s [%s] at Ox%x>' % (self.__class__.__name__,
- self._repr_name(),
- self.fromlineno,
- self.root().name,
- id(self))
-
-
- def accept(self, visitor):
- klass = self.__class__.__name__
- func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
- return func(self)
-
- def get_children(self):
- for field in self._astroid_fields:
- attr = getattr(self, field)
- if attr is None:
- continue
- if isinstance(attr, (list, tuple)):
- for elt in attr:
- yield elt
- else:
- yield attr
-
- def last_child(self):
- """an optimized version of list(get_children())[-1]"""
- for field in self._astroid_fields[::-1]:
- attr = getattr(self, field)
- if not attr: # None or empty listy / tuple
- continue
- if isinstance(attr, (list, tuple)):
- return attr[-1]
- else:
- return attr
- return None
-
- def parent_of(self, node):
- """return true if i'm a parent of the given node"""
- parent = node.parent
- while parent is not None:
- if self is parent:
- return True
- parent = parent.parent
- return False
-
- def statement(self):
- """return the first parent node marked as statement node"""
- if self.is_statement:
- return self
- return self.parent.statement()
-
- def frame(self):
- """return the first parent frame node (i.e. Module, Function or Class)
- """
- return self.parent.frame()
-
- def scope(self):
- """return the first node defining a new scope (i.e. Module, Function,
- Class, Lambda but also GenExpr)
- """
- return self.parent.scope()
-
- def root(self):
- """return the root node of the tree, (i.e. a Module)"""
- if self.parent:
- return self.parent.root()
- return self
-
- def child_sequence(self, child):
- """search for the right sequence where the child lies in"""
- for field in self._astroid_fields:
- node_or_sequence = getattr(self, field)
- if node_or_sequence is child:
- return [node_or_sequence]
- # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
- if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
- return node_or_sequence
- else:
- msg = 'Could not find %s in %s\'s children'
- raise AstroidError(msg % (repr(child), repr(self)))
-
- def locate_child(self, child):
- """return a 2-uple (child attribute name, sequence or node)"""
- for field in self._astroid_fields:
- node_or_sequence = getattr(self, field)
- # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
- if child is node_or_sequence:
- return field, child
- if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
- return field, node_or_sequence
- msg = 'Could not find %s in %s\'s children'
- raise AstroidError(msg % (repr(child), repr(self)))
- # FIXME : should we merge child_sequence and locate_child ? locate_child
- # is only used in are_exclusive, child_sequence one time in pylint.
-
- def next_sibling(self):
- """return the next sibling statement"""
- return self.parent.next_sibling()
-
- def previous_sibling(self):
- """return the previous sibling statement"""
- return self.parent.previous_sibling()
-
- def nearest(self, nodes):
- """return the node which is the nearest before this one in the
- given list of nodes
- """
- myroot = self.root()
- mylineno = self.fromlineno
- nearest = None, 0
- for node in nodes:
- assert node.root() is myroot, \
- 'nodes %s and %s are not from the same module' % (self, node)
- lineno = node.fromlineno
- if node.fromlineno > mylineno:
- break
- if lineno > nearest[1]:
- nearest = node, lineno
- # FIXME: raise an exception if nearest is None ?
- return nearest[0]
-
- def set_line_info(self, lastchild):
- if self.lineno is None:
- self.fromlineno = self._fixed_source_line()
- else:
- self.fromlineno = self.lineno
- if lastchild is None:
- self.tolineno = self.fromlineno
- else:
- self.tolineno = lastchild.tolineno
- return
- # TODO / FIXME:
- assert self.fromlineno is not None, self
- assert self.tolineno is not None, self
-
- def _fixed_source_line(self):
- """return the line number where the given node appears
-
- we need this method since not all nodes have the lineno attribute
- correctly set...
- """
- line = self.lineno
- _node = self
- try:
- while line is None:
- _node = _node.get_children().next()
- line = _node.lineno
- except StopIteration:
- _node = self.parent
- while _node and line is None:
- line = _node.lineno
- _node = _node.parent
- return line
-
- def block_range(self, lineno):
- """handle block line numbers range for non block opening statements
- """
- return lineno, self.tolineno
-
- def set_local(self, name, stmt):
- """delegate to a scoped parent handling a locals dictionary"""
- self.parent.set_local(name, stmt)
-
- def nodes_of_class(self, klass, skip_klass=None):
- """return an iterator on nodes which are instance of the given class(es)
-
- klass may be a class object or a tuple of class objects
- """
- if isinstance(self, klass):
- yield self
- for child_node in self.get_children():
- if skip_klass is not None and isinstance(child_node, skip_klass):
- continue
- for matching in child_node.nodes_of_class(klass, skip_klass):
- yield matching
-
- def _infer_name(self, frame, name):
- # overridden for From, Import, Global, TryExcept and Arguments
- return None
-
- def _infer(self, context=None):
- """we don't know how to resolve a statement by default"""
- # this method is overridden by most concrete classes
- raise InferenceError(self.__class__.__name__)
-
- def infered(self):
- '''return list of infered values for a more simple inference usage'''
- return list(self.infer())
-
- def instanciate_class(self):
- """instanciate a node if it is a Class node, else return self"""
- return self
-
- def has_base(self, node):
- return False
-
- def callable(self):
- return False
-
- def eq(self, value):
- return False
-
- def as_string(self):
- from astroid.as_string import to_code
- return to_code(self)
-
- def repr_tree(self, ids=False):
- from astroid.as_string import dump
- return dump(self)
-
-
-class Statement(NodeNG):
- """Statement node adding a few attributes"""
- is_statement = True
-
- def next_sibling(self):
- """return the next sibling statement"""
- stmts = self.parent.child_sequence(self)
- index = stmts.index(self)
- try:
- return stmts[index +1]
- except IndexError:
- pass
-
- def previous_sibling(self):
- """return the previous sibling statement"""
- stmts = self.parent.child_sequence(self)
- index = stmts.index(self)
- if index >= 1:
- return stmts[index -1]
diff -Nru astroid-1.0.1/brain/py2gi.py astroid-1.3.8/brain/py2gi.py
--- astroid-1.0.1/brain/py2gi.py 2013-10-18 15:34:05.000000000 +0000
+++ astroid-1.3.8/brain/py2gi.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,147 +0,0 @@
-"""Astroid hooks for the Python 2 GObject introspection bindings.
-
-Helps with understanding everything imported from 'gi.repository'
-"""
-
-import inspect
-import sys
-
-from astroid import MANAGER, AstroidBuildingException
-from astroid.builder import AstroidBuilder
-
-
-_inspected_modules = {}
-
-
-def _gi_build_stub(parent):
- """
- Inspect the passed module recursively and build stubs for functions,
- classes, etc.
- """
- classes = {}
- functions = {}
- constants = {}
- methods = {}
- for name in dir(parent):
- if not name or name.startswith("__"):
- # GLib.IConv has a parameter named "" :/
- continue
- try:
- obj = getattr(parent, name)
- except:
- continue
-
- if inspect.isclass(obj):
- classes[name] = obj
- elif (inspect.isfunction(obj) or
- inspect.isbuiltin(obj)):
- functions[name] = obj
- elif (inspect.ismethod(obj) or
- inspect.ismethoddescriptor(obj)):
- methods[name] = obj
- elif type(obj) in [int, str]:
- constants[name] = obj
- elif (str(obj).startswith(".
-"""The AstroidBuilder makes astroid from living object and / or from _ast
-
-The builder is not thread safe and can't be used to parse different sources
-at the same time.
-"""
-
-__docformat__ = "restructuredtext en"
-
-import sys
-from os.path import splitext, basename, exists, abspath
-
-from logilab.common.modutils import modpath_from_file
-
-from astroid.exceptions import AstroidBuildingException, InferenceError
-from astroid.raw_building import InspectBuilder
-from astroid.rebuilder import TreeRebuilder
-from astroid.manager import AstroidManager
-from astroid.bases import YES, Instance
-
-from _ast import PyCF_ONLY_AST
-def parse(string):
- return compile(string, "", 'exec', PyCF_ONLY_AST)
-
-if sys.version_info >= (3, 0):
- from tokenize import detect_encoding
-
- def open_source_file(filename):
- byte_stream = open(filename, 'bU')
- encoding = detect_encoding(byte_stream.readline)[0]
- stream = open(filename, 'U', encoding=encoding)
- try:
- data = stream.read()
- except UnicodeError, uex: # wrong encodingg
- # detect_encoding returns utf-8 if no encoding specified
- msg = 'Wrong (%s) or no encoding specified' % encoding
- raise AstroidBuildingException(msg)
- return stream, encoding, data
-
-else:
- import re
-
- _ENCODING_RGX = re.compile("\s*#+.*coding[:=]\s*([-\w.]+)")
-
- def _guess_encoding(string):
- """get encoding from a python file as string or return None if not found
- """
- # check for UTF-8 byte-order mark
- if string.startswith('\xef\xbb\xbf'):
- return 'UTF-8'
- for line in string.split('\n', 2)[:2]:
- # check for encoding declaration
- match = _ENCODING_RGX.match(line)
- if match is not None:
- return match.group(1)
-
- def open_source_file(filename):
- """get data for parsing a file"""
- stream = open(filename, 'U')
- data = stream.read()
- encoding = _guess_encoding(data)
- return stream, encoding, data
-
-# ast NG builder ##############################################################
-
-MANAGER = AstroidManager()
-
-class AstroidBuilder(InspectBuilder):
- """provide astroid building methods"""
-
- def __init__(self, manager=None):
- InspectBuilder.__init__(self)
- self._manager = manager or MANAGER
-
- def module_build(self, module, modname=None):
- """build an astroid from a living module instance
- """
- node = None
- path = getattr(module, '__file__', None)
- if path is not None:
- path_, ext = splitext(module.__file__)
- if ext in ('.py', '.pyc', '.pyo') and exists(path_ + '.py'):
- node = self.file_build(path_ + '.py', modname)
- if node is None:
- # this is a built-in module
- # get a partial representation by introspection
- node = self.inspect_build(module, modname=modname, path=path)
- return node
-
- def file_build(self, path, modname=None):
- """build astroid from a source code file (i.e. from an ast)
-
- path is expected to be a python source file
- """
- try:
- stream, encoding, data = open_source_file(path)
- except IOError, exc:
- msg = 'Unable to load file %r (%s)' % (path, exc)
- raise AstroidBuildingException(msg)
- except SyntaxError, exc: # py3k encoding specification error
- raise AstroidBuildingException(exc)
- except LookupError, exc: # unknown encoding
- raise AstroidBuildingException(exc)
- # get module name if necessary
- if modname is None:
- try:
- modname = '.'.join(modpath_from_file(path))
- except ImportError:
- modname = splitext(basename(path))[0]
- # build astroid representation
- node = self.string_build(data, modname, path)
- node.file_encoding = encoding
- return node
-
- def string_build(self, data, modname='', path=None):
- """build astroid from source code string and return rebuilded astroid"""
- module = self._data_build(data, modname, path)
- self._manager.astroid_cache[module.name] = module
- # post tree building steps after we stored the module in the cache:
- for from_node in module._from_nodes:
- self.add_from_names_to_locals(from_node)
- # handle delayed assattr nodes
- for delayed in module._delayed_assattr:
- self.delayed_assattr(delayed)
- return module
-
- def _data_build(self, data, modname, path):
- """build tree node from data and add some informations"""
- # this method could be wrapped with a pickle/cache function
- node = parse(data + '\n')
- if path is not None:
- node_file = abspath(path)
- else:
- node_file = '>'
- if modname.endswith('.__init__'):
- modname = modname[:-9]
- package = True
- else:
- package = path and path.find('__init__.py') > -1 or False
- rebuilder = TreeRebuilder(self._manager)
- module = rebuilder.visit_module(node, modname, package)
- module.file = module.path = node_file
- module._from_nodes = rebuilder._from_nodes
- module._delayed_assattr = rebuilder._delayed_assattr
- return module
-
- def add_from_names_to_locals(self, node):
- """store imported names to the locals;
- resort the locals if coming from a delayed node
- """
-
- _key_func = lambda node: node.fromlineno
- def sort_locals(my_list):
- my_list.sort(key=_key_func)
- for (name, asname) in node.names:
- if name == '*':
- try:
- imported = node.root().import_module(node.modname)
- except AstroidBuildingException:
- continue
- for name in imported.wildcard_import_names():
- node.parent.set_local(name, node)
- sort_locals(node.parent.scope().locals[name])
- else:
- node.parent.set_local(asname or name, node)
- sort_locals(node.parent.scope().locals[asname or name])
-
- def delayed_assattr(self, node):
- """visit a AssAttr node -> add name to locals, handle members
- definition
- """
- try:
- frame = node.frame()
- for infered in node.expr.infer():
- if infered is YES:
- continue
- try:
- if infered.__class__ is Instance:
- infered = infered._proxied
- iattrs = infered.instance_attrs
- elif isinstance(infered, Instance):
- # Const, Tuple, ... we may be wrong, may be not, but
- # anyway we don't want to pollute builtin's namespace
- continue
- elif infered.is_function:
- iattrs = infered.instance_attrs
- else:
- iattrs = infered.locals
- except AttributeError:
- # XXX log error
- #import traceback
- #traceback.print_exc()
- continue
- values = iattrs.setdefault(node.attrname, [])
- if node in values:
- continue
- # get assign in __init__ first XXX useful ?
- if frame.name == '__init__' and values and not \
- values[0].frame().name == '__init__':
- values.insert(0, node)
- else:
- values.append(node)
- except InferenceError:
- pass
-
diff -Nru astroid-1.0.1/ChangeLog astroid-1.3.8/ChangeLog
--- astroid-1.0.1/ChangeLog 2013-10-18 15:34:05.000000000 +0000
+++ astroid-1.3.8/ChangeLog 2015-08-02 19:37:44.000000000 +0000
@@ -1,6 +1,251 @@
Change log for the astroid package (used to be astng)
=====================================================
+2015-08-02 -- 1.3.8
+
+ * Backport of 40e3176, which fixes issue #84.
+
+2015-07-27 -- 1.3.7
+
+ * Improve the inference of six.moves, especially when using `from ... import ...`
+ syntax. Also, we added a new fail import hook for six.moves, which fixes the
+ import-error false positive from pylint. Closes issue #107.
+
+2015-03-14 -- 1.3.6
+
+ * Class.slots raises NotImplementedError for old style classes.
+ Closes issue #67.
+
+ * Add a new option to AstroidManager, `optimize_ast`, which
+ controls if peephole optimizer should be enabled or not.
+ This prevents a regression, where the visit_binop method
+ wasn't called anymore with astroid 1.3.5, due to the differences
+ in the resulting AST. Closes issue #82.
+
+
+2015-03-11 -- 1.3.5
+
+ * Add the ability to optimize small ast subtrees,
+ with the first use in the optimization of multiple
+ BinOp nodes. This removes recursivity in the rebuilder
+ when dealing with a lot of small strings joined by the
+ addition operator. Closes issue #59.
+
+ * Obtain the methods for the nose brain tip through an
+ unittest.TestCase instance. Closes Pylint issue #457.
+
+ * Fix a crash which occurred when a class was the ancestor
+ of itself. Closes issue #78.
+
+ * Improve the scope_lookup method for Classes regarding qualified
+ objects, with an attribute name exactly as one provided in the
+ class itself.
+
+ For example, a class containing an attribute 'first',
+ which was also an import and which had, as a base, a qualified name
+ or a Gettattr node, in the form 'module.first', then Pylint would
+ have inferred the `first` name as the function from the Class,
+ not the import. Closes Pylint issue #466.
+
+ * Implement the assigned_stmts operation for Starred nodes,
+ which was omitted when support for Python 3 was added in astroid.
+ Closes issue #36.
+
+
+2015-01-17 -- 1.3.4
+
+ * Get the first element from the method list when obtaining
+ the functions from nose.tools.trivial. Closes Pylint issue #448.
+
+2015-01-16 -- 1.3.3
+
+ * Restore file_stream to a property, but deprecate it in favour of
+ the newly added method Module.stream. By using a method instead of a
+ property, it will be easier to properly close the file right
+ after it is used, which will ensure that no file descriptors are
+ leaked. Until now, due to the fact that a module was cached,
+ it was not possible to close the file_stream anywhere.
+ file_stream will start emitting PendingDeprecationWarnings in
+ astroid 1.4, DeprecationWarnings in astroid 1.5 and it will
+ be finally removed in astroid 1.6.
+
+ * Add inference tips for 'tuple', 'list', 'dict' and 'set' builtins.
+
+ * Add brain definition for most string and unicode methods
+
+ * Changed the API for Class.slots. It returns None when the class
+ doesn't define any slots. Previously, for both the cases where
+ the class didn't have slots defined and when it had an empty list
+ of slots, Class.slots returned an empty list.
+
+ * Add a new method to Class nodes, 'mro', for obtaining the
+ the method resolution order of the class.
+
+ * Add brain tips for six.moves. Closes issue #63.
+
+ * Improve the detection for functions decorated with decorators
+ which returns static or class methods.
+
+ * .slots() can contain unicode strings on Python 2.
+
+ * Add inference tips for nose.tools.
+
+
+2014-11-22 -- 1.3.2
+
+ * Fixed a crash with invalid subscript index.
+
+ * Implement proper base class semantics for Python 3, where
+ every class derives from object.
+
+ * Allow more fine-grained control over C extension loading
+ in the manager.
+
+2014-11-21 -- 1.3.1
+
+ * Fixed a crash issue with the pytest brain module.
+
+2014-11-20 -- 1.3.0
+
+ * Fix a maximum recursion error occured during the inference,
+ where statements with the same name weren't filtered properly.
+ Closes pylint issue #295.
+
+ * Check that EmptyNode has an underlying object in
+ EmptyNode.has_underlying_object.
+
+ * Simplify the understanding of enum members.
+
+ * Fix an infinite loop with decorator call chain inference,
+ where the decorator returns itself. Closes issue #50.
+
+ * Various speed improvements. Patch by Alex Munroe.
+
+ * Add pytest brain plugin. Patch by Robbie Coomber.
+
+ * Support for Python versions < 2.7 has been dropped, and the
+ source has been made compatible with Python 2 and 3. Running
+ 2to3 on installation for Python 3 is not needed anymore.
+
+ * astroid now depends on six.
+
+ * modutils._module_file opens __init__.py in binary mode.
+ Closes issues #51 and #13.
+
+ * Only C extensions from trusted sources (the standard library)
+ are loaded into the examining Python process to build an AST
+ from the live module.
+
+ * Path names on case-insensitive filesystems are now properly
+ handled. This fixes the stdlib detection code on Windows.
+
+ * Metaclass-generating functions like six.with_metaclass
+ are now supported via some explicit detection code.
+
+ * astroid.register_module_extender has been added to generalize
+ the support for module extenders as used by many brain plugins.
+
+ * brain plugins can now register hooks to handle failed imports,
+ as done by the gobject-introspection plugin.
+
+ * The modules have been moved to a separate package directory,
+ `setup.py develop` now works correctly.
+
+
+2014-08-24 -- 1.2.1
+
+ * Fix a crash occurred when inferring decorator call chain.
+ Closes issue #42.
+
+ * Set the parent of vararg and kwarg nodes when inferring them.
+ Closes issue #43.
+
+ * namedtuple inference knows about '_fields' attribute.
+
+ * enum members knows about the methods from the enum class.
+
+ * Name inference will lookup in the parent function
+ of the current scope, in case searching in the current scope
+ fails.
+
+ * Inference of the functional form of the enums takes into
+ consideration the various inputs that enums accepts.
+
+ * The inference engine handles binary operations (add, mul etc.)
+ between instances.
+
+ * Fix an infinite loop in the inference, by returning a copy
+ of instance attributes, when calling 'instance_attr'.
+ Closes issue #34 (patch by Emile Anclin).
+
+ * Don't crash when trying to infer unbound object.__new__ call.
+ Closes issue #11.
+
+2014-07-25 -- 1.2.0
+
+ * Function nodes can detect decorator call chain and see if they are
+ decorated with builtin descriptors (`classmethod` and `staticmethod`).
+
+ * infer_call_result called on a subtype of the builtin type will now
+ return a new `Class` rather than an `Instance`.
+
+ * `Class.metaclass()` now handles module-level __metaclass__ declaration
+ on python 2, and no longer looks at the __metaclass__ class attribute on
+ python 3.
+
+ * Function nodes can detect if they are decorated with subclasses
+ of builtin descriptors when determining their type
+ (`classmethod` and `staticmethod`).
+
+ * Add `slots` method to `Class` nodes, for retrieving
+ the list of valid slots it defines.
+
+ * Expose function annotation to astroid: `Arguments` node
+ exposes 'varargannotation', 'kwargannotation' and 'annotations'
+ attributes, while `Function` node has the 'returns' attribute.
+
+ * Backported most of the logilab.common.modutils module there, as
+ most things there are for pylint/astroid only and we want to be
+ able to fix them without requiring a new logilab.common release
+
+ * Fix names grabed using wildcard import in "absolute import mode"
+ (ie with absolute_import activated from the __future__ or with
+ python 3). Fix pylint issue #58.
+
+ * Add support in pylint-brain for understanding enum classes.
+
+2014-04-30 -- 1.1.1
+ * `Class.metaclass()` looks in ancestors when the current class
+ does not define explicitly a metaclass.
+
+ * Do not cache modules if a module with the same qname is already
+ known, and only return cached modules if both name and filepath
+ match. Fixes pylint Bitbucket issue #136.
+
+2014-04-18 -- 1.1.0
+ * All class nodes are marked as new style classes for Py3k.
+
+ * Add a `metaclass` function to `Class` nodes to
+ retrieve their metaclass.
+
+ * Add a new YieldFrom node.
+
+ * Add support for inferring arguments to namedtuple invocations.
+
+ * Make sure that objects returned for namedtuple
+ inference have parents.
+
+ * Don't crash when inferring nodes from `with` clauses
+ with multiple context managers. Closes #18.
+
+ * Don't crash when a class has some __call__ method that is not
+ inferable. Closes #17.
+
+ * Unwrap instances found in `.ancestors()`, by using their _proxied
+ class.
+
+
+
2013-10-18 -- 1.0.1
* fix py3k/windows installation issue (issue #4)
@@ -21,7 +266,7 @@
as abstract.
* Allow transformation functions on any node, providing a
- `register_transform` function on the manager instead of the
+ `register_transform` function on the manager instead of the
`register_transformer` to make it more flexible wrt node selection
* Use the new transformation API to provide support for namedtuple
diff -Nru astroid-1.0.1/debian/changelog astroid-1.3.8/debian/changelog
--- astroid-1.0.1/debian/changelog 2014-01-04 11:14:18.000000000 +0000
+++ astroid-1.3.8/debian/changelog 2015-11-05 20:23:22.000000000 +0000
@@ -1,3 +1,109 @@
+astroid (1.3.8-1~trusty) trusty; urgency=medium
+
+ * Backport to trusty.
+
+ -- Robert Bruce Park Thu, 05 Nov 2015 14:22:55 -0600
+
+astroid (1.3.8-1) unstable; urgency=medium
+
+ * New upstream release
+ * debian/control
+ - tighen logilab-common deps to >= 0.63.0
+
+ -- Sandro Tosi Tue, 04 Aug 2015 07:57:06 +0100
+
+astroid (1.3.6-2) unstable; urgency=medium
+
+ * upload to unstable
+
+ -- Sandro Tosi Sun, 02 Aug 2015 00:11:06 +0100
+
+astroid (1.3.6-1) experimental; urgency=medium
+
+ * New upstream release
+ * debian/watch
+ - uses PyPI redirector
+ * debian/control
+ - add python{,3}-nose to b-d, needed to run tests
+
+ -- Sandro Tosi Thu, 26 Mar 2015 00:28:54 +0000
+
+astroid (1.3.4-1) experimental; urgency=medium
+
+ * New upstream release
+ * debian/copyright
+ - extend upstream and packaging copyright years
+ - update upstream email contact
+ - update path location for new upstream code organization
+ * debian/control
+ - add six to dependencies
+ - add setuptoold to b-d
+ * debian/patches/*
+ - drop patched, they are now part of a release
+ * debian/watch
+ - update to the proper PyPI location
+ * debian/rules
+ - test dir has changed name, update rm command
+
+ -- Sandro Tosi Sun, 01 Feb 2015 21:31:37 +0000
+
+astroid (1.2.1-3) unstable; urgency=medium
+
+ * debian/patches/afea46c0380956213976db2ce0f1e8f3cf6a0abc.patch
+ - enable fine-grained control over extensions loading; this fix is needed
+ after #591676 fix; Addresses: #772018
+
+ -- Sandro Tosi Mon, 08 Dec 2014 21:43:04 +0000
+
+astroid (1.2.1-2) unstable; urgency=medium
+
+ * debian/patches/e24cacb15e2e152db155fdca9197a8d1bf9ce235.patch
+ - Never load C extensions that are not from the standard library and also
+ never load any compiled Python files; thanks to Jakub Wilk for the report;
+ Closes: #591676
+
+ -- Sandro Tosi Sun, 23 Nov 2014 13:36:44 +0000
+
+astroid (1.2.1-1) unstable; urgency=medium
+
+ * New upstream release
+ * debian/watch
+ - update to support multiple tarball formats
+ * debian/control
+ - bump Standards-Version to 3.9.6 (no changes needed)
+ - add dh-python to b-d, that package will contain dh_python* scripts
+
+ -- Sandro Tosi Sun, 02 Nov 2014 14:47:27 +0000
+
+astroid (1.2.0-1) unstable; urgency=medium
+
+ * New upstream release
+
+ -- Sandro Tosi Sat, 09 Aug 2014 14:47:03 +0100
+
+astroid (1.1.1-1) unstable; urgency=medium
+
+ * New upstream release; Closes: #735327
+ * debian/control
+ - switch me to Maintainer (team to Uploaders)
+ * debian/copyright
+ - extend upstream copyright years
+ * debian/patches/*
+ - removed, merged upstream
+
+ -- Sandro Tosi Sun, 11 May 2014 17:43:01 +0200
+
+astroid (1.0.1-2) unstable; urgency=low
+
+ * debian/copyright
+ - document test/data/SSL1/Connection1.py copyright, as pointed out by
+ Thorsten Alteholz
+ * debian/patches/bts744225-fix-gi-introspection-issues.patch
+ - fix GI introspection issues; thanks to Leo Iannacone for the report;
+ Closes: #744225
+
+ -- Sandro Tosi Sat, 19 Apr 2014 19:57:08 +0200
+
astroid (1.0.1-1) unstable; urgency=low
* Initial release (Closes: #734075)
diff -Nru astroid-1.0.1/debian/control astroid-1.3.8/debian/control
--- astroid-1.0.1/debian/control 2014-01-04 10:40:47.000000000 +0000
+++ astroid-1.3.8/debian/control 2015-08-04 06:55:22.000000000 +0000
@@ -1,17 +1,17 @@
Source: astroid
Section: python
Priority: optional
-Maintainer: Debian Python Modules Team
-Uploaders: Sandro Tosi
-Build-Depends: debhelper (>= 9.0.0), python, python3
-Standards-Version: 3.9.5
+Maintainer: Sandro Tosi
+Uploaders: Debian Python Modules Team
+Build-Depends: debhelper (>= 9.0.0), python, python3, dh-python, python-setuptools, python3-setuptools, python-nose, python3-nose
+Standards-Version: 3.9.6
Homepage: http://www.astroid.org/
Vcs-Svn: svn://anonscm.debian.org/python-modules/packages/astroid/trunk/
Vcs-Browser: http://anonscm.debian.org/viewvc/python-modules/packages/astroid/trunk/
Package: python-astroid
Architecture: all
-Depends: ${python:Depends}, ${misc:Depends}, python-logilab-common (>= 0.60.0)
+Depends: ${python:Depends}, ${misc:Depends}, python-logilab-common (>= 0.63.0), python-six
Description: rebuild a new abstract syntax tree from Python's AST
The aim of this module is to provide a common base representation of
Python source code for projects such as pychecker, pyreverse,
@@ -39,7 +39,7 @@
Package: python3-astroid
Architecture: all
-Depends: ${python3:Depends}, ${misc:Depends}, python3-logilab-common (>= 0.60.0)
+Depends: ${python3:Depends}, ${misc:Depends}, python3-logilab-common (>= 0.63.0), python3-six
Description: rebuild a new abstract syntax tree from Python's AST (Python3)
The aim of this module is to provide a common base representation of
Python source code for projects such as pychecker, pyreverse,
diff -Nru astroid-1.0.1/debian/copyright astroid-1.3.8/debian/copyright
--- astroid-1.0.1/debian/copyright 2014-01-03 15:24:05.000000000 +0000
+++ astroid-1.3.8/debian/copyright 2015-01-31 01:39:21.000000000 +0000
@@ -3,7 +3,7 @@
Source: http://www.astroid.org/
Files: *
-Copyright: 2003-2013 Logilab
+Copyright: 2003-2015 Logilab
License: LGPL-2.1+
astroid is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the
@@ -22,7 +22,7 @@
License version 2.1 can be found in "/usr/share/common-licenses/LGPL-2.1".
Files: debian/*
-Copyright: 2014 Sandro Tosi
+Copyright: 2014-2015 Sandro Tosi
License: LGPL-2.1+
astroid is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the
@@ -40,7 +40,7 @@
On Debian systems, the complete text of the GNU Lesser General Public
License version 2.1 can be found in "/usr/share/common-licenses/LGPL-2.1".
-Files: test/unittest_brain.py
+Files: astroid/tests/unittest_brain.py
Copyright: Copyright 2013 Google Inc. All Rights Reserved.
License: LGPL-2.1+
astroid is free software: you can redistribute it and/or modify it
@@ -59,3 +59,5 @@
On Debian systems, the complete text of the GNU Lesser General Public
License version 2.1 can be found in "/usr/share/common-licenses/LGPL-2.1".
+Files: astroid/tests/testdata/python{2,3}/data/SSL1/Connection1.py
+Copyright: Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved.
diff -Nru astroid-1.0.1/debian/rules astroid-1.3.8/debian/rules
--- astroid-1.0.1/debian/rules 2014-01-04 11:12:08.000000000 +0000
+++ astroid-1.3.8/debian/rules 2015-02-01 21:18:20.000000000 +0000
@@ -18,7 +18,7 @@
--root=$(CURDIR)/debian/$(PKG3)/ \
--install-layout=deb
# remove tests files
- rm -rf debian/*/usr/lib/python*/*-packages/astroid/test
+ rm -rf debian/*/usr/lib/python*/*-packages/astroid/tests
override_dh_installdocs:
dh_installdocs -i README
diff -Nru astroid-1.0.1/debian/watch astroid-1.3.8/debian/watch
--- astroid-1.0.1/debian/watch 2014-01-03 15:24:05.000000000 +0000
+++ astroid-1.3.8/debian/watch 2015-03-25 11:28:34.000000000 +0000
@@ -1,4 +1,3 @@
-# Compulsory line, this is a version 3 file
version=3
-
-https://pypi.python.org/packages/source/a/astroid/astroid-(.*)\.tar.gz
+opts=uversionmangle=s/(rc|a|b|c)/~$1/ \
+http://pypi.debian.net/astroid/astroid-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))
\ No newline at end of file
diff -Nru astroid-1.0.1/exceptions.py astroid-1.3.8/exceptions.py
--- astroid-1.0.1/exceptions.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/exceptions.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,51 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""this module contains exceptions used in the astroid library
-
-"""
-
-__doctype__ = "restructuredtext en"
-
-class AstroidError(Exception):
- """base exception class for all astroid related exceptions"""
-
-class AstroidBuildingException(AstroidError):
- """exception class when we are unable to build an astroid representation"""
-
-class ResolveError(AstroidError):
- """base class of astroid resolution/inference error"""
-
-class NotFoundError(ResolveError):
- """raised when we are unable to resolve a name"""
-
-class InferenceError(ResolveError):
- """raised when we are unable to infer a node"""
-
-class UseInferenceDefault(Exception):
- """exception to be raised in custom inference function to indicate that it
- should go back to the default behaviour
- """
-
-class UnresolvableName(InferenceError):
- """raised when we are unable to resolve a name"""
-
-class NoDefault(AstroidError):
- """raised by function's `default_value` method when an argument has
- no default value
- """
-
diff -Nru astroid-1.0.1/inference.py astroid-1.3.8/inference.py
--- astroid-1.0.1/inference.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/inference.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,388 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""this module contains a set of functions to handle inference on astroid trees
-"""
-
-__doctype__ = "restructuredtext en"
-
-from itertools import chain
-
-from astroid import nodes
-
-from astroid.manager import AstroidManager
-from astroid.exceptions import (AstroidError,
- InferenceError, NoDefault, NotFoundError, UnresolvableName)
-from astroid.bases import YES, Instance, InferenceContext, \
- _infer_stmts, copy_context, path_wrapper, raise_if_nothing_infered
-from astroid.protocols import _arguments_infer_argname
-
-MANAGER = AstroidManager()
-
-
-class CallContext:
- """when inferring a function call, this class is used to remember values
- given as argument
- """
- def __init__(self, args, starargs, dstarargs):
- self.args = []
- self.nargs = {}
- for arg in args:
- if isinstance(arg, nodes.Keyword):
- self.nargs[arg.arg] = arg.value
- else:
- self.args.append(arg)
- self.starargs = starargs
- self.dstarargs = dstarargs
-
- def infer_argument(self, funcnode, name, context):
- """infer a function argument value according to the call context"""
- # 1. search in named keywords
- try:
- return self.nargs[name].infer(context)
- except KeyError:
- # Function.args.args can be None in astroid (means that we don't have
- # information on argnames)
- argindex = funcnode.args.find_argname(name)[0]
- if argindex is not None:
- # 2. first argument of instance/class method
- if argindex == 0 and funcnode.type in ('method', 'classmethod'):
- if context.boundnode is not None:
- boundnode = context.boundnode
- else:
- # XXX can do better ?
- boundnode = funcnode.parent.frame()
- if funcnode.type == 'method':
- if not isinstance(boundnode, Instance):
- boundnode = Instance(boundnode)
- return iter((boundnode,))
- if funcnode.type == 'classmethod':
- return iter((boundnode,))
- # 2. search arg index
- try:
- return self.args[argindex].infer(context)
- except IndexError:
- pass
- # 3. search in *args (.starargs)
- if self.starargs is not None:
- its = []
- for infered in self.starargs.infer(context):
- if infered is YES:
- its.append((YES,))
- continue
- try:
- its.append(infered.getitem(argindex, context).infer(context))
- except (InferenceError, AttributeError):
- its.append((YES,))
- except (IndexError, TypeError):
- continue
- if its:
- return chain(*its)
- # 4. XXX search in **kwargs (.dstarargs)
- if self.dstarargs is not None:
- its = []
- for infered in self.dstarargs.infer(context):
- if infered is YES:
- its.append((YES,))
- continue
- try:
- its.append(infered.getitem(name, context).infer(context))
- except (InferenceError, AttributeError):
- its.append((YES,))
- except (IndexError, TypeError):
- continue
- if its:
- return chain(*its)
- # 5. */** argument, (Tuple or Dict)
- if name == funcnode.args.vararg:
- return iter((nodes.const_factory(())))
- if name == funcnode.args.kwarg:
- return iter((nodes.const_factory({})))
- # 6. return default value if any
- try:
- return funcnode.args.default_value(name).infer(context)
- except NoDefault:
- raise InferenceError(name)
-
-
-# .infer method ###############################################################
-
-
-def infer_end(self, context=None):
- """inference's end for node such as Module, Class, Function, Const...
- """
- yield self
-nodes.Module._infer = infer_end
-nodes.Class._infer = infer_end
-nodes.Function._infer = infer_end
-nodes.Lambda._infer = infer_end
-nodes.Const._infer = infer_end
-nodes.List._infer = infer_end
-nodes.Tuple._infer = infer_end
-nodes.Dict._infer = infer_end
-nodes.Set._infer = infer_end
-
-def infer_name(self, context=None):
- """infer a Name: use name lookup rules"""
- frame, stmts = self.lookup(self.name)
- if not stmts:
- raise UnresolvableName(self.name)
- context = context.clone()
- context.lookupname = self.name
- return _infer_stmts(stmts, context, frame)
-nodes.Name._infer = path_wrapper(infer_name)
-nodes.AssName.infer_lhs = infer_name # won't work with a path wrapper
-
-
-def infer_callfunc(self, context=None):
- """infer a CallFunc node by trying to guess what the function returns"""
- callcontext = context.clone()
- callcontext.callcontext = CallContext(self.args, self.starargs, self.kwargs)
- callcontext.boundnode = None
- for callee in self.func.infer(context):
- if callee is YES:
- yield callee
- continue
- try:
- if hasattr(callee, 'infer_call_result'):
- for infered in callee.infer_call_result(self, callcontext):
- yield infered
- except InferenceError:
- ## XXX log error ?
- continue
-nodes.CallFunc._infer = path_wrapper(raise_if_nothing_infered(infer_callfunc))
-
-
-def infer_import(self, context=None, asname=True):
- """infer an Import node: return the imported module/object"""
- name = context.lookupname
- if name is None:
- raise InferenceError()
- if asname:
- yield self.do_import_module(self.real_name(name))
- else:
- yield self.do_import_module(name)
-nodes.Import._infer = path_wrapper(infer_import)
-
-def infer_name_module(self, name):
- context = InferenceContext()
- context.lookupname = name
- return self.infer(context, asname=False)
-nodes.Import.infer_name_module = infer_name_module
-
-
-def infer_from(self, context=None, asname=True):
- """infer a From nodes: return the imported module/object"""
- name = context.lookupname
- if name is None:
- raise InferenceError()
- if asname:
- name = self.real_name(name)
- module = self.do_import_module(self.modname)
- try:
- context = copy_context(context)
- context.lookupname = name
- return _infer_stmts(module.getattr(name, ignore_locals=module is self.root()), context)
- except NotFoundError:
- raise InferenceError(name)
-nodes.From._infer = path_wrapper(infer_from)
-
-
-def infer_getattr(self, context=None):
- """infer a Getattr node by using getattr on the associated object"""
- #context = context.clone()
- for owner in self.expr.infer(context):
- if owner is YES:
- yield owner
- continue
- try:
- context.boundnode = owner
- for obj in owner.igetattr(self.attrname, context):
- yield obj
- context.boundnode = None
- except (NotFoundError, InferenceError):
- context.boundnode = None
- except AttributeError:
- # XXX method / function
- context.boundnode = None
-nodes.Getattr._infer = path_wrapper(raise_if_nothing_infered(infer_getattr))
-nodes.AssAttr.infer_lhs = raise_if_nothing_infered(infer_getattr) # # won't work with a path wrapper
-
-
-def infer_global(self, context=None):
- if context.lookupname is None:
- raise InferenceError()
- try:
- return _infer_stmts(self.root().getattr(context.lookupname), context)
- except NotFoundError:
- raise InferenceError()
-nodes.Global._infer = path_wrapper(infer_global)
-
-
-def infer_subscript(self, context=None):
- """infer simple subscription such as [1,2,3][0] or (1,2,3)[-1]"""
- value = self.value.infer(context).next()
- if value is YES:
- yield YES
- return
-
- index = self.slice.infer(context).next()
- if index is YES:
- yield YES
- return
-
- if isinstance(index, nodes.Const):
- try:
- assigned = value.getitem(index.value, context)
- except AttributeError:
- raise InferenceError()
- except (IndexError, TypeError):
- yield YES
- return
- for infered in assigned.infer(context):
- yield infered
- else:
- raise InferenceError()
-nodes.Subscript._infer = path_wrapper(infer_subscript)
-nodes.Subscript.infer_lhs = raise_if_nothing_infered(infer_subscript)
-
-
-UNARY_OP_METHOD = {'+': '__pos__',
- '-': '__neg__',
- '~': '__invert__',
- 'not': None, # XXX not '__nonzero__'
- }
-
-def infer_unaryop(self, context=None):
- for operand in self.operand.infer(context):
- try:
- yield operand.infer_unary_op(self.op)
- except TypeError:
- continue
- except AttributeError:
- meth = UNARY_OP_METHOD[self.op]
- if meth is None:
- yield YES
- else:
- try:
- # XXX just suppose if the type implement meth, returned type
- # will be the same
- operand.getattr(meth)
- yield operand
- except GeneratorExit:
- raise
- except:
- yield YES
-nodes.UnaryOp._infer = path_wrapper(infer_unaryop)
-
-
-BIN_OP_METHOD = {'+': '__add__',
- '-': '__sub__',
- '/': '__div__',
- '//': '__floordiv__',
- '*': '__mul__',
- '**': '__power__',
- '%': '__mod__',
- '&': '__and__',
- '|': '__or__',
- '^': '__xor__',
- '<<': '__lshift__',
- '>>': '__rshift__',
- }
-
-def _infer_binop(operator, operand1, operand2, context, failures=None):
- if operand1 is YES:
- yield operand1
- return
- try:
- for valnode in operand1.infer_binary_op(operator, operand2, context):
- yield valnode
- except AttributeError:
- try:
- # XXX just suppose if the type implement meth, returned type
- # will be the same
- operand1.getattr(BIN_OP_METHOD[operator])
- yield operand1
- except:
- if failures is None:
- yield YES
- else:
- failures.append(operand1)
-
-def infer_binop(self, context=None):
- failures = []
- for lhs in self.left.infer(context):
- for val in _infer_binop(self.op, lhs, self.right, context, failures):
- yield val
- for lhs in failures:
- for rhs in self.right.infer(context):
- for val in _infer_binop(self.op, rhs, lhs, context):
- yield val
-nodes.BinOp._infer = path_wrapper(infer_binop)
-
-
-def infer_arguments(self, context=None):
- name = context.lookupname
- if name is None:
- raise InferenceError()
- return _arguments_infer_argname(self, name, context)
-nodes.Arguments._infer = infer_arguments
-
-
-def infer_ass(self, context=None):
- """infer a AssName/AssAttr: need to inspect the RHS part of the
- assign node
- """
- stmt = self.statement()
- if isinstance(stmt, nodes.AugAssign):
- return stmt.infer(context)
- stmts = list(self.assigned_stmts(context=context))
- return _infer_stmts(stmts, context)
-nodes.AssName._infer = path_wrapper(infer_ass)
-nodes.AssAttr._infer = path_wrapper(infer_ass)
-
-def infer_augassign(self, context=None):
- failures = []
- for lhs in self.target.infer_lhs(context):
- for val in _infer_binop(self.op, lhs, self.value, context, failures):
- yield val
- for lhs in failures:
- for rhs in self.value.infer(context):
- for val in _infer_binop(self.op, rhs, lhs, context):
- yield val
-nodes.AugAssign._infer = path_wrapper(infer_augassign)
-
-
-# no infer method on DelName and DelAttr (expected InferenceError)
-
-
-def infer_empty_node(self, context=None):
- if not self.has_underlying_object():
- yield YES
- else:
- try:
- for infered in MANAGER.infer_ast_from_something(self.object,
- context=context):
- yield infered
- except AstroidError:
- yield YES
-nodes.EmptyNode._infer = path_wrapper(infer_empty_node)
-
-
-def infer_index(self, context=None):
- return self.value.infer(context)
-nodes.Index._infer = infer_index
diff -Nru astroid-1.0.1/__init__.py astroid-1.3.8/__init__.py
--- astroid-1.0.1/__init__.py 2013-07-29 15:04:24.000000000 +0000
+++ astroid-1.3.8/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,118 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""Python Abstract Syntax Tree New Generation
-
-The aim of this module is to provide a common base representation of
-python source code for projects such as pychecker, pyreverse,
-pylint... Well, actually the development of this library is essentially
-governed by pylint's needs.
-
-It extends class defined in the python's _ast module with some
-additional methods and attributes. Instance attributes are added by a
-builder object, which can either generate extended ast (let's call
-them astroid ;) by visiting an existent ast tree or by inspecting living
-object. Methods are added by monkey patching ast classes.
-
-Main modules are:
-
-* nodes and scoped_nodes for more information about methods and
- attributes added to different node classes
-
-* the manager contains a high level object to get astroid trees from
- source files and living objects. It maintains a cache of previously
- constructed tree for quick access
-
-* builder contains the class responsible to build astroid trees
-"""
-__doctype__ = "restructuredtext en"
-
-import sys
-import re
-from operator import attrgetter
-
-# WARNING: internal imports order matters !
-
-# make all exception classes accessible from astroid package
-from astroid.exceptions import *
-
-# make all node classes accessible from astroid package
-from astroid.nodes import *
-
-# trigger extra monkey-patching
-from astroid import inference
-
-# more stuff available
-from astroid import raw_building
-from astroid.bases import YES, Instance, BoundMethod, UnboundMethod
-from astroid.node_classes import are_exclusive, unpack_infer
-from astroid.scoped_nodes import builtin_lookup
-
-# make a manager instance (borg) as well as Project and Package classes
-# accessible from astroid package
-from astroid.manager import AstroidManager, Project
-MANAGER = AstroidManager()
-del AstroidManager
-
-# transform utilities (filters and decorator)
-
-class AsStringRegexpPredicate(object):
- """Class to be used as predicate that may be given to `register_transform`
-
- First argument is a regular expression that will be searched against the `as_string`
- representation of the node onto which it's applied.
-
- If specified, the second argument is an `attrgetter` expression that will be
- applied on the node first to get the actual node on which `as_string` should
- be called.
- """
- def __init__(self, regexp, expression=None):
- self.regexp = re.compile(regexp)
- self.expression = expression
-
- def __call__(self, node):
- if self.expression is not None:
- node = attrgetter(self.expression)(node)
- return self.regexp.search(node.as_string())
-
-def inference_tip(infer_function):
- """Given an instance specific inference function, return a function to be
- given to MANAGER.register_transform to set this inference function.
-
- Typical usage
-
- .. sourcecode:: python
-
- MANAGER.register_transform(CallFunc, inference_tip(infer_named_tuple),
- AsStringRegexpPredicate('namedtuple', 'func'))
- """
- def transform(node, infer_function=infer_function):
- node._explicit_inference = infer_function
- return node
- return transform
-
-# load brain plugins
-from os import listdir
-from os.path import join, dirname
-BRAIN_MODULES_DIR = join(dirname(__file__), 'brain')
-if BRAIN_MODULES_DIR not in sys.path:
- # add it to the end of the list so user path take precedence
- sys.path.append(BRAIN_MODULES_DIR)
-# load modules in this directory
-for module in listdir(BRAIN_MODULES_DIR):
- if module.endswith('.py'):
- __import__(module[:-3])
diff -Nru astroid-1.0.1/inspector.py astroid-1.3.8/inspector.py
--- astroid-1.0.1/inspector.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/inspector.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,275 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""visitor doing some postprocessing on the astroid tree.
-Try to resolve definitions (namespace) dictionary, relationship...
-
-This module has been imported from pyreverse
-"""
-
-__docformat__ = "restructuredtext en"
-
-from os.path import dirname
-
-from logilab.common.modutils import get_module_part, is_relative, \
- is_standard_module
-
-import astroid
-from astroid.exceptions import InferenceError
-from astroid.utils import LocalsVisitor
-
-class IdGeneratorMixIn:
- """
- Mixin adding the ability to generate integer uid
- """
- def __init__(self, start_value=0):
- self.id_count = start_value
-
- def init_counter(self, start_value=0):
- """init the id counter
- """
- self.id_count = start_value
-
- def generate_id(self):
- """generate a new identifier
- """
- self.id_count += 1
- return self.id_count
-
-
-class Linker(IdGeneratorMixIn, LocalsVisitor):
- """
- walk on the project tree and resolve relationships.
-
- According to options the following attributes may be added to visited nodes:
-
- * uid,
- a unique identifier for the node (on astroid.Project, astroid.Module,
- astroid.Class and astroid.locals_type). Only if the linker has been instantiated
- with tag=True parameter (False by default).
-
- * Function
- a mapping from locals names to their bounded value, which may be a
- constant like a string or an integer, or an astroid node (on astroid.Module,
- astroid.Class and astroid.Function).
-
- * instance_attrs_type
- as locals_type but for klass member attributes (only on astroid.Class)
-
- * implements,
- list of implemented interface _objects_ (only on astroid.Class nodes)
- """
-
- def __init__(self, project, inherited_interfaces=0, tag=False):
- IdGeneratorMixIn.__init__(self)
- LocalsVisitor.__init__(self)
- # take inherited interface in consideration or not
- self.inherited_interfaces = inherited_interfaces
- # tag nodes or not
- self.tag = tag
- # visited project
- self.project = project
-
-
- def visit_project(self, node):
- """visit an astroid.Project node
-
- * optionally tag the node with a unique id
- """
- if self.tag:
- node.uid = self.generate_id()
- for module in node.modules:
- self.visit(module)
-
- def visit_package(self, node):
- """visit an astroid.Package node
-
- * optionally tag the node with a unique id
- """
- if self.tag:
- node.uid = self.generate_id()
- for subelmt in node.values():
- self.visit(subelmt)
-
- def visit_module(self, node):
- """visit an astroid.Module node
-
- * set the locals_type mapping
- * set the depends mapping
- * optionally tag the node with a unique id
- """
- if hasattr(node, 'locals_type'):
- return
- node.locals_type = {}
- node.depends = []
- if self.tag:
- node.uid = self.generate_id()
-
- def visit_class(self, node):
- """visit an astroid.Class node
-
- * set the locals_type and instance_attrs_type mappings
- * set the implements list and build it
- * optionally tag the node with a unique id
- """
- if hasattr(node, 'locals_type'):
- return
- node.locals_type = {}
- if self.tag:
- node.uid = self.generate_id()
- # resolve ancestors
- for baseobj in node.ancestors(recurs=False):
- specializations = getattr(baseobj, 'specializations', [])
- specializations.append(node)
- baseobj.specializations = specializations
- # resolve instance attributes
- node.instance_attrs_type = {}
- for assattrs in node.instance_attrs.values():
- for assattr in assattrs:
- self.handle_assattr_type(assattr, node)
- # resolve implemented interface
- try:
- node.implements = list(node.interfaces(self.inherited_interfaces))
- except InferenceError:
- node.implements = ()
-
- def visit_function(self, node):
- """visit an astroid.Function node
-
- * set the locals_type mapping
- * optionally tag the node with a unique id
- """
- if hasattr(node, 'locals_type'):
- return
- node.locals_type = {}
- if self.tag:
- node.uid = self.generate_id()
-
- link_project = visit_project
- link_module = visit_module
- link_class = visit_class
- link_function = visit_function
-
- def visit_assname(self, node):
- """visit an astroid.AssName node
-
- handle locals_type
- """
- # avoid double parsing done by different Linkers.visit
- # running over the same project:
- if hasattr(node, '_handled'):
- return
- node._handled = True
- if node.name in node.frame():
- frame = node.frame()
- else:
- # the name has been defined as 'global' in the frame and belongs
- # there. Btw the frame is not yet visited as the name is in the
- # root locals; the frame hence has no locals_type attribute
- frame = node.root()
- try:
- values = node.infered()
- try:
- already_infered = frame.locals_type[node.name]
- for valnode in values:
- if not valnode in already_infered:
- already_infered.append(valnode)
- except KeyError:
- frame.locals_type[node.name] = values
- except astroid.InferenceError:
- pass
-
- def handle_assattr_type(self, node, parent):
- """handle an astroid.AssAttr node
-
- handle instance_attrs_type
- """
- try:
- values = list(node.infer())
- try:
- already_infered = parent.instance_attrs_type[node.attrname]
- for valnode in values:
- if not valnode in already_infered:
- already_infered.append(valnode)
- except KeyError:
- parent.instance_attrs_type[node.attrname] = values
- except astroid.InferenceError:
- pass
-
- def visit_import(self, node):
- """visit an astroid.Import node
-
- resolve module dependencies
- """
- context_file = node.root().file
- for name in node.names:
- relative = is_relative(name[0], context_file)
- self._imported_module(node, name[0], relative)
-
-
- def visit_from(self, node):
- """visit an astroid.From node
-
- resolve module dependencies
- """
- basename = node.modname
- context_file = node.root().file
- if context_file is not None:
- relative = is_relative(basename, context_file)
- else:
- relative = False
- for name in node.names:
- if name[0] == '*':
- continue
- # analyze dependencies
- fullname = '%s.%s' % (basename, name[0])
- if fullname.find('.') > -1:
- try:
- # XXX: don't use get_module_part, missing package precedence
- fullname = get_module_part(fullname, context_file)
- except ImportError:
- continue
- if fullname != basename:
- self._imported_module(node, fullname, relative)
-
-
- def compute_module(self, context_name, mod_path):
- """return true if the module should be added to dependencies"""
- package_dir = dirname(self.project.path)
- if context_name == mod_path:
- return 0
- elif is_standard_module(mod_path, (package_dir,)):
- return 1
- return 0
-
- # protected methods ########################################################
-
- def _imported_module(self, node, mod_path, relative):
- """notify an imported module, used to analyze dependencies
- """
- module = node.root()
- context_name = module.name
- if relative:
- mod_path = '%s.%s' % ('.'.join(context_name.split('.')[:-1]),
- mod_path)
- if self.compute_module(context_name, mod_path):
- # handle dependencies
- if not hasattr(module, 'depends'):
- module.depends = []
- mod_paths = module.depends
- if not mod_path in mod_paths:
- mod_paths.append(mod_path)
diff -Nru astroid-1.0.1/manager.py astroid-1.3.8/manager.py
--- astroid-1.0.1/manager.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/manager.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,303 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""astroid manager: avoid multiple astroid build of a same module when
-possible by providing a class responsible to get astroid representation
-from various source and using a cache of built modules)
-"""
-
-__docformat__ = "restructuredtext en"
-
-import os
-from os.path import dirname, join, isdir, exists
-
-from logilab.common.modutils import NoSourceFile, is_python_source, \
- file_from_modpath, load_module_from_name, modpath_from_file, \
- get_module_files, get_source_file, zipimport
-from logilab.common.configuration import OptionsProviderMixIn
-
-from astroid.exceptions import AstroidBuildingException
-
-def astroid_wrapper(func, modname):
- """wrapper to give to AstroidManager.project_from_files"""
- print 'parsing %s...' % modname
- try:
- return func(modname)
- except AstroidBuildingException, exc:
- print exc
- except Exception, exc:
- import traceback
- traceback.print_exc()
-
-def _silent_no_wrap(func, modname):
- """silent wrapper that doesn't do anything; can be used for tests"""
- return func(modname)
-
-def safe_repr(obj):
- try:
- return repr(obj)
- except:
- return '???'
-
-
-
-class AstroidManager(OptionsProviderMixIn):
- """the astroid manager, responsible to build astroid from files
- or modules.
-
- Use the Borg pattern.
- """
-
- name = 'astroid loader'
- options = (("ignore",
- {'type' : "csv", 'metavar' : "",
- 'dest' : "black_list", "default" : ('CVS',),
- 'help' : "add (may be a directory) to the black list\
-. It should be a base name, not a path. You may set this option multiple times\
-."}),
- ("project",
- {'default': "No Name", 'type' : 'string', 'short': 'p',
- 'metavar' : '',
- 'help' : 'set the project name.'}),
- )
- brain = {}
- def __init__(self):
- self.__dict__ = AstroidManager.brain
- if not self.__dict__:
- OptionsProviderMixIn.__init__(self)
- self.load_defaults()
- # NOTE: cache entries are added by the [re]builder
- self.astroid_cache = {}
- self._mod_file_cache = {}
- self.transforms = {}
-
- def ast_from_file(self, filepath, modname=None, fallback=True, source=False):
- """given a module name, return the astroid object"""
- try:
- filepath = get_source_file(filepath, include_no_ext=True)
- source = True
- except NoSourceFile:
- pass
- if modname is None:
- try:
- modname = '.'.join(modpath_from_file(filepath))
- except ImportError:
- modname = filepath
- if modname in self.astroid_cache:
- return self.astroid_cache[modname]
- if source:
- from astroid.builder import AstroidBuilder
- return AstroidBuilder(self).file_build(filepath, modname)
- elif fallback and modname:
- return self.ast_from_module_name(modname)
- raise AstroidBuildingException('unable to get astroid for file %s' %
- filepath)
-
- def ast_from_module_name(self, modname, context_file=None):
- """given a module name, return the astroid object"""
- if modname in self.astroid_cache:
- return self.astroid_cache[modname]
- if modname == '__main__':
- from astroid.builder import AstroidBuilder
- return AstroidBuilder(self).string_build('', modname)
- old_cwd = os.getcwd()
- if context_file:
- os.chdir(dirname(context_file))
- try:
- filepath = self.file_from_module_name(modname, context_file)
- if filepath is not None and not is_python_source(filepath):
- module = self.zip_import_data(filepath)
- if module is not None:
- return module
- if filepath is None or not is_python_source(filepath):
- try:
- module = load_module_from_name(modname)
- except Exception, ex:
- msg = 'Unable to load module %s (%s)' % (modname, ex)
- raise AstroidBuildingException(msg)
- return self.ast_from_module(module, modname)
- return self.ast_from_file(filepath, modname, fallback=False)
- finally:
- os.chdir(old_cwd)
-
- def zip_import_data(self, filepath):
- if zipimport is None:
- return None
- from astroid.builder import AstroidBuilder
- builder = AstroidBuilder(self)
- for ext in ('.zip', '.egg'):
- try:
- eggpath, resource = filepath.rsplit(ext + '/', 1)
- except ValueError:
- continue
- try:
- importer = zipimport.zipimporter(eggpath + ext)
- zmodname = resource.replace('/', '.')
- if importer.is_package(resource):
- zmodname = zmodname + '.__init__'
- module = builder.string_build(importer.get_source(resource),
- zmodname, filepath)
- return module
- except:
- continue
- return None
-
- def file_from_module_name(self, modname, contextfile):
- try:
- value = self._mod_file_cache[(modname, contextfile)]
- except KeyError:
- try:
- value = file_from_modpath(modname.split('.'),
- context_file=contextfile)
- except ImportError, ex:
- msg = 'Unable to load module %s (%s)' % (modname, ex)
- value = AstroidBuildingException(msg)
- self._mod_file_cache[(modname, contextfile)] = value
- if isinstance(value, AstroidBuildingException):
- raise value
- return value
-
- def ast_from_module(self, module, modname=None):
- """given an imported module, return the astroid object"""
- modname = modname or module.__name__
- if modname in self.astroid_cache:
- return self.astroid_cache[modname]
- try:
- # some builtin modules don't have __file__ attribute
- filepath = module.__file__
- if is_python_source(filepath):
- return self.ast_from_file(filepath, modname)
- except AttributeError:
- pass
- from astroid.builder import AstroidBuilder
- return AstroidBuilder(self).module_build(module, modname)
-
- def ast_from_class(self, klass, modname=None):
- """get astroid for the given class"""
- if modname is None:
- try:
- modname = klass.__module__
- except AttributeError:
- raise AstroidBuildingException(
- 'Unable to get module for class %s' % safe_repr(klass))
- modastroid = self.ast_from_module_name(modname)
- return modastroid.getattr(klass.__name__)[0] # XXX
-
-
- def infer_ast_from_something(self, obj, context=None):
- """infer astroid for the given class"""
- if hasattr(obj, '__class__') and not isinstance(obj, type):
- klass = obj.__class__
- else:
- klass = obj
- try:
- modname = klass.__module__
- except AttributeError:
- raise AstroidBuildingException(
- 'Unable to get module for %s' % safe_repr(klass))
- except Exception, ex:
- raise AstroidBuildingException(
- 'Unexpected error while retrieving module for %s: %s'
- % (safe_repr(klass), ex))
- try:
- name = klass.__name__
- except AttributeError:
- raise AstroidBuildingException(
- 'Unable to get name for %s' % safe_repr(klass))
- except Exception, ex:
- raise AstroidBuildingException(
- 'Unexpected error while retrieving name for %s: %s'
- % (safe_repr(klass), ex))
- # take care, on living object __module__ is regularly wrong :(
- modastroid = self.ast_from_module_name(modname)
- if klass is obj:
- for infered in modastroid.igetattr(name, context):
- yield infered
- else:
- for infered in modastroid.igetattr(name, context):
- yield infered.instanciate_class()
-
- def project_from_files(self, files, func_wrapper=astroid_wrapper,
- project_name=None, black_list=None):
- """return a Project from a list of files or modules"""
- # build the project representation
- project_name = project_name or self.config.project
- black_list = black_list or self.config.black_list
- project = Project(project_name)
- for something in files:
- if not exists(something):
- fpath = file_from_modpath(something.split('.'))
- elif isdir(something):
- fpath = join(something, '__init__.py')
- else:
- fpath = something
- astroid = func_wrapper(self.ast_from_file, fpath)
- if astroid is None:
- continue
- # XXX why is first file defining the project.path ?
- project.path = project.path or astroid.file
- project.add_module(astroid)
- base_name = astroid.name
- # recurse in package except if __init__ was explicitly given
- if astroid.package and something.find('__init__') == -1:
- # recurse on others packages / modules if this is a package
- for fpath in get_module_files(dirname(astroid.file),
- black_list):
- astroid = func_wrapper(self.ast_from_file, fpath)
- if astroid is None or astroid.name == base_name:
- continue
- project.add_module(astroid)
- return project
-
- def register_transform(self, node_class, transform, predicate=None):
- """Register `transform(node)` function to be applied on the given
- Astroid's `node_class` if `predicate` is None or return a true value
- when called with the node as argument.
-
- The transform function may return a value which is then used to
- substitute the original node in the tree.
- """
- self.transforms.setdefault(node_class, []).append( (transform, predicate) )
-
-class Project:
- """a project handle a set of modules / packages"""
- def __init__(self, name=''):
- self.name = name
- self.path = None
- self.modules = []
- self.locals = {}
- self.__getitem__ = self.locals.__getitem__
- self.__iter__ = self.locals.__iter__
- self.values = self.locals.values
- self.keys = self.locals.keys
- self.items = self.locals.items
-
- def add_module(self, node):
- self.locals[node.name] = node
- self.modules.append(node)
-
- def get_module(self, name):
- return self.locals[name]
-
- def get_children(self):
- return self.modules
-
- def __repr__(self):
- return '' % (self.name, id(self),
- len(self.modules))
-
-
diff -Nru astroid-1.0.1/MANIFEST.in astroid-1.3.8/MANIFEST.in
--- astroid-1.0.1/MANIFEST.in 2013-07-29 15:04:24.000000000 +0000
+++ astroid-1.3.8/MANIFEST.in 2015-03-09 22:00:27.000000000 +0000
@@ -1,9 +1,7 @@
include ChangeLog
-include README*
+include README
include COPYING
include COPYING.LESSER
-include test/fulltest.sh
-recursive-include test/data *.py *.zip *.egg
-recursive-include test/data2 *.py
-recursive-include test/regrtest_data *.py
-recursive-include brain *.py
+include tox.ini
+recursive-include astroid/tests/testdata *.py *.zip *.egg
+recursive-include astroid/brain *.py
diff -Nru astroid-1.0.1/mixins.py astroid-1.3.8/mixins.py
--- astroid-1.0.1/mixins.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/mixins.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,122 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""This module contains some mixins for the different nodes.
-"""
-
-from astroid.exceptions import (AstroidBuildingException, InferenceError,
- NotFoundError)
-
-
-class BlockRangeMixIn(object):
- """override block range """
- def set_line_info(self, lastchild):
- self.fromlineno = self.lineno
- self.tolineno = lastchild.tolineno
- self.blockstart_tolineno = self._blockstart_toline()
-
- def _elsed_block_range(self, lineno, orelse, last=None):
- """handle block line numbers range for try/finally, for, if and while
- statements
- """
- if lineno == self.fromlineno:
- return lineno, lineno
- if orelse:
- if lineno >= orelse[0].fromlineno:
- return lineno, orelse[-1].tolineno
- return lineno, orelse[0].fromlineno - 1
- return lineno, last or self.tolineno
-
-
-class FilterStmtsMixin(object):
- """Mixin for statement filtering and assignment type"""
-
- def _get_filtered_stmts(self, _, node, _stmts, mystmt):
- """method used in _filter_stmts to get statemtents and trigger break"""
- if self.statement() is mystmt:
- # original node's statement is the assignment, only keep
- # current node (gen exp, list comp)
- return [node], True
- return _stmts, False
-
- def ass_type(self):
- return self
-
-
-class AssignTypeMixin(object):
-
- def ass_type(self):
- return self
-
- def _get_filtered_stmts(self, lookup_node, node, _stmts, mystmt):
- """method used in filter_stmts"""
- if self is mystmt:
- return _stmts, True
- if self.statement() is mystmt:
- # original node's statement is the assignment, only keep
- # current node (gen exp, list comp)
- return [node], True
- return _stmts, False
-
-
-class ParentAssignTypeMixin(AssignTypeMixin):
-
- def ass_type(self):
- return self.parent.ass_type()
-
-
-class FromImportMixIn(FilterStmtsMixin):
- """MixIn for From and Import Nodes"""
-
- def _infer_name(self, frame, name):
- return name
-
- def do_import_module(self, modname):
- """return the ast for a module whose name is imported by
- """
- # handle special case where we are on a package node importing a module
- # using the same name as the package, which may end in an infinite loop
- # on relative imports
- # XXX: no more needed ?
- mymodule = self.root()
- level = getattr(self, 'level', None) # Import as no level
- # XXX we should investigate deeper if we really want to check
- # importing itself: modname and mymodule.name be relative or absolute
- if mymodule.relative_to_absolute_name(modname, level) == mymodule.name:
- # FIXME: we used to raise InferenceError here, but why ?
- return mymodule
- try:
- return mymodule.import_module(modname, level=level)
- except AstroidBuildingException:
- raise InferenceError(modname)
- except SyntaxError, ex:
- raise InferenceError(str(ex))
-
- def real_name(self, asname):
- """get name from 'as' name"""
- for name, _asname in self.names:
- if name == '*':
- return asname
- if not _asname:
- name = name.split('.', 1)[0]
- _asname = name
- if asname == _asname:
- return name
- raise NotFoundError(asname)
-
-
-
diff -Nru astroid-1.0.1/node_classes.py astroid-1.3.8/node_classes.py
--- astroid-1.0.1/node_classes.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/node_classes.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,925 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""Module for some node classes. More nodes in scoped_nodes.py
-"""
-
-import sys
-
-from astroid.exceptions import NoDefault
-from astroid.bases import (NodeNG, Statement, Instance, InferenceContext,
- _infer_stmts, YES, BUILTINS)
-from astroid.mixins import BlockRangeMixIn, AssignTypeMixin, \
- ParentAssignTypeMixin, FromImportMixIn
-
-
-def unpack_infer(stmt, context=None):
- """recursively generate nodes inferred by the given statement.
- If the inferred value is a list or a tuple, recurse on the elements
- """
- if isinstance(stmt, (List, Tuple)):
- for elt in stmt.elts:
- for infered_elt in unpack_infer(elt, context):
- yield infered_elt
- return
- # if infered is a final node, return it and stop
- infered = stmt.infer(context).next()
- if infered is stmt:
- yield infered
- return
- # else, infer recursivly, except YES object that should be returned as is
- for infered in stmt.infer(context):
- if infered is YES:
- yield infered
- else:
- for inf_inf in unpack_infer(infered, context):
- yield inf_inf
-
-
-def are_exclusive(stmt1, stmt2, exceptions=None):
- """return true if the two given statements are mutually exclusive
-
- `exceptions` may be a list of exception names. If specified, discard If
- branches and check one of the statement is in an exception handler catching
- one of the given exceptions.
-
- algorithm :
- 1) index stmt1's parents
- 2) climb among stmt2's parents until we find a common parent
- 3) if the common parent is a If or TryExcept statement, look if nodes are
- in exclusive branches
- """
- # index stmt1's parents
- stmt1_parents = {}
- children = {}
- node = stmt1.parent
- previous = stmt1
- while node:
- stmt1_parents[node] = 1
- children[node] = previous
- previous = node
- node = node.parent
- # climb among stmt2's parents until we find a common parent
- node = stmt2.parent
- previous = stmt2
- while node:
- if node in stmt1_parents:
- # if the common parent is a If or TryExcept statement, look if
- # nodes are in exclusive branches
- if isinstance(node, If) and exceptions is None:
- if (node.locate_child(previous)[1]
- is not node.locate_child(children[node])[1]):
- return True
- elif isinstance(node, TryExcept):
- c2attr, c2node = node.locate_child(previous)
- c1attr, c1node = node.locate_child(children[node])
- if c1node is not c2node:
- if ((c2attr == 'body' and c1attr == 'handlers' and children[node].catch(exceptions)) or
- (c2attr == 'handlers' and c1attr == 'body' and previous.catch(exceptions)) or
- (c2attr == 'handlers' and c1attr == 'orelse') or
- (c2attr == 'orelse' and c1attr == 'handlers')):
- return True
- elif c2attr == 'handlers' and c1attr == 'handlers':
- return previous is not children[node]
- return False
- previous = node
- node = node.parent
- return False
-
-
-class LookupMixIn(object):
- """Mixin looking up a name in the right scope
- """
-
- def lookup(self, name):
- """lookup a variable name
-
- return the scope node and the list of assignments associated to the given
- name according to the scope where it has been found (locals, globals or
- builtin)
-
- The lookup is starting from self's scope. 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
- """
- return self.scope().scope_lookup(self, name)
-
- def ilookup(self, name):
- """infered lookup
-
- return an iterator on infered values of the statements returned by
- the lookup method
- """
- frame, stmts = self.lookup(name)
- context = InferenceContext()
- return _infer_stmts(stmts, context, frame)
-
- 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
- assert hasattr(node, 'ass_type'), (node, node.scope(),
- node.scope().locals)
- ass_type = node.ass_type()
-
- if node.has_base(self):
- break
-
- _stmts, done = ass_type._get_filtered_stmts(self, node, _stmts, mystmt)
- if done:
- break
-
- optional_assign = ass_type.optional_assign
- 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, AssName):
- if not optional_assign and stmt.parent is mystmt.parent:
- _stmts = []
- _stmt_parents = []
- elif isinstance(node, DelName):
- _stmts = []
- _stmt_parents = []
- continue
- if not are_exclusive(self, node):
- _stmts.append(node)
- _stmt_parents.append(stmt.parent)
- return _stmts
-
-# Name classes
-
-class AssName(LookupMixIn, ParentAssignTypeMixin, NodeNG):
- """class representing an AssName node"""
-
-
-class DelName(LookupMixIn, ParentAssignTypeMixin, NodeNG):
- """class representing a DelName node"""
-
-
-class Name(LookupMixIn, NodeNG):
- """class representing a Name node"""
-
-
-
-
-##################### node classes ########################################
-
-class Arguments(NodeNG, AssignTypeMixin):
- """class representing an Arguments node"""
- _astroid_fields = ('args', 'defaults', 'kwonlyargs', 'kw_defaults')
- args = None
- defaults = None
- kwonlyargs = None
- kw_defaults = None
-
- def __init__(self, vararg=None, kwarg=None):
- self.vararg = vararg
- self.kwarg = kwarg
-
- def _infer_name(self, frame, name):
- if self.parent is frame:
- return name
- return None
-
- def format_args(self):
- """return arguments formatted as string"""
- result = []
- if self.args:
- result.append(_format_args(self.args, self.defaults))
- if self.vararg:
- result.append('*%s' % self.vararg)
- if self.kwarg:
- result.append('**%s' % self.kwarg)
- if self.kwonlyargs:
- if not self.vararg:
- result.append('*')
- result.append(_format_args(self.kwonlyargs, self.kw_defaults))
- return ', '.join(result)
-
- def default_value(self, argname):
- """return the default value for an argument
-
- :raise `NoDefault`: if there is no default value defined
- """
- i = _find_arg(argname, self.args)[0]
- if i is not None:
- idx = i - (len(self.args) - len(self.defaults))
- if idx >= 0:
- return self.defaults[idx]
- i = _find_arg(argname, self.kwonlyargs)[0]
- if i is not None and self.kw_defaults[i] is not None:
- return self.kw_defaults[i]
- raise NoDefault()
-
- def is_argument(self, name):
- """return True if the name is defined in arguments"""
- if name == self.vararg:
- return True
- if name == self.kwarg:
- return True
- return self.find_argname(name, True)[1] is not None
-
- def find_argname(self, argname, rec=False):
- """return index and Name node with given name"""
- if self.args: # self.args may be None in some cases (builtin function)
- return _find_arg(argname, self.args, rec)
- return None, None
-
- def get_children(self):
- """override get_children to skip over None elements in kw_defaults"""
- for child in super(Arguments, self).get_children():
- if child is not None:
- yield child
-
-
-def _find_arg(argname, args, rec=False):
- for i, arg in enumerate(args):
- if isinstance(arg, Tuple):
- if rec:
- found = _find_arg(argname, arg.elts)
- if found[0] is not None:
- return found
- elif arg.name == argname:
- return i, arg
- return None, None
-
-
-def _format_args(args, defaults=None):
- values = []
- if args is None:
- return ''
- if defaults is not None:
- default_offset = len(args) - len(defaults)
- for i, arg in enumerate(args):
- if isinstance(arg, Tuple):
- values.append('(%s)' % _format_args(arg.elts))
- else:
- values.append(arg.name)
- if defaults is not None and i >= default_offset:
- if defaults[i-default_offset] is not None:
- values[-1] += '=' + defaults[i-default_offset].as_string()
- return ', '.join(values)
-
-
-class AssAttr(NodeNG, ParentAssignTypeMixin):
- """class representing an AssAttr node"""
- _astroid_fields = ('expr',)
- expr = None
-
-class Assert(Statement):
- """class representing an Assert node"""
- _astroid_fields = ('test', 'fail',)
- test = None
- fail = None
-
-class Assign(Statement, AssignTypeMixin):
- """class representing an Assign node"""
- _astroid_fields = ('targets', 'value',)
- targets = None
- value = None
-
-class AugAssign(Statement, AssignTypeMixin):
- """class representing an AugAssign node"""
- _astroid_fields = ('target', 'value',)
- target = None
- value = None
-
-class Backquote(NodeNG):
- """class representing a Backquote node"""
- _astroid_fields = ('value',)
- value = None
-
-class BinOp(NodeNG):
- """class representing a BinOp node"""
- _astroid_fields = ('left', 'right',)
- left = None
- right = None
-
-class BoolOp(NodeNG):
- """class representing a BoolOp node"""
- _astroid_fields = ('values',)
- values = None
-
-class Break(Statement):
- """class representing a Break node"""
-
-
-class CallFunc(NodeNG):
- """class representing a CallFunc node"""
- _astroid_fields = ('func', 'args', 'starargs', 'kwargs')
- func = None
- args = None
- starargs = None
- kwargs = None
-
- def __init__(self):
- self.starargs = None
- self.kwargs = None
-
-class Compare(NodeNG):
- """class representing a Compare node"""
- _astroid_fields = ('left', 'ops',)
- left = None
- ops = None
-
- def get_children(self):
- """override get_children for tuple fields"""
- yield self.left
- for _, comparator in self.ops:
- yield comparator # we don't want the 'op'
-
- def last_child(self):
- """override last_child"""
- # XXX maybe if self.ops:
- return self.ops[-1][1]
- #return self.left
-
-class Comprehension(NodeNG):
- """class representing a Comprehension node"""
- _astroid_fields = ('target', 'iter' ,'ifs')
- target = None
- iter = None
- ifs = None
-
- optional_assign = True
- def ass_type(self):
- return self
-
- def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt):
- """method used in filter_stmts"""
- if self is mystmt:
- if isinstance(lookup_node, (Const, Name)):
- return [lookup_node], True
-
- elif self.statement() is mystmt:
- # original node's statement is the assignment, only keeps
- # current node (gen exp, list comp)
-
- return [node], True
-
- return stmts, False
-
-
-class Const(NodeNG, Instance):
- """represent a constant node like num, str, bool, None, bytes"""
-
- def __init__(self, value=None):
- self.value = value
-
- def getitem(self, index, context=None):
- if isinstance(self.value, basestring):
- return Const(self.value[index])
- raise TypeError('%r (value=%s)' % (self, self.value))
-
- def has_dynamic_getattr(self):
- return False
-
- def itered(self):
- if isinstance(self.value, basestring):
- return self.value
- raise TypeError()
-
- def pytype(self):
- return self._proxied.qname()
-
-
-class Continue(Statement):
- """class representing a Continue node"""
-
-
-class Decorators(NodeNG):
- """class representing a Decorators node"""
- _astroid_fields = ('nodes',)
- nodes = None
-
- def __init__(self, nodes=None):
- self.nodes = nodes
-
- def scope(self):
- # skip the function node to go directly to the upper level scope
- return self.parent.parent.scope()
-
-class DelAttr(NodeNG, ParentAssignTypeMixin):
- """class representing a DelAttr node"""
- _astroid_fields = ('expr',)
- expr = None
-
-
-class Delete(Statement, AssignTypeMixin):
- """class representing a Delete node"""
- _astroid_fields = ('targets',)
- targets = None
-
-
-class Dict(NodeNG, Instance):
- """class representing a Dict node"""
- _astroid_fields = ('items',)
-
- def __init__(self, items=None):
- if items is None:
- self.items = []
- else:
- self.items = [(const_factory(k), const_factory(v))
- for k,v in items.iteritems()]
-
- def pytype(self):
- return '%s.dict' % BUILTINS
-
- def get_children(self):
- """get children of a Dict node"""
- # overrides get_children
- for key, value in self.items:
- yield key
- yield value
-
- def last_child(self):
- """override last_child"""
- if self.items:
- return self.items[-1][1]
- return None
-
- def itered(self):
- return self.items[::2]
-
- def getitem(self, lookup_key, context=None):
- for key, value in self.items:
- for inferedkey in key.infer(context):
- if inferedkey is YES:
- continue
- if isinstance(inferedkey, Const) and inferedkey.value == lookup_key:
- return value
- # This should raise KeyError, but all call sites only catch
- # IndexError. Let's leave it like that for now.
- raise IndexError(lookup_key)
-
-
-class Discard(Statement):
- """class representing a Discard node"""
- _astroid_fields = ('value',)
- value = None
-
-
-class Ellipsis(NodeNG):
- """class representing an Ellipsis node"""
-
-
-class EmptyNode(NodeNG):
- """class representing an EmptyNode node"""
-
-
-class ExceptHandler(Statement, AssignTypeMixin):
- """class representing an ExceptHandler node"""
- _astroid_fields = ('type', 'name', 'body',)
- type = None
- name = None
- body = None
-
- def _blockstart_toline(self):
- if self.name:
- return self.name.tolineno
- elif self.type:
- return self.type.tolineno
- else:
- return self.lineno
-
- def set_line_info(self, lastchild):
- self.fromlineno = self.lineno
- self.tolineno = lastchild.tolineno
- self.blockstart_tolineno = self._blockstart_toline()
-
- def catch(self, exceptions):
- if self.type is None or exceptions is None:
- return True
- for node in self.type.nodes_of_class(Name):
- if node.name in exceptions:
- return True
-
-
-class Exec(Statement):
- """class representing an Exec node"""
- _astroid_fields = ('expr', 'globals', 'locals',)
- expr = None
- globals = None
- locals = None
-
-
-class ExtSlice(NodeNG):
- """class representing an ExtSlice node"""
- _astroid_fields = ('dims',)
- dims = None
-
-class For(BlockRangeMixIn, AssignTypeMixin, Statement):
- """class representing a For node"""
- _astroid_fields = ('target', 'iter', 'body', 'orelse',)
- target = None
- iter = None
- body = None
- orelse = None
-
- optional_assign = True
- def _blockstart_toline(self):
- return self.iter.tolineno
-
-
-class From(FromImportMixIn, Statement):
- """class representing a From node"""
-
- def __init__(self, fromname, names, level=0):
- self.modname = fromname
- self.names = names
- self.level = level
-
-class Getattr(NodeNG):
- """class representing a Getattr node"""
- _astroid_fields = ('expr',)
- expr = None
-
-
-class Global(Statement):
- """class representing a Global node"""
-
- def __init__(self, names):
- self.names = names
-
- def _infer_name(self, frame, name):
- return name
-
-
-class If(BlockRangeMixIn, Statement):
- """class representing an If node"""
- _astroid_fields = ('test', 'body', 'orelse')
- test = None
- body = None
- orelse = None
-
- def _blockstart_toline(self):
- return self.test.tolineno
-
- def block_range(self, lineno):
- """handle block line numbers range for if statements"""
- if lineno == self.body[0].fromlineno:
- return lineno, lineno
- if lineno <= self.body[-1].tolineno:
- return lineno, self.body[-1].tolineno
- return self._elsed_block_range(lineno, self.orelse,
- self.body[0].fromlineno - 1)
-
-
-class IfExp(NodeNG):
- """class representing an IfExp node"""
- _astroid_fields = ('test', 'body', 'orelse')
- test = None
- body = None
- orelse = None
-
-
-class Import(FromImportMixIn, Statement):
- """class representing an Import node"""
-
-
-class Index(NodeNG):
- """class representing an Index node"""
- _astroid_fields = ('value',)
- value = None
-
-
-class Keyword(NodeNG):
- """class representing a Keyword node"""
- _astroid_fields = ('value',)
- value = None
-
-
-class List(NodeNG, Instance, ParentAssignTypeMixin):
- """class representing a List node"""
- _astroid_fields = ('elts',)
-
- def __init__(self, elts=None):
- if elts is None:
- self.elts = []
- else:
- self.elts = [const_factory(e) for e in elts]
-
- def pytype(self):
- return '%s.list' % BUILTINS
-
- def getitem(self, index, context=None):
- return self.elts[index]
-
- def itered(self):
- return self.elts
-
-
-class Nonlocal(Statement):
- """class representing a Nonlocal node"""
-
- def __init__(self, names):
- self.names = names
-
- def _infer_name(self, frame, name):
- return name
-
-
-class Pass(Statement):
- """class representing a Pass node"""
-
-
-class Print(Statement):
- """class representing a Print node"""
- _astroid_fields = ('dest', 'values',)
- dest = None
- values = None
-
-
-class Raise(Statement):
- """class representing a Raise node"""
- exc = None
- if sys.version_info < (3, 0):
- _astroid_fields = ('exc', 'inst', 'tback')
- inst = None
- tback = None
- else:
- _astroid_fields = ('exc', 'cause')
- exc = None
- cause = None
-
- def raises_not_implemented(self):
- if not self.exc:
- return
- for name in self.exc.nodes_of_class(Name):
- if name.name == 'NotImplementedError':
- return True
-
-
-class Return(Statement):
- """class representing a Return node"""
- _astroid_fields = ('value',)
- value = None
-
-
-class Set(NodeNG, Instance, ParentAssignTypeMixin):
- """class representing a Set node"""
- _astroid_fields = ('elts',)
-
- def __init__(self, elts=None):
- if elts is None:
- self.elts = []
- else:
- self.elts = [const_factory(e) for e in elts]
-
- def pytype(self):
- return '%s.set' % BUILTINS
-
- def itered(self):
- return self.elts
-
-
-class Slice(NodeNG):
- """class representing a Slice node"""
- _astroid_fields = ('lower', 'upper', 'step')
- lower = None
- upper = None
- step = None
-
-class Starred(NodeNG, ParentAssignTypeMixin):
- """class representing a Starred node"""
- _astroid_fields = ('value',)
- value = None
-
-
-class Subscript(NodeNG):
- """class representing a Subscript node"""
- _astroid_fields = ('value', 'slice')
- value = None
- slice = None
-
-
-class TryExcept(BlockRangeMixIn, Statement):
- """class representing a TryExcept node"""
- _astroid_fields = ('body', 'handlers', 'orelse',)
- body = None
- handlers = None
- orelse = None
-
- def _infer_name(self, frame, name):
- return name
-
- def _blockstart_toline(self):
- return self.lineno
-
- def block_range(self, lineno):
- """handle block line numbers range for try/except statements"""
- last = None
- for exhandler in self.handlers:
- if exhandler.type and lineno == exhandler.type.fromlineno:
- return lineno, lineno
- if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:
- return lineno, exhandler.body[-1].tolineno
- if last is None:
- last = exhandler.body[0].fromlineno - 1
- return self._elsed_block_range(lineno, self.orelse, last)
-
-
-class TryFinally(BlockRangeMixIn, Statement):
- """class representing a TryFinally node"""
- _astroid_fields = ('body', 'finalbody',)
- body = None
- finalbody = None
-
- def _blockstart_toline(self):
- return self.lineno
-
- def block_range(self, lineno):
- """handle block line numbers range for try/finally statements"""
- child = self.body[0]
- # py2.5 try: except: finally:
- if (isinstance(child, TryExcept) and child.fromlineno == self.fromlineno
- and lineno > self.fromlineno and lineno <= child.tolineno):
- return child.block_range(lineno)
- return self._elsed_block_range(lineno, self.finalbody)
-
-
-class Tuple(NodeNG, Instance, ParentAssignTypeMixin):
- """class representing a Tuple node"""
- _astroid_fields = ('elts',)
-
- def __init__(self, elts=None):
- if elts is None:
- self.elts = []
- else:
- self.elts = [const_factory(e) for e in elts]
-
- def pytype(self):
- return '%s.tuple' % BUILTINS
-
- def getitem(self, index, context=None):
- return self.elts[index]
-
- def itered(self):
- return self.elts
-
-
-class UnaryOp(NodeNG):
- """class representing an UnaryOp node"""
- _astroid_fields = ('operand',)
- operand = None
-
-
-class While(BlockRangeMixIn, Statement):
- """class representing a While node"""
- _astroid_fields = ('test', 'body', 'orelse',)
- test = None
- body = None
- orelse = None
-
- def _blockstart_toline(self):
- return self.test.tolineno
-
- def block_range(self, lineno):
- """handle block line numbers range for for and while statements"""
- return self. _elsed_block_range(lineno, self.orelse)
-
-
-class With(BlockRangeMixIn, AssignTypeMixin, Statement):
- """class representing a With node"""
- _astroid_fields = ('items', 'body')
- items = None
- body = None
-
- def _blockstart_toline(self):
- return self.items[-1][0].tolineno
-
- def get_children(self):
- for expr, var in self.items:
- yield expr
- if var:
- yield var
- for elt in self.body:
- yield elt
-
-class Yield(NodeNG):
- """class representing a Yield node"""
- _astroid_fields = ('value',)
- value = None
-
-# constants ##############################################################
-
-CONST_CLS = {
- list: List,
- tuple: Tuple,
- dict: Dict,
- set: Set,
- type(None): Const,
- }
-
-def _update_const_classes():
- """update constant classes, so the keys of CONST_CLS can be reused"""
- klasses = (bool, int, float, complex, str)
- if sys.version_info < (3, 0):
- klasses += (unicode, long)
- if sys.version_info >= (2, 6):
- klasses += (bytes,)
- for kls in klasses:
- CONST_CLS[kls] = Const
-_update_const_classes()
-
-def const_factory(value):
- """return an astroid node for a python value"""
- # XXX we should probably be stricter here and only consider stuff in
- # CONST_CLS or do better treatment: in case where value is not in CONST_CLS,
- # we should rather recall the builder on this value than returning an empty
- # node (another option being that const_factory shouldn't be called with something
- # not in CONST_CLS)
- assert not isinstance(value, NodeNG)
- try:
- return CONST_CLS[value.__class__](value)
- except (KeyError, AttributeError):
- node = EmptyNode()
- node.object = value
- return node
diff -Nru astroid-1.0.1/nodes.py astroid-1.3.8/nodes.py
--- astroid-1.0.1/nodes.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/nodes.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,73 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""
-on all nodes :
- .is_statement, returning true if the node should be considered as a
- statement node
- .root(), returning the root node of the tree (i.e. a Module)
- .previous_sibling(), returning previous sibling statement node
- .next_sibling(), returning next sibling statement node
- .statement(), returning the first parent node marked as statement node
- .frame(), returning the first node defining a new local scope (i.e.
- Module, Function or Class)
- .set_local(name, node), define an identifier on the first parent frame,
- with the node defining it. This is used by the astroid builder and should not
- be used from out there.
-
-on From and Import :
- .real_name(name),
-
-
-"""
-
-__docformat__ = "restructuredtext en"
-
-from astroid.node_classes import Arguments, AssAttr, Assert, Assign, \
- AssName, AugAssign, Backquote, BinOp, BoolOp, Break, CallFunc, Compare, \
- Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete, \
- Dict, Discard, Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, For, \
- From, Getattr, Global, If, IfExp, Import, Index, Keyword, \
- List, Name, Nonlocal, Pass, Print, Raise, Return, Set, Slice, Starred, Subscript, \
- TryExcept, TryFinally, Tuple, UnaryOp, While, With, Yield, \
- const_factory
-from astroid.scoped_nodes import Module, GenExpr, Lambda, DictComp, \
- ListComp, SetComp, Function, Class
-
-ALL_NODE_CLASSES = (
- Arguments, AssAttr, Assert, Assign, AssName, AugAssign,
- Backquote, BinOp, BoolOp, Break,
- CallFunc, Class, Compare, Comprehension, Const, Continue,
- Decorators, DelAttr, DelName, Delete,
- Dict, DictComp, Discard,
- Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice,
- For, From, Function,
- Getattr, GenExpr, Global,
- If, IfExp, Import, Index,
- Keyword,
- Lambda, List, ListComp,
- Name, Nonlocal,
- Module,
- Pass, Print,
- Raise, Return,
- Set, SetComp, Slice, Starred, Subscript,
- TryExcept, TryFinally, Tuple,
- UnaryOp,
- While, With,
- Yield,
- )
-
diff -Nru astroid-1.0.1/PKG-INFO astroid-1.3.8/PKG-INFO
--- astroid-1.0.1/PKG-INFO 2013-10-18 15:34:22.000000000 +0000
+++ astroid-1.3.8/PKG-INFO 2015-08-02 20:40:06.000000000 +0000
@@ -1,71 +1,80 @@
-Metadata-Version: 1.1
-Name: astroid
-Version: 1.0.1
-Summary: rebuild a new abstract syntax tree from Python's ast
-Home-page: http://bitbucket.org/logilab/astroid
-Author: Logilab
-Author-email: python-projects@lists.logilab.org
-License: LGPL
-Description: Astroid
- =======
-
- What's this?
- ------------
-
- The aim of this module is to provide a common base representation of
- python source code for projects such as pychecker, pyreverse,
- pylint... Well, actually the development of this library is essentially
- governed by pylint's needs. It used to be called logilab-astng.
-
- It provides a compatible representation which comes from the `_ast`
- module. It rebuilds the tree generated by the builtin _ast module by
- recursively walking down the AST and building an extended ast. The new
- node classes have additional methods and attributes for different
- usages. They include some support for static inference and local name
- scopes. Furthermore, astroid builds partial trees by inspecting living
- objects.
-
- Main modules are:
-
- * `bases`, `node_classses` and `scoped_nodes` contain the classes for the
- different type of nodes of the tree.
-
- * the `manager` contains a high level object to get astroid trees from
- source files and living objects. It maintains a cache of previously
- constructed tree for quick access.
-
-
- Installation
- ------------
-
- Extract the tarball, jump into the created directory and run::
-
- python setup.py install
-
- For installation options, see::
-
- python setup.py install --help
-
-
- If you have any questions, please mail the code-quality@python.org
- mailing list for support. See
- http://mail.python.org/mailman/listinfo/code-quality for subscription
- information and archives. You may find older archives at
- http://lists.logilab.org/mailman/listinfo/python-projects .
-
- Test
- ----
-
- Tests are in the 'test' subdirectory. To launch the whole tests suite
- at once, you may use the 'pytest' utility from logilab-common (simply
- type 'pytest' from within this directory) or if you're running python
- >= 2.7, using discover, for instance::
-
- python -m unittest discover -p "unittest*.py"
-
-Platform: UNKNOWN
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: Software Development :: Quality Assurance
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 3
+Metadata-Version: 1.1
+Name: astroid
+Version: 1.3.8
+Summary: A abstract syntax tree for Python with inference support.
+Home-page: http://bitbucket.org/logilab/astroid
+Author: Logilab
+Author-email: pylint-dev@lists.logilab.org
+License: LGPL
+Description: .. image:: https://drone.io/bitbucket.org/logilab/astroid/status.png
+ :alt: drone.io Build Status
+ :target: https://drone.io/bitbucket.org/logilab/astroid
+
+ Astroid
+ =======
+
+ What's this?
+ ------------
+
+ The aim of this module is to provide a common base representation of
+ python source code for projects such as pychecker, pyreverse,
+ pylint... Well, actually the development of this library is essentially
+ governed by pylint's needs. It used to be called logilab-astng.
+
+ It provides a compatible representation which comes from the `_ast`
+ module. It rebuilds the tree generated by the builtin _ast module by
+ recursively walking down the AST and building an extended ast. The new
+ node classes have additional methods and attributes for different
+ usages. They include some support for static inference and local name
+ scopes. Furthermore, astroid builds partial trees by inspecting living
+ objects.
+
+ Main modules are:
+
+ * `bases`, `node_classses` and `scoped_nodes` contain the classes for the
+ different type of nodes of the tree.
+
+ * the `manager` contains a high level object to get astroid trees from
+ source files and living objects. It maintains a cache of previously
+ constructed tree for quick access.
+
+
+ Installation
+ ------------
+
+ Extract the tarball, jump into the created directory and run::
+
+ python setup.py install
+
+ For installation options, see::
+
+ python setup.py install --help
+
+
+ If you have any questions, please mail the code-quality@python.org
+ mailing list for support. See
+ http://mail.python.org/mailman/listinfo/code-quality for subscription
+ information and archives. You may find older archives at
+ http://lists.logilab.org/mailman/listinfo/python-projects .
+
+ Python Versions
+ ---------------
+
+ astroid is compatible with Python 2.7 as well as 3.3 and later. astroid uses
+ the same code base for both Python versions, using six.
+
+ Test
+ ----
+
+ Tests are in the 'test' subdirectory. To launch the whole tests suite
+ at once, you may use the 'pytest' utility from logilab-common (simply
+ type 'pytest' from within this directory) or using unittest discover::
+
+ python -m unittest discover -p "unittest*.py"
+
+Platform: UNKNOWN
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Software Development :: Quality Assurance
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
diff -Nru astroid-1.0.1/__pkginfo__.py astroid-1.3.8/__pkginfo__.py
--- astroid-1.0.1/__pkginfo__.py 2013-10-18 15:34:05.000000000 +0000
+++ astroid-1.3.8/__pkginfo__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,48 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""astroid packaging information"""
-
-distname = 'astroid'
-
-modname = 'astroid'
-
-numversion = (1, 0, 1)
-version = '.'.join([str(num) for num in numversion])
-
-install_requires = ['logilab-common >= 0.60.0']
-
-license = 'LGPL'
-
-author = 'Logilab'
-author_email = 'python-projects@lists.logilab.org'
-mailinglist = "mailto://%s" % author_email
-web = 'http://bitbucket.org/logilab/astroid'
-
-description = "rebuild a new abstract syntax tree from Python's ast"
-
-from os.path import join
-include_dirs = ['brain',
- join('test', 'regrtest_data'),
- join('test', 'data'), join('test', 'data2')]
-
-classifiers = ["Topic :: Software Development :: Libraries :: Python Modules",
- "Topic :: Software Development :: Quality Assurance",
- "Programming Language :: Python",
- "Programming Language :: Python :: 2",
- "Programming Language :: Python :: 3",
- ]
diff -Nru astroid-1.0.1/protocols.py astroid-1.3.8/protocols.py
--- astroid-1.0.1/protocols.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/protocols.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,320 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""this module contains a set of functions to handle python protocols for nodes
-where it makes sense.
-"""
-
-__doctype__ = "restructuredtext en"
-
-from astroid.exceptions import InferenceError, NoDefault
-from astroid.node_classes import unpack_infer
-from astroid.bases import copy_context, \
- raise_if_nothing_infered, yes_if_nothing_infered, Instance, YES
-from astroid.nodes import const_factory
-from astroid import nodes
-
-# unary operations ############################################################
-
-def tl_infer_unary_op(self, operator):
- if operator == 'not':
- return const_factory(not bool(self.elts))
- raise TypeError() # XXX log unsupported operation
-nodes.Tuple.infer_unary_op = tl_infer_unary_op
-nodes.List.infer_unary_op = tl_infer_unary_op
-
-
-def dict_infer_unary_op(self, operator):
- if operator == 'not':
- return const_factory(not bool(self.items))
- raise TypeError() # XXX log unsupported operation
-nodes.Dict.infer_unary_op = dict_infer_unary_op
-
-
-def const_infer_unary_op(self, operator):
- if operator == 'not':
- return const_factory(not self.value)
- # XXX log potentially raised TypeError
- elif operator == '+':
- return const_factory(+self.value)
- else: # operator == '-':
- return const_factory(-self.value)
-nodes.Const.infer_unary_op = const_infer_unary_op
-
-
-# binary operations ###########################################################
-
-BIN_OP_IMPL = {'+': lambda a, b: a + b,
- '-': lambda a, b: a - b,
- '/': lambda a, b: a / b,
- '//': lambda a, b: a // b,
- '*': lambda a, b: a * b,
- '**': lambda a, b: a ** b,
- '%': lambda a, b: a % b,
- '&': lambda a, b: a & b,
- '|': lambda a, b: a | b,
- '^': lambda a, b: a ^ b,
- '<<': lambda a, b: a << b,
- '>>': lambda a, b: a >> b,
- }
-for key, impl in BIN_OP_IMPL.items():
- BIN_OP_IMPL[key+'='] = impl
-
-def const_infer_binary_op(self, operator, other, context):
- for other in other.infer(context):
- if isinstance(other, nodes.Const):
- try:
- impl = BIN_OP_IMPL[operator]
-
- try:
- yield const_factory(impl(self.value, other.value))
- except Exception:
- # ArithmeticError is not enough: float >> float is a TypeError
- # TODO : let pylint know about the problem
- pass
- except TypeError:
- # XXX log TypeError
- continue
- elif other is YES:
- yield other
- else:
- try:
- for val in other.infer_binary_op(operator, self, context):
- yield val
- except AttributeError:
- yield YES
-nodes.Const.infer_binary_op = yes_if_nothing_infered(const_infer_binary_op)
-
-
-def tl_infer_binary_op(self, operator, other, context):
- for other in other.infer(context):
- if isinstance(other, self.__class__) and operator == '+':
- node = self.__class__()
- elts = [n for elt in self.elts for n in elt.infer(context)
- if not n is YES]
- elts += [n for elt in other.elts for n in elt.infer(context)
- if not n is YES]
- node.elts = elts
- yield node
- elif isinstance(other, nodes.Const) and operator == '*':
- if not isinstance(other.value, int):
- yield YES
- continue
- node = self.__class__()
- elts = [n for elt in self.elts for n in elt.infer(context)
- if not n is YES] * other.value
- node.elts = elts
- yield node
- elif isinstance(other, Instance) and not isinstance(other, nodes.Const):
- yield YES
- # XXX else log TypeError
-nodes.Tuple.infer_binary_op = yes_if_nothing_infered(tl_infer_binary_op)
-nodes.List.infer_binary_op = yes_if_nothing_infered(tl_infer_binary_op)
-
-
-def dict_infer_binary_op(self, operator, other, context):
- for other in other.infer(context):
- if isinstance(other, Instance) and isinstance(other._proxied, nodes.Class):
- yield YES
- # XXX else log TypeError
-nodes.Dict.infer_binary_op = yes_if_nothing_infered(dict_infer_binary_op)
-
-
-# assignment ##################################################################
-
-"""the assigned_stmts method is responsible to return the assigned statement
-(e.g. not inferred) according to the assignment type.
-
-The `asspath` argument is used to record the lhs path of the original node.
-For instance if we want assigned statements for 'c' in 'a, (b,c)', asspath
-will be [1, 1] once arrived to the Assign node.
-
-The `context` argument is the current inference context which should be given
-to any intermediary inference necessary.
-"""
-
-def _resolve_looppart(parts, asspath, context):
- """recursive function to resolve multiple assignments on loops"""
- asspath = asspath[:]
- index = asspath.pop(0)
- for part in parts:
- if part is YES:
- continue
- # XXX handle __iter__ and log potentially detected errors
- if not hasattr(part, 'itered'):
- continue
- try:
- itered = part.itered()
- except TypeError:
- continue # XXX log error
- for stmt in itered:
- try:
- assigned = stmt.getitem(index, context)
- except (AttributeError, IndexError):
- continue
- except TypeError, exc: # stmt is unsubscriptable Const
- continue
- if not asspath:
- # we achieved to resolved the assignment path,
- # don't infer the last part
- yield assigned
- elif assigned is YES:
- break
- else:
- # we are not yet on the last part of the path
- # search on each possibly inferred value
- try:
- for infered in _resolve_looppart(assigned.infer(context),
- asspath, context):
- yield infered
- except InferenceError:
- break
-
-
-def for_assigned_stmts(self, node, context=None, asspath=None):
- if asspath is None:
- for lst in self.iter.infer(context):
- if isinstance(lst, (nodes.Tuple, nodes.List)):
- for item in lst.elts:
- yield item
- else:
- for infered in _resolve_looppart(self.iter.infer(context),
- asspath, context):
- yield infered
-
-nodes.For.assigned_stmts = raise_if_nothing_infered(for_assigned_stmts)
-nodes.Comprehension.assigned_stmts = raise_if_nothing_infered(for_assigned_stmts)
-
-
-def mulass_assigned_stmts(self, node, context=None, asspath=None):
- if asspath is None:
- asspath = []
- asspath.insert(0, self.elts.index(node))
- return self.parent.assigned_stmts(self, context, asspath)
-nodes.Tuple.assigned_stmts = mulass_assigned_stmts
-nodes.List.assigned_stmts = mulass_assigned_stmts
-
-
-def assend_assigned_stmts(self, context=None):
- return self.parent.assigned_stmts(self, context=context)
-nodes.AssName.assigned_stmts = assend_assigned_stmts
-nodes.AssAttr.assigned_stmts = assend_assigned_stmts
-
-
-def _arguments_infer_argname(self, name, context):
- # arguments information may be missing, in which case we can't do anything
- # more
- if not (self.args or self.vararg or self.kwarg):
- yield YES
- return
- # first argument of instance/class method
- if self.args and getattr(self.args[0], 'name', None) == name:
- functype = self.parent.type
- if functype == 'method':
- yield Instance(self.parent.parent.frame())
- return
- if functype == 'classmethod':
- yield self.parent.parent.frame()
- return
- if name == self.vararg:
- yield const_factory(())
- return
- if name == self.kwarg:
- yield const_factory({})
- return
- # if there is a default value, yield it. And then yield YES to reflect
- # we can't guess given argument value
- try:
- context = copy_context(context)
- for infered in self.default_value(name).infer(context):
- yield infered
- yield YES
- except NoDefault:
- yield YES
-
-
-def arguments_assigned_stmts(self, node, context, asspath=None):
- if context.callcontext:
- # reset call context/name
- callcontext = context.callcontext
- context = copy_context(context)
- context.callcontext = None
- for infered in callcontext.infer_argument(self.parent, node.name, context):
- yield infered
- return
- for infered in _arguments_infer_argname(self, node.name, context):
- yield infered
-nodes.Arguments.assigned_stmts = arguments_assigned_stmts
-
-
-def assign_assigned_stmts(self, node, context=None, asspath=None):
- if not asspath:
- yield self.value
- return
- for infered in _resolve_asspart(self.value.infer(context), asspath, context):
- yield infered
-nodes.Assign.assigned_stmts = raise_if_nothing_infered(assign_assigned_stmts)
-nodes.AugAssign.assigned_stmts = raise_if_nothing_infered(assign_assigned_stmts)
-
-
-def _resolve_asspart(parts, asspath, context):
- """recursive function to resolve multiple assignments"""
- asspath = asspath[:]
- index = asspath.pop(0)
- for part in parts:
- if hasattr(part, 'getitem'):
- try:
- assigned = part.getitem(index, context)
- # XXX raise a specific exception to avoid potential hiding of
- # unexpected exception ?
- except (TypeError, IndexError):
- return
- if not asspath:
- # we achieved to resolved the assignment path, don't infer the
- # last part
- yield assigned
- elif assigned is YES:
- return
- else:
- # we are not yet on the last part of the path search on each
- # possibly inferred value
- try:
- for infered in _resolve_asspart(assigned.infer(context),
- asspath, context):
- yield infered
- except InferenceError:
- return
-
-
-def excepthandler_assigned_stmts(self, node, context=None, asspath=None):
- for assigned in unpack_infer(self.type):
- if isinstance(assigned, nodes.Class):
- assigned = Instance(assigned)
- yield assigned
-nodes.ExceptHandler.assigned_stmts = raise_if_nothing_infered(excepthandler_assigned_stmts)
-
-
-def with_assigned_stmts(self, node, context=None, asspath=None):
- if asspath is None:
- for _, vars in self.items:
- for lst in vars.infer(context):
- if isinstance(lst, (nodes.Tuple, nodes.List)):
- for item in lst.nodes:
- yield item
-nodes.With.assigned_stmts = raise_if_nothing_infered(with_assigned_stmts)
-
-
diff -Nru astroid-1.0.1/raw_building.py astroid-1.3.8/raw_building.py
--- astroid-1.0.1/raw_building.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/raw_building.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,351 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""this module contains a set of functions to create astroid trees from scratch
-(build_* functions) or from living object (object_build_* functions)
-"""
-
-__docformat__ = "restructuredtext en"
-
-import sys
-from os.path import abspath
-from inspect import (getargspec, isdatadescriptor, isfunction, ismethod,
- ismethoddescriptor, isclass, isbuiltin)
-
-from astroid.node_classes import CONST_CLS
-from astroid.nodes import (Module, Class, Const, const_factory, From,
- Function, EmptyNode, Name, Arguments)
-from astroid.bases import BUILTINS, Generator
-from astroid.manager import AstroidManager
-MANAGER = AstroidManager()
-
-_CONSTANTS = tuple(CONST_CLS) # the keys of CONST_CLS eg python builtin types
-
-def _attach_local_node(parent, node, name):
- node.name = name # needed by add_local_node
- parent.add_local_node(node)
-
-_marker = object()
-
-def attach_dummy_node(node, name, object=_marker):
- """create a dummy node and register it in the locals of the given
- node with the specified name
- """
- enode = EmptyNode()
- enode.object = object
- _attach_local_node(node, enode, name)
-
-EmptyNode.has_underlying_object = lambda self: self.object is not _marker
-
-def attach_const_node(node, name, value):
- """create a Const node and register it in the locals of the given
- node with the specified name
- """
- if not name in node.special_attributes:
- _attach_local_node(node, const_factory(value), name)
-
-def attach_import_node(node, modname, membername):
- """create a From node and register it in the locals of the given
- node with the specified name
- """
- from_node = From(modname, [(membername, None)])
- _attach_local_node(node, from_node, membername)
-
-
-def build_module(name, doc=None):
- """create and initialize a astroid Module node"""
- node = Module(name, doc, pure_python=False)
- node.package = False
- node.parent = None
- return node
-
-def build_class(name, basenames=(), doc=None):
- """create and initialize a astroid Class node"""
- node = Class(name, doc)
- for base in basenames:
- basenode = Name()
- basenode.name = base
- node.bases.append(basenode)
- basenode.parent = node
- return node
-
-def build_function(name, args=None, defaults=None, flag=0, doc=None):
- """create and initialize a astroid Function node"""
- args, defaults = args or [], defaults or []
- # first argument is now a list of decorators
- func = Function(name, doc)
- func.args = argsnode = Arguments()
- argsnode.args = []
- for arg in args:
- argsnode.args.append(Name())
- argsnode.args[-1].name = arg
- argsnode.args[-1].parent = argsnode
- argsnode.defaults = []
- for default in defaults:
- argsnode.defaults.append(const_factory(default))
- argsnode.defaults[-1].parent = argsnode
- argsnode.kwarg = None
- argsnode.vararg = None
- argsnode.parent = func
- if args:
- register_arguments(func)
- return func
-
-
-def build_from_import(fromname, names):
- """create and initialize an astroid From import statement"""
- return From(fromname, [(name, None) for name in names])
-
-def register_arguments(func, args=None):
- """add given arguments to local
-
- args is a list that may contains nested lists
- (i.e. def func(a, (b, c, d)): ...)
- """
- if args is None:
- args = func.args.args
- if func.args.vararg:
- func.set_local(func.args.vararg, func.args)
- if func.args.kwarg:
- func.set_local(func.args.kwarg, func.args)
- for arg in args:
- if isinstance(arg, Name):
- func.set_local(arg.name, arg)
- else:
- register_arguments(func, arg.elts)
-
-def object_build_class(node, member, localname):
- """create astroid for a living class object"""
- basenames = [base.__name__ for base in member.__bases__]
- return _base_class_object_build(node, member, basenames,
- localname=localname)
-
-def object_build_function(node, member, localname):
- """create astroid for a living function object"""
- args, varargs, varkw, defaults = getargspec(member)
- if varargs is not None:
- args.append(varargs)
- if varkw is not None:
- args.append(varkw)
- func = build_function(getattr(member, '__name__', None) or localname, args,
- defaults, member.func_code.co_flags, member.__doc__)
- node.add_local_node(func, localname)
-
-def object_build_datadescriptor(node, member, name):
- """create astroid for a living data descriptor object"""
- return _base_class_object_build(node, member, [], name)
-
-def object_build_methoddescriptor(node, member, localname):
- """create astroid for a living method descriptor object"""
- # FIXME get arguments ?
- func = build_function(getattr(member, '__name__', None) or localname,
- doc=member.__doc__)
- # set node's arguments to None to notice that we have no information, not
- # and empty argument list
- func.args.args = None
- node.add_local_node(func, localname)
-
-def _base_class_object_build(node, member, basenames, name=None, localname=None):
- """create astroid for a living class object, with a given set of base names
- (e.g. ancestors)
- """
- klass = build_class(name or getattr(member, '__name__', None) or localname,
- basenames, member.__doc__)
- klass._newstyle = isinstance(member, type)
- node.add_local_node(klass, localname)
- try:
- # limit the instantiation trick since it's too dangerous
- # (such as infinite test execution...)
- # this at least resolves common case such as Exception.args,
- # OSError.errno
- if issubclass(member, Exception):
- instdict = member().__dict__
- else:
- raise TypeError
- except:
- pass
- else:
- for name, obj in instdict.items():
- valnode = EmptyNode()
- valnode.object = obj
- valnode.parent = klass
- valnode.lineno = 1
- klass.instance_attrs[name] = [valnode]
- return klass
-
-
-
-
-class InspectBuilder(object):
- """class for building nodes from living object
-
- this is actually a really minimal representation, including only Module,
- Function and Class nodes and some others as guessed.
- """
-
- # astroid from living objects ###############################################
-
- def __init__(self):
- self._done = {}
- self._module = None
-
- def inspect_build(self, module, modname=None, path=None):
- """build astroid from a living module (i.e. using inspect)
- this is used when there is no python source code available (either
- because it's a built-in module or because the .py is not available)
- """
- self._module = module
- if modname is None:
- modname = module.__name__
- try:
- node = build_module(modname, module.__doc__)
- except AttributeError:
- # in jython, java modules have no __doc__ (see #109562)
- node = build_module(modname)
- node.file = node.path = path and abspath(path) or path
- MANAGER.astroid_cache[modname] = node
- node.package = hasattr(module, '__path__')
- self._done = {}
- self.object_build(node, module)
- return node
-
- def object_build(self, node, obj):
- """recursive method which create a partial ast from real objects
- (only function, class, and method are handled)
- """
- if obj in self._done:
- return self._done[obj]
- self._done[obj] = node
- for name in dir(obj):
- try:
- member = getattr(obj, name)
- except AttributeError:
- # damned ExtensionClass.Base, I know you're there !
- attach_dummy_node(node, name)
- continue
- if ismethod(member):
- member = member.im_func
- if isfunction(member):
- # verify this is not an imported function
- filename = getattr(member.func_code, 'co_filename', None)
- if filename is None:
- assert isinstance(member, object)
- object_build_methoddescriptor(node, member, name)
- elif filename != getattr(self._module, '__file__', None):
- attach_dummy_node(node, name, member)
- else:
- object_build_function(node, member, name)
- elif isbuiltin(member):
- if self.imported_member(node, member, name):
- #if obj is object:
- # print 'skippp', obj, name, member
- continue
- object_build_methoddescriptor(node, member, name)
- elif isclass(member):
- if self.imported_member(node, member, name):
- continue
- if member in self._done:
- class_node = self._done[member]
- if not class_node in node.locals.get(name, ()):
- node.add_local_node(class_node, name)
- else:
- class_node = object_build_class(node, member, name)
- # recursion
- self.object_build(class_node, member)
- if name == '__class__' and class_node.parent is None:
- class_node.parent = self._done[self._module]
- elif ismethoddescriptor(member):
- assert isinstance(member, object)
- object_build_methoddescriptor(node, member, name)
- elif isdatadescriptor(member):
- assert isinstance(member, object)
- object_build_datadescriptor(node, member, name)
- elif type(member) in _CONSTANTS:
- attach_const_node(node, name, member)
- else:
- # create an empty node so that the name is actually defined
- attach_dummy_node(node, name, member)
-
- def imported_member(self, node, member, name):
- """verify this is not an imported class or handle it"""
- # /!\ some classes like ExtensionClass doesn't have a __module__
- # attribute ! Also, this may trigger an exception on badly built module
- # (see http://www.logilab.org/ticket/57299 for instance)
- try:
- modname = getattr(member, '__module__', None)
- except:
- # XXX use logging
- print 'unexpected error while building astroid from living object'
- import traceback
- traceback.print_exc()
- modname = None
- if modname is None:
- if name in ('__new__', '__subclasshook__'):
- # Python 2.5.1 (r251:54863, Sep 1 2010, 22:03:14)
- # >>> print object.__new__.__module__
- # None
- modname = BUILTINS
- else:
- attach_dummy_node(node, name, member)
- return True
- if {'gtk': 'gtk._gtk'}.get(modname, modname) != self._module.__name__:
- # check if it sounds valid and then add an import node, else use a
- # dummy node
- try:
- getattr(sys.modules[modname], name)
- except (KeyError, AttributeError):
- attach_dummy_node(node, name, member)
- else:
- attach_import_node(node, modname, name)
- return True
- return False
-
-
-### astroid boot strapping ################################################### ###
-Astroid_BUILDER = InspectBuilder()
-
-_CONST_PROXY = {}
-def astroid_boot_strapping():
- """astroid boot strapping the builtins module"""
- # this boot strapping is necessary since we need the Const nodes to
- # inspect_build builtins, and then we can proxy Const
- from logilab.common.compat import builtins
- astroid_builtin = Astroid_BUILDER.inspect_build(builtins)
- for cls, node_cls in CONST_CLS.items():
- if cls is type(None):
- proxy = build_class('NoneType')
- proxy.parent = astroid_builtin
- else:
- proxy = astroid_builtin.getattr(cls.__name__)[0]
- if cls in (dict, list, set, tuple):
- node_cls._proxied = proxy
- else:
- _CONST_PROXY[cls] = proxy
-
-astroid_boot_strapping()
-
-# TODO : find a nicer way to handle this situation;
-# However __proxied introduced an
-# infinite recursion (see https://bugs.launchpad.net/pylint/+bug/456870)
-def _set_proxied(const):
- return _CONST_PROXY[const.value.__class__]
-Const._proxied = property(_set_proxied)
-
-from types import GeneratorType
-Generator._proxied = Class(GeneratorType.__name__, GeneratorType.__doc__)
-Astroid_BUILDER.object_build(Generator._proxied, GeneratorType)
-
diff -Nru astroid-1.0.1/README astroid-1.3.8/README
--- astroid-1.0.1/README 2013-07-29 15:04:24.000000000 +0000
+++ astroid-1.3.8/README 2015-08-02 19:35:46.000000000 +0000
@@ -1,3 +1,7 @@
+.. image:: https://drone.io/bitbucket.org/logilab/astroid/status.png
+ :alt: drone.io Build Status
+ :target: https://drone.io/bitbucket.org/logilab/astroid
+
Astroid
=======
@@ -45,12 +49,17 @@
information and archives. You may find older archives at
http://lists.logilab.org/mailman/listinfo/python-projects .
+Python Versions
+---------------
+
+astroid is compatible with Python 2.7 as well as 3.3 and later. astroid uses
+the same code base for both Python versions, using six.
+
Test
----
Tests are in the 'test' subdirectory. To launch the whole tests suite
at once, you may use the 'pytest' utility from logilab-common (simply
-type 'pytest' from within this directory) or if you're running python
->= 2.7, using discover, for instance::
+type 'pytest' from within this directory) or using unittest discover::
python -m unittest discover -p "unittest*.py"
diff -Nru astroid-1.0.1/README.Python3 astroid-1.3.8/README.Python3
--- astroid-1.0.1/README.Python3 2013-07-29 15:04:24.000000000 +0000
+++ astroid-1.3.8/README.Python3 1970-01-01 00:00:00.000000000 +0000
@@ -1,26 +0,0 @@
-Python3
-=======
-
-Approach
---------
-
-We maintain a Python 2 base and use 2to3 to generate Python 3 code.
-
-2to3 is integrated into the distutils installation process and will be run as a
-build step when invoked by the python3 interpreter::
-
- python3 setup.py install --no-compile
-
-
-Debian
-------
-
-For the Debian packaging, you can use the debian.py3k/ content against
-the debian/ folder::
-
- cp debian.py3k/* debian/
-
-
-Resources
----------
-http://wiki.python.org/moin/PortingPythonToPy3k
diff -Nru astroid-1.0.1/rebuilder.py astroid-1.3.8/rebuilder.py
--- astroid-1.0.1/rebuilder.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/rebuilder.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,940 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""this module contains utilities for rebuilding a _ast tree in
-order to get a single Astroid representation
-"""
-
-import sys
-from warnings import warn
-from _ast import (Expr as Discard, Str,
- # binary operators
- Add, Div, FloorDiv, Mod, Mult, Pow, Sub, BitAnd, BitOr, BitXor,
- LShift, RShift,
- # logical operators
- And, Or,
- # unary operators
- UAdd, USub, Not, Invert,
- # comparison operators
- Eq, Gt, GtE, In, Is, IsNot, Lt, LtE, NotEq, NotIn,
- )
-
-from astroid import nodes as new
-
-
-_BIN_OP_CLASSES = {Add: '+',
- BitAnd: '&',
- BitOr: '|',
- BitXor: '^',
- Div: '/',
- FloorDiv: '//',
- Mod: '%',
- Mult: '*',
- Pow: '**',
- Sub: '-',
- LShift: '<<',
- RShift: '>>'}
-
-_BOOL_OP_CLASSES = {And: 'and',
- Or: 'or'}
-
-_UNARY_OP_CLASSES = {UAdd: '+',
- USub: '-',
- Not: 'not',
- Invert: '~'}
-
-_CMP_OP_CLASSES = {Eq: '==',
- Gt: '>',
- GtE: '>=',
- In: 'in',
- Is: 'is',
- IsNot: 'is not',
- Lt: '<',
- LtE: '<=',
- NotEq: '!=',
- NotIn: 'not in'}
-
-CONST_NAME_TRANSFORMS = {'None': None,
- 'True': True,
- 'False': False}
-
-REDIRECT = {'arguments': 'Arguments',
- 'Attribute': 'Getattr',
- 'comprehension': 'Comprehension',
- 'Call': 'CallFunc',
- 'ClassDef': 'Class',
- "ListCompFor": 'Comprehension',
- "GenExprFor": 'Comprehension',
- 'excepthandler': 'ExceptHandler',
- 'Expr': 'Discard',
- 'FunctionDef': 'Function',
- 'GeneratorExp': 'GenExpr',
- 'ImportFrom': 'From',
- 'keyword': 'Keyword',
- 'Repr': 'Backquote',
- }
-
-def _init_set_doc(node, newnode):
- newnode.doc = None
- try:
- if isinstance(node.body[0], Discard) and isinstance(node.body[0].value, Str):
- newnode.tolineno = node.body[0].lineno
- newnode.doc = node.body[0].value.s
- node.body = node.body[1:]
-
- except IndexError:
- pass # ast built from scratch
-
-def _lineno_parent(oldnode, newnode, parent):
- newnode.parent = parent
- if hasattr(oldnode, 'lineno'):
- newnode.lineno = oldnode.lineno
- if hasattr(oldnode, 'col_offset'):
- newnode.col_offset = oldnode.col_offset
-
-def _set_infos(oldnode, newnode, parent):
- newnode.parent = parent
- if hasattr(oldnode, 'lineno'):
- newnode.lineno = oldnode.lineno
- if hasattr(oldnode, 'col_offset'):
- newnode.col_offset = oldnode.col_offset
- newnode.set_line_info(newnode.last_child()) # set_line_info accepts None
-
-
-
-
-class TreeRebuilder(object):
- """Rebuilds the _ast tree to become an Astroid tree"""
-
- def __init__(self, manager):
- self._manager = manager
- self.asscontext = None
- self._metaclass = ['']
- self._global_names = []
- self._from_nodes = []
- self._delayed_assattr = []
- self._visit_meths = {}
-
- def _transform(self, node):
- try:
- transforms = self._manager.transforms[type(node)]
- except KeyError:
- return node # no transform registered for this class of node
- orig_node = node # copy the reference
- for transform_func, predicate in transforms:
- if predicate is None or predicate(node):
- ret = transform_func(node)
- # if the transformation function returns something, it's
- # expected to be a replacement for the node
- if ret is not None:
- if node is not orig_node:
- # node has already be modified by some previous
- # transformation, warn about it
- warn('node %s substitued multiple times' % node)
- node = ret
- return node
-
- def visit_module(self, node, modname, package):
- """visit a Module node by returning a fresh instance of it"""
- newnode = new.Module(modname, None)
- newnode.package = package
- _lineno_parent(node, newnode, parent=None)
- _init_set_doc(node, newnode)
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.set_line_info(newnode.last_child())
- return self._transform(newnode)
-
- def visit(self, node, parent):
- cls = node.__class__
- if cls in self._visit_meths:
- visit_method = self._visit_meths[cls]
- else:
- cls_name = cls.__name__
- visit_name = 'visit_' + REDIRECT.get(cls_name, cls_name).lower()
- visit_method = getattr(self, visit_name)
- self._visit_meths[cls] = visit_method
- return self._transform(visit_method(node, parent))
-
- def _save_assignment(self, node, name=None):
- """save assignement situation since node.parent is not available yet"""
- if self._global_names and node.name in self._global_names[-1]:
- node.root().set_local(node.name, node)
- else:
- node.parent.set_local(node.name, node)
-
-
- def visit_arguments(self, node, parent):
- """visit a Arguments node by returning a fresh instance of it"""
- newnode = new.Arguments()
- _lineno_parent(node, newnode, parent)
- self.asscontext = "Ass"
- newnode.args = [self.visit(child, newnode) for child in node.args]
- self.asscontext = None
- newnode.defaults = [self.visit(child, newnode) for child in node.defaults]
- newnode.kwonlyargs = []
- newnode.kw_defaults = []
- newnode.vararg = node.vararg
- newnode.kwarg = node.kwarg
- # save argument names in locals:
- if node.vararg:
- newnode.parent.set_local(newnode.vararg, newnode)
- if node.kwarg:
- newnode.parent.set_local(newnode.kwarg, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_assattr(self, node, parent):
- """visit a AssAttr node by returning a fresh instance of it"""
- assc, self.asscontext = self.asscontext, None
- newnode = new.AssAttr()
- _lineno_parent(node, newnode, parent)
- newnode.expr = self.visit(node.expr, newnode)
- self.asscontext = assc
- self._delayed_assattr.append(newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_assert(self, node, parent):
- """visit a Assert node by returning a fresh instance of it"""
- newnode = new.Assert()
- _lineno_parent(node, newnode, parent)
- newnode.test = self.visit(node.test, newnode)
- if node.msg is not None:
- newnode.fail = self.visit(node.msg, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_assign(self, node, parent):
- """visit a Assign node by returning a fresh instance of it"""
- newnode = new.Assign()
- _lineno_parent(node, newnode, parent)
- self.asscontext = "Ass"
- newnode.targets = [self.visit(child, newnode) for child in node.targets]
- self.asscontext = None
- newnode.value = self.visit(node.value, newnode)
- # set some function or metaclass infos XXX explain ?
- klass = newnode.parent.frame()
- if (isinstance(klass, new.Class)
- and isinstance(newnode.value, new.CallFunc)
- and isinstance(newnode.value.func, new.Name)):
- func_name = newnode.value.func.name
- for ass_node in newnode.targets:
- try:
- meth = klass[ass_node.name]
- if isinstance(meth, new.Function):
- if func_name in ('classmethod', 'staticmethod'):
- meth.type = func_name
- elif func_name == 'classproperty': # see lgc.decorators
- meth.type = 'classmethod'
- meth.extra_decorators.append(newnode.value)
- except (AttributeError, KeyError):
- continue
- elif getattr(newnode.targets[0], 'name', None) == '__metaclass__':
- # XXX check more...
- self._metaclass[-1] = 'type' # XXX get the actual metaclass
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_assname(self, node, parent, node_name=None):
- '''visit a node and return a AssName node'''
- newnode = new.AssName()
- _set_infos(node, newnode, parent)
- newnode.name = node_name
- self._save_assignment(newnode)
- return newnode
-
- def visit_augassign(self, node, parent):
- """visit a AugAssign node by returning a fresh instance of it"""
- newnode = new.AugAssign()
- _lineno_parent(node, newnode, parent)
- newnode.op = _BIN_OP_CLASSES[node.op.__class__] + "="
- self.asscontext = "Ass"
- newnode.target = self.visit(node.target, newnode)
- self.asscontext = None
- newnode.value = self.visit(node.value, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_backquote(self, node, parent):
- """visit a Backquote node by returning a fresh instance of it"""
- newnode = new.Backquote()
- _lineno_parent(node, newnode, parent)
- newnode.value = self.visit(node.value, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_binop(self, node, parent):
- """visit a BinOp node by returning a fresh instance of it"""
- newnode = new.BinOp()
- _lineno_parent(node, newnode, parent)
- newnode.left = self.visit(node.left, newnode)
- newnode.right = self.visit(node.right, newnode)
- newnode.op = _BIN_OP_CLASSES[node.op.__class__]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_boolop(self, node, parent):
- """visit a BoolOp node by returning a fresh instance of it"""
- newnode = new.BoolOp()
- _lineno_parent(node, newnode, parent)
- newnode.values = [self.visit(child, newnode) for child in node.values]
- newnode.op = _BOOL_OP_CLASSES[node.op.__class__]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_break(self, node, parent):
- """visit a Break node by returning a fresh instance of it"""
- newnode = new.Break()
- _set_infos(node, newnode, parent)
- return newnode
-
- def visit_callfunc(self, node, parent):
- """visit a CallFunc node by returning a fresh instance of it"""
- newnode = new.CallFunc()
- _lineno_parent(node, newnode, parent)
- newnode.func = self.visit(node.func, newnode)
- newnode.args = [self.visit(child, newnode) for child in node.args]
- if node.starargs is not None:
- newnode.starargs = self.visit(node.starargs, newnode)
- if node.kwargs is not None:
- newnode.kwargs = self.visit(node.kwargs, newnode)
- newnode.args.extend(self.visit(child, newnode) for child in node.keywords)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_class(self, node, parent):
- """visit a Class node to become astroid"""
- self._metaclass.append(self._metaclass[-1])
- newnode = new.Class(node.name, None)
- _lineno_parent(node, newnode, parent)
- _init_set_doc(node, newnode)
- newnode.bases = [self.visit(child, newnode) for child in node.bases]
- newnode.body = [self.visit(child, newnode) for child in node.body]
- if 'decorator_list' in node._fields and node.decorator_list:# py >= 2.6
- newnode.decorators = self.visit_decorators(node, newnode)
- newnode.set_line_info(newnode.last_child())
- metaclass = self._metaclass.pop()
- if not newnode.bases:
- # no base classes, detect new / style old style according to
- # current scope
- newnode._newstyle = metaclass == 'type'
- newnode.parent.frame().set_local(newnode.name, newnode)
- return newnode
-
- def visit_const(self, node, parent):
- """visit a Const node by returning a fresh instance of it"""
- newnode = new.Const(node.value)
- _set_infos(node, newnode, parent)
- return newnode
-
- def visit_continue(self, node, parent):
- """visit a Continue node by returning a fresh instance of it"""
- newnode = new.Continue()
- _set_infos(node, newnode, parent)
- return newnode
-
- def visit_compare(self, node, parent):
- """visit a Compare node by returning a fresh instance of it"""
- newnode = new.Compare()
- _lineno_parent(node, newnode, parent)
- newnode.left = self.visit(node.left, newnode)
- newnode.ops = [(_CMP_OP_CLASSES[op.__class__], self.visit(expr, newnode))
- for (op, expr) in zip(node.ops, node.comparators)]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_comprehension(self, node, parent):
- """visit a Comprehension node by returning a fresh instance of it"""
- newnode = new.Comprehension()
- _lineno_parent(node, newnode, parent)
- self.asscontext = "Ass"
- newnode.target = self.visit(node.target, newnode)
- self.asscontext = None
- newnode.iter = self.visit(node.iter, newnode)
- newnode.ifs = [self.visit(child, newnode) for child in node.ifs]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_decorators(self, node, parent):
- """visit a Decorators node by returning a fresh instance of it"""
- # /!\ node is actually a _ast.Function node while
- # parent is a astroid.nodes.Function node
- newnode = new.Decorators()
- _lineno_parent(node, newnode, parent)
- if 'decorators' in node._fields: # py < 2.6, i.e. 2.5
- decorators = node.decorators
- else:
- decorators= node.decorator_list
- newnode.nodes = [self.visit(child, newnode) for child in decorators]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_delete(self, node, parent):
- """visit a Delete node by returning a fresh instance of it"""
- newnode = new.Delete()
- _lineno_parent(node, newnode, parent)
- self.asscontext = "Del"
- newnode.targets = [self.visit(child, newnode) for child in node.targets]
- self.asscontext = None
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_dict(self, node, parent):
- """visit a Dict node by returning a fresh instance of it"""
- newnode = new.Dict()
- _lineno_parent(node, newnode, parent)
- newnode.items = [(self.visit(key, newnode), self.visit(value, newnode))
- for key, value in zip(node.keys, node.values)]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_dictcomp(self, node, parent):
- """visit a DictComp node by returning a fresh instance of it"""
- newnode = new.DictComp()
- _lineno_parent(node, newnode, parent)
- newnode.key = self.visit(node.key, newnode)
- newnode.value = self.visit(node.value, newnode)
- newnode.generators = [self.visit(child, newnode)
- for child in node.generators]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_discard(self, node, parent):
- """visit a Discard node by returning a fresh instance of it"""
- newnode = new.Discard()
- _lineno_parent(node, newnode, parent)
- newnode.value = self.visit(node.value, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_ellipsis(self, node, parent):
- """visit an Ellipsis node by returning a fresh instance of it"""
- newnode = new.Ellipsis()
- _set_infos(node, newnode, parent)
- return newnode
-
- def visit_emptynode(self, node, parent):
- """visit an EmptyNode node by returning a fresh instance of it"""
- newnode = new.EmptyNode()
- _set_infos(node, newnode, parent)
- return newnode
-
- def visit_excepthandler(self, node, parent):
- """visit an ExceptHandler node by returning a fresh instance of it"""
- newnode = new.ExceptHandler()
- _lineno_parent(node, newnode, parent)
- if node.type is not None:
- newnode.type = self.visit(node.type, newnode)
- if node.name is not None:
- # /!\ node.name can be a tuple
- self.asscontext = "Ass"
- newnode.name = self.visit(node.name, newnode)
- self.asscontext = None
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_exec(self, node, parent):
- """visit an Exec node by returning a fresh instance of it"""
- newnode = new.Exec()
- _lineno_parent(node, newnode, parent)
- newnode.expr = self.visit(node.body, newnode)
- if node.globals is not None:
- newnode.globals = self.visit(node.globals, newnode)
- if node.locals is not None:
- newnode.locals = self.visit(node.locals, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_extslice(self, node, parent):
- """visit an ExtSlice node by returning a fresh instance of it"""
- newnode = new.ExtSlice()
- _lineno_parent(node, newnode, parent)
- newnode.dims = [self.visit(dim, newnode) for dim in node.dims]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_for(self, node, parent):
- """visit a For node by returning a fresh instance of it"""
- newnode = new.For()
- _lineno_parent(node, newnode, parent)
- self.asscontext = "Ass"
- newnode.target = self.visit(node.target, newnode)
- self.asscontext = None
- newnode.iter = self.visit(node.iter, newnode)
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_from(self, node, parent):
- """visit a From node by returning a fresh instance of it"""
- names = [(alias.name, alias.asname) for alias in node.names]
- newnode = new.From(node.module or '', names, node.level or None)
- _set_infos(node, newnode, parent)
- # store From names to add them to locals after building
- self._from_nodes.append(newnode)
- return newnode
-
- def visit_function(self, node, parent):
- """visit an Function node to become astroid"""
- self._global_names.append({})
- newnode = new.Function(node.name, None)
- _lineno_parent(node, newnode, parent)
- _init_set_doc(node, newnode)
- newnode.args = self.visit(node.args, newnode)
- newnode.body = [self.visit(child, newnode) for child in node.body]
- if 'decorators' in node._fields: # py < 2.6
- attr = 'decorators'
- else:
- attr = 'decorator_list'
- decorators = getattr(node, attr)
- if decorators:
- newnode.decorators = self.visit_decorators(node, newnode)
- newnode.set_line_info(newnode.last_child())
- self._global_names.pop()
- frame = newnode.parent.frame()
- if isinstance(frame, new.Class):
- if newnode.name == '__new__':
- newnode.type = 'classmethod'
- else:
- newnode.type = 'method'
- if newnode.decorators is not None:
- for decorator_expr in newnode.decorators.nodes:
- if isinstance(decorator_expr, new.Name):
- if decorator_expr.name in ('classmethod', 'staticmethod'):
- newnode.type = decorator_expr.name
- elif decorator_expr.name == 'classproperty':
- newnode.type = 'classmethod'
- frame.set_local(newnode.name, newnode)
- return newnode
-
- def visit_genexpr(self, node, parent):
- """visit a GenExpr node by returning a fresh instance of it"""
- newnode = new.GenExpr()
- _lineno_parent(node, newnode, parent)
- newnode.elt = self.visit(node.elt, newnode)
- newnode.generators = [self.visit(child, newnode) for child in node.generators]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_getattr(self, node, parent):
- """visit a Getattr node by returning a fresh instance of it"""
- if self.asscontext == "Del":
- # FIXME : maybe we should reintroduce and visit_delattr ?
- # for instance, deactivating asscontext
- newnode = new.DelAttr()
- elif self.asscontext == "Ass":
- # FIXME : maybe we should call visit_assattr ?
- newnode = new.AssAttr()
- self._delayed_assattr.append(newnode)
- else:
- newnode = new.Getattr()
- _lineno_parent(node, newnode, parent)
- asscontext, self.asscontext = self.asscontext, None
- newnode.expr = self.visit(node.value, newnode)
- self.asscontext = asscontext
- newnode.attrname = node.attr
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_global(self, node, parent):
- """visit an Global node to become astroid"""
- newnode = new.Global(node.names)
- _set_infos(node, newnode, parent)
- if self._global_names: # global at the module level, no effect
- for name in node.names:
- self._global_names[-1].setdefault(name, []).append(newnode)
- return newnode
-
- def visit_if(self, node, parent):
- """visit a If node by returning a fresh instance of it"""
- newnode = new.If()
- _lineno_parent(node, newnode, parent)
- newnode.test = self.visit(node.test, newnode)
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_ifexp(self, node, parent):
- """visit a IfExp node by returning a fresh instance of it"""
- newnode = new.IfExp()
- _lineno_parent(node, newnode, parent)
- newnode.test = self.visit(node.test, newnode)
- newnode.body = self.visit(node.body, newnode)
- newnode.orelse = self.visit(node.orelse, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_import(self, node, parent):
- """visit a Import node by returning a fresh instance of it"""
- newnode = new.Import()
- _set_infos(node, newnode, parent)
- newnode.names = [(alias.name, alias.asname) for alias in node.names]
- # save import names in parent's locals:
- for (name, asname) in newnode.names:
- name = asname or name
- newnode.parent.set_local(name.split('.')[0], newnode)
- return newnode
-
- def visit_index(self, node, parent):
- """visit a Index node by returning a fresh instance of it"""
- newnode = new.Index()
- _lineno_parent(node, newnode, parent)
- newnode.value = self.visit(node.value, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_keyword(self, node, parent):
- """visit a Keyword node by returning a fresh instance of it"""
- newnode = new.Keyword()
- _lineno_parent(node, newnode, parent)
- newnode.arg = node.arg
- newnode.value = self.visit(node.value, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_lambda(self, node, parent):
- """visit a Lambda node by returning a fresh instance of it"""
- newnode = new.Lambda()
- _lineno_parent(node, newnode, parent)
- newnode.args = self.visit(node.args, newnode)
- newnode.body = self.visit(node.body, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_list(self, node, parent):
- """visit a List node by returning a fresh instance of it"""
- newnode = new.List()
- _lineno_parent(node, newnode, parent)
- newnode.elts = [self.visit(child, newnode) for child in node.elts]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_listcomp(self, node, parent):
- """visit a ListComp node by returning a fresh instance of it"""
- newnode = new.ListComp()
- _lineno_parent(node, newnode, parent)
- newnode.elt = self.visit(node.elt, newnode)
- newnode.generators = [self.visit(child, newnode)
- for child in node.generators]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_name(self, node, parent):
- """visit a Name node by returning a fresh instance of it"""
- # True and False can be assigned to something in py2x, so we have to
- # check first the asscontext
- if self.asscontext == "Del":
- newnode = new.DelName()
- elif self.asscontext is not None: # Ass
- assert self.asscontext == "Ass"
- newnode = new.AssName()
- elif node.id in CONST_NAME_TRANSFORMS:
- newnode = new.Const(CONST_NAME_TRANSFORMS[node.id])
- _set_infos(node, newnode, parent)
- return newnode
- else:
- newnode = new.Name()
- _lineno_parent(node, newnode, parent)
- newnode.name = node.id
- # XXX REMOVE me :
- if self.asscontext in ('Del', 'Ass'): # 'Aug' ??
- self._save_assignment(newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_bytes(self, node, parent):
- """visit a Bytes node by returning a fresh instance of Const"""
- newnode = new.Const(node.s)
- _set_infos(node, newnode, parent)
- return newnode
-
- def visit_num(self, node, parent):
- """visit a Num node by returning a fresh instance of Const"""
- newnode = new.Const(node.n)
- _set_infos(node, newnode, parent)
- return newnode
-
- def visit_pass(self, node, parent):
- """visit a Pass node by returning a fresh instance of it"""
- newnode = new.Pass()
- _set_infos(node, newnode, parent)
- return newnode
-
- def visit_str(self, node, parent):
- """visit a Str node by returning a fresh instance of Const"""
- newnode = new.Const(node.s)
- _set_infos(node, newnode, parent)
- return newnode
-
- def visit_print(self, node, parent):
- """visit a Print node by returning a fresh instance of it"""
- newnode = new.Print()
- _lineno_parent(node, newnode, parent)
- newnode.nl = node.nl
- if node.dest is not None:
- newnode.dest = self.visit(node.dest, newnode)
- newnode.values = [self.visit(child, newnode) for child in node.values]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_raise(self, node, parent):
- """visit a Raise node by returning a fresh instance of it"""
- newnode = new.Raise()
- _lineno_parent(node, newnode, parent)
- if node.type is not None:
- newnode.exc = self.visit(node.type, newnode)
- if node.inst is not None:
- newnode.inst = self.visit(node.inst, newnode)
- if node.tback is not None:
- newnode.tback = self.visit(node.tback, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_return(self, node, parent):
- """visit a Return node by returning a fresh instance of it"""
- newnode = new.Return()
- _lineno_parent(node, newnode, parent)
- if node.value is not None:
- newnode.value = self.visit(node.value, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_set(self, node, parent):
- """visit a Set node by returning a fresh instance of it"""
- newnode = new.Set()
- _lineno_parent(node, newnode, parent)
- newnode.elts = [self.visit(child, newnode) for child in node.elts]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_setcomp(self, node, parent):
- """visit a SetComp node by returning a fresh instance of it"""
- newnode = new.SetComp()
- _lineno_parent(node, newnode, parent)
- newnode.elt = self.visit(node.elt, newnode)
- newnode.generators = [self.visit(child, newnode)
- for child in node.generators]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_slice(self, node, parent):
- """visit a Slice node by returning a fresh instance of it"""
- newnode = new.Slice()
- _lineno_parent(node, newnode, parent)
- if node.lower is not None:
- newnode.lower = self.visit(node.lower, newnode)
- if node.upper is not None:
- newnode.upper = self.visit(node.upper, newnode)
- if node.step is not None:
- newnode.step = self.visit(node.step, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_subscript(self, node, parent):
- """visit a Subscript node by returning a fresh instance of it"""
- newnode = new.Subscript()
- _lineno_parent(node, newnode, parent)
- subcontext, self.asscontext = self.asscontext, None
- newnode.value = self.visit(node.value, newnode)
- newnode.slice = self.visit(node.slice, newnode)
- self.asscontext = subcontext
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_tryexcept(self, node, parent):
- """visit a TryExcept node by returning a fresh instance of it"""
- newnode = new.TryExcept()
- _lineno_parent(node, newnode, parent)
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.handlers = [self.visit(child, newnode) for child in node.handlers]
- newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_tryfinally(self, node, parent):
- """visit a TryFinally node by returning a fresh instance of it"""
- newnode = new.TryFinally()
- _lineno_parent(node, newnode, parent)
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.finalbody = [self.visit(n, newnode) for n in node.finalbody]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_tuple(self, node, parent):
- """visit a Tuple node by returning a fresh instance of it"""
- newnode = new.Tuple()
- _lineno_parent(node, newnode, parent)
- newnode.elts = [self.visit(child, newnode) for child in node.elts]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_unaryop(self, node, parent):
- """visit a UnaryOp node by returning a fresh instance of it"""
- newnode = new.UnaryOp()
- _lineno_parent(node, newnode, parent)
- newnode.operand = self.visit(node.operand, newnode)
- newnode.op = _UNARY_OP_CLASSES[node.op.__class__]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_while(self, node, parent):
- """visit a While node by returning a fresh instance of it"""
- newnode = new.While()
- _lineno_parent(node, newnode, parent)
- newnode.test = self.visit(node.test, newnode)
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_with(self, node, parent):
- newnode = new.With()
- _lineno_parent(node, newnode, parent)
- expr = self.visit(node.context_expr, newnode)
- self.asscontext = "Ass"
- if node.optional_vars is not None:
- vars = self.visit(node.optional_vars, newnode)
- else:
- vars = None
- self.asscontext = None
- newnode.items = [(expr, vars)]
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_yield(self, node, parent):
- """visit a Yield node by returning a fresh instance of it"""
- newnode = new.Yield()
- _lineno_parent(node, newnode, parent)
- if node.value is not None:
- newnode.value = self.visit(node.value, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
-
-class TreeRebuilder3k(TreeRebuilder):
- """extend and overwrite TreeRebuilder for python3k"""
-
- def visit_arg(self, node, parent):
- """visit a arg node by returning a fresh AssName instance"""
- # the node is coming from py>=3.0, but we use AssName in py2.x
- # XXX or we should instead introduce a Arg node in astroid ?
- return self.visit_assname(node, parent, node.arg)
-
- def visit_arguments(self, node, parent):
- newnode = super(TreeRebuilder3k, self).visit_arguments(node, parent)
- self.asscontext = "Ass"
- newnode.kwonlyargs = [self.visit(child, newnode) for child in node.kwonlyargs]
- self.asscontext = None
- newnode.kw_defaults = [self.visit(child, newnode) if child else None for child in node.kw_defaults]
- return newnode
-
- def visit_excepthandler(self, node, parent):
- """visit an ExceptHandler node by returning a fresh instance of it"""
- newnode = new.ExceptHandler()
- _lineno_parent(node, newnode, parent)
- if node.type is not None:
- newnode.type = self.visit(node.type, newnode)
- if node.name is not None:
- newnode.name = self.visit_assname(node, newnode, node.name)
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_nonlocal(self, node, parent):
- """visit a Nonlocal node and return a new instance of it"""
- newnode = new.Nonlocal(node.names)
- _set_infos(node, newnode, parent)
- return newnode
-
- def visit_raise(self, node, parent):
- """visit a Raise node by returning a fresh instance of it"""
- newnode = new.Raise()
- _lineno_parent(node, newnode, parent)
- # no traceback; anyway it is not used in Pylint
- if node.exc is not None:
- newnode.exc = self.visit(node.exc, newnode)
- if node.cause is not None:
- newnode.cause = self.visit(node.cause, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_starred(self, node, parent):
- """visit a Starred node and return a new instance of it"""
- newnode = new.Starred()
- _lineno_parent(node, newnode, parent)
- newnode.value = self.visit(node.value, newnode)
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_try(self, node, parent):
- # python 3.3 introduce a new Try node replacing TryFinally/TryExcept nodes
- if node.finalbody:
- newnode = new.TryFinally()
- _lineno_parent(node, newnode, parent)
- newnode.finalbody = [self.visit(n, newnode) for n in node.finalbody]
- if node.handlers:
- excnode = new.TryExcept()
- _lineno_parent(node, excnode, newnode)
- excnode.body = [self.visit(child, excnode) for child in node.body]
- excnode.handlers = [self.visit(child, excnode) for child in node.handlers]
- excnode.orelse = [self.visit(child, excnode) for child in node.orelse]
- excnode.set_line_info(excnode.last_child())
- newnode.body = [excnode]
- else:
- newnode.body = [self.visit(child, newnode) for child in node.body]
- elif node.handlers:
- newnode = new.TryExcept()
- _lineno_parent(node, newnode, parent)
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.handlers = [self.visit(child, newnode) for child in node.handlers]
- newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_with(self, node, parent):
- if 'items' not in node._fields:
- # python < 3.3
- return super(TreeRebuilder3k, self).visit_with(node, parent)
-
- newnode = new.With()
- _lineno_parent(node, newnode, parent)
- def visit_child(child):
- expr = self.visit(child.context_expr, newnode)
- self.asscontext = 'Ass'
- if child.optional_vars:
- var = self.visit(child.optional_vars, newnode)
- else:
- var = None
- self.asscontext = None
- return expr, var
- newnode.items = [visit_child(child)
- for child in node.items]
- newnode.body = [self.visit(child, newnode) for child in node.body]
- newnode.set_line_info(newnode.last_child())
- return newnode
-
- def visit_yieldfrom(self, node, parent):
- return self.visit_yield(node, parent)
-
-if sys.version_info >= (3, 0):
- TreeRebuilder = TreeRebuilder3k
-
-
diff -Nru astroid-1.0.1/scoped_nodes.py astroid-1.3.8/scoped_nodes.py
--- astroid-1.0.1/scoped_nodes.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/scoped_nodes.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,992 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""This module contains the classes for "scoped" node, i.e. which are opening a
-new local scope in the language definition : Module, Class, Function (and
-Lambda, GenExpr, DictComp and SetComp to some extent).
-"""
-from __future__ import with_statement
-
-__doctype__ = "restructuredtext en"
-
-import sys
-from itertools import chain
-
-from logilab.common.compat import builtins
-from logilab.common.decorators import cached
-
-from astroid.exceptions import NotFoundError, \
- AstroidBuildingException, InferenceError
-from astroid.node_classes import Const, DelName, DelAttr, \
- Dict, From, List, Pass, Raise, Return, Tuple, Yield, \
- LookupMixIn, const_factory as cf, unpack_infer
-from astroid.bases import NodeNG, InferenceContext, Instance,\
- YES, Generator, UnboundMethod, BoundMethod, _infer_stmts, copy_context, \
- BUILTINS
-from astroid.mixins import FilterStmtsMixin
-from astroid.bases import Statement
-from astroid.manager import AstroidManager
-
-
-def remove_nodes(func, cls):
- def wrapper(*args, **kwargs):
- nodes = [n for n in func(*args, **kwargs) if not isinstance(n, cls)]
- if not nodes:
- raise NotFoundError()
- return nodes
- return wrapper
-
-
-def function_to_method(n, klass):
- if isinstance(n, Function):
- if n.type == 'classmethod':
- return BoundMethod(n, klass)
- if n.type != 'staticmethod':
- return UnboundMethod(n)
- return n
-
-def std_special_attributes(self, name, add_locals=True):
- if add_locals:
- locals = self.locals
- else:
- locals = {}
- if name == '__name__':
- return [cf(self.name)] + locals.get(name, [])
- if name == '__doc__':
- return [cf(self.doc)] + locals.get(name, [])
- if name == '__dict__':
- return [Dict()] + locals.get(name, [])
- raise NotFoundError(name)
-
-MANAGER = AstroidManager()
-def builtin_lookup(name):
- """lookup a name into the builtin module
- return the list of matching statements and the astroid for the builtin
- module
- """
- builtin_astroid = MANAGER.ast_from_module(builtins)
- if name == '__dict__':
- return builtin_astroid, ()
- try:
- stmts = builtin_astroid.locals[name]
- except KeyError:
- stmts = ()
- return builtin_astroid, stmts
-
-
-# TODO move this Mixin to mixins.py; problem: 'Function' in _scope_lookup
-class LocalsDictNodeNG(LookupMixIn, NodeNG):
- """ this class provides locals handling common to Module, Function
- and Class nodes, including a dict like interface for direct access
- to locals information
- """
-
- # attributes below are set by the builder module or by raw factories
-
- # dictionary of locals with name as key and node defining the local as
- # value
-
- def qname(self):
- """return the 'qualified' name of the node, eg module.name,
- module.class.name ...
- """
- if self.parent is None:
- return self.name
- return '%s.%s' % (self.parent.frame().qname(), self.name)
-
- def frame(self):
- """return the first parent frame node (i.e. Module, Function or Class)
- """
- return self
-
- def scope(self):
- """return the first node defining a new scope (i.e. Module,
- Function, Class, Lambda but also GenExpr, DictComp and SetComp)
- """
- return self
-
-
- def _scope_lookup(self, node, name, offset=0):
- """XXX method for interfacing the scope lookup"""
- try:
- stmts = node._filter_stmts(self.locals[name], self, offset)
- except KeyError:
- stmts = ()
- if stmts:
- return self, stmts
- if self.parent: # i.e. not Module
- # nested scope: if parent scope is a function, that's fine
- # else jump to the module
- pscope = self.parent.scope()
- if not pscope.is_function:
- pscope = pscope.root()
- return pscope.scope_lookup(node, name)
- return builtin_lookup(name) # Module
-
-
-
- def set_local(self, name, stmt):
- """define in locals ( is the node defining the name)
- if the node is a Module node (i.e. has globals), add the name to
- globals
-
- if the name is already defined, ignore it
- """
- #assert not stmt in self.locals.get(name, ()), (self, stmt)
- self.locals.setdefault(name, []).append(stmt)
-
- __setitem__ = set_local
-
- def _append_node(self, child):
- """append a child, linking it in the tree"""
- self.body.append(child)
- child.parent = self
-
- def add_local_node(self, child_node, name=None):
- """append a child which should alter locals to the given node"""
- if name != '__class__':
- # add __class__ node as a child will cause infinite recursion later!
- self._append_node(child_node)
- self.set_local(name or child_node.name, child_node)
-
-
- def __getitem__(self, item):
- """method from the `dict` interface returning the first node
- associated with the given name in the locals dictionary
-
- :type item: str
- :param item: the name of the locally defined object
- :raises KeyError: if the name is not defined
- """
- return self.locals[item][0]
-
- def __iter__(self):
- """method from the `dict` interface returning an iterator on
- `self.keys()`
- """
- return iter(self.keys())
-
- def keys(self):
- """method from the `dict` interface returning a tuple containing
- locally defined names
- """
- return self.locals.keys()
-
- def values(self):
- """method from the `dict` interface returning a tuple containing
- locally defined nodes which are instance of `Function` or `Class`
- """
- return [self[key] for key in self.keys()]
-
- def items(self):
- """method from the `dict` interface returning a list of tuple
- containing each locally defined name with its associated node,
- which is an instance of `Function` or `Class`
- """
- return zip(self.keys(), self.values())
-
-
- def __contains__(self, name):
- return name in self.locals
- has_key = __contains__
-
-# Module #####################################################################
-
-class Module(LocalsDictNodeNG):
- _astroid_fields = ('body',)
-
- fromlineno = 0
- lineno = 0
-
- # attributes below are set by the builder module or by raw factories
-
- # the file from which as been extracted the astroid representation. It may
- # be None if the representation has been built from a built-in module
- file = None
- # encoding of python source file, so we can get unicode out of it (python2
- # only)
- file_encoding = None
- # the module name
- name = None
- # boolean for astroid built from source (i.e. ast)
- pure_python = None
- # boolean for package module
- package = None
- # dictionary of globals with name as key and node defining the global
- # as value
- globals = None
-
- # names of python special attributes (handled by getattr impl.)
- special_attributes = set(('__name__', '__doc__', '__file__', '__path__',
- '__dict__'))
- # names of module attributes available through the global scope
- scope_attrs = set(('__name__', '__doc__', '__file__', '__path__'))
-
- def __init__(self, name, doc, pure_python=True):
- self.name = name
- self.doc = doc
- self.pure_python = pure_python
- self.locals = self.globals = {}
- self.body = []
-
- @property
- def file_stream(self):
- if self.file is not None:
- return open(self.file, 'rb')
- return None
-
- def block_range(self, lineno):
- """return block line numbers.
-
- start from the beginning whatever the given lineno
- """
- return self.fromlineno, self.tolineno
-
- def scope_lookup(self, node, name, offset=0):
- if name in self.scope_attrs and not name in self.locals:
- try:
- return self, self.getattr(name)
- except NotFoundError:
- return self, ()
- return self._scope_lookup(node, name, offset)
-
- def pytype(self):
- return '%s.module' % BUILTINS
-
- def display_type(self):
- return 'Module'
-
- def getattr(self, name, context=None, ignore_locals=False):
- if name in self.special_attributes:
- if name == '__file__':
- return [cf(self.file)] + self.locals.get(name, [])
- if name == '__path__' and self.package:
- return [List()] + self.locals.get(name, [])
- return std_special_attributes(self, name)
- if not ignore_locals and name in self.locals:
- return self.locals[name]
- if self.package:
- try:
- return [self.import_module(name, relative_only=True)]
- except AstroidBuildingException:
- raise NotFoundError(name)
- except Exception:# XXX pylint tests never pass here; do we need it?
- import traceback
- traceback.print_exc()
- raise NotFoundError(name)
- getattr = remove_nodes(getattr, DelName)
-
- def igetattr(self, name, context=None):
- """inferred getattr"""
- # set lookup name since this is necessary to infer on import nodes for
- # instance
- context = copy_context(context)
- context.lookupname = name
- try:
- return _infer_stmts(self.getattr(name, context), context, frame=self)
- except NotFoundError:
- raise InferenceError(name)
-
- def fully_defined(self):
- """return True if this module has been built from a .py file
- and so contains a complete representation including the code
- """
- return self.file is not None and self.file.endswith('.py')
-
- def statement(self):
- """return the first parent node marked as statement node
- consider a module as a statement...
- """
- return self
-
- def previous_sibling(self):
- """module has no sibling"""
- return
-
- def next_sibling(self):
- """module has no sibling"""
- return
-
- if sys.version_info < (2, 8):
- def absolute_import_activated(self):
- for stmt in self.locals.get('absolute_import', ()):
- if isinstance(stmt, From) and stmt.modname == '__future__':
- return True
- return False
- else:
- absolute_import_activated = lambda self: True
-
- def import_module(self, modname, relative_only=False, level=None):
- """import the given module considering self as context"""
- if relative_only and level is None:
- level = 0
- absmodname = self.relative_to_absolute_name(modname, level)
- try:
- return MANAGER.ast_from_module_name(absmodname)
- except AstroidBuildingException:
- # we only want to import a sub module or package of this module,
- # skip here
- if relative_only:
- raise
- return MANAGER.ast_from_module_name(modname)
-
- def relative_to_absolute_name(self, modname, level):
- """return the absolute module name for a relative import.
-
- The relative import can be implicit or explicit.
- """
- # XXX this returns non sens when called on an absolute import
- # like 'pylint.checkers.astroid.utils'
- # XXX doesn't return absolute name if self.name isn't absolute name
- if self.absolute_import_activated() and level is None:
- return modname
- if level:
- if self.package:
- level = level - 1
- package_name = self.name.rsplit('.', level)[0]
- elif self.package:
- package_name = self.name
- else:
- package_name = self.name.rsplit('.', 1)[0]
- if package_name:
- if not modname:
- return package_name
- return '%s.%s' % (package_name, modname)
- return modname
-
-
- def wildcard_import_names(self):
- """return the list of imported names when this module is 'wildcard
- imported'
-
- It doesn't include the '__builtins__' name which is added by the
- current CPython implementation of wildcard imports.
- """
- # take advantage of a living module if it exists
- try:
- living = sys.modules[self.name]
- except KeyError:
- pass
- else:
- try:
- return living.__all__
- except AttributeError:
- return [name for name in living.__dict__.keys()
- if not name.startswith('_')]
- # else lookup the astroid
- #
- # We separate the different steps of lookup in try/excepts
- # to avoid catching too many Exceptions
- # However, we can not analyse dynamically constructed __all__
- try:
- all = self['__all__']
- except KeyError:
- return [name for name in self.keys() if not name.startswith('_')]
- try:
- explicit = all.assigned_stmts().next()
- except InferenceError:
- return [name for name in self.keys() if not name.startswith('_')]
- except AttributeError:
- # not an assignment node
- # XXX infer?
- return [name for name in self.keys() if not name.startswith('_')]
- try:
- # should be a Tuple/List of constant string / 1 string not allowed
- return [const.value for const in explicit.elts]
- except AttributeError:
- return [name for name in self.keys() if not name.startswith('_')]
-
-
-class ComprehensionScope(LocalsDictNodeNG):
- def frame(self):
- return self.parent.frame()
-
- scope_lookup = LocalsDictNodeNG._scope_lookup
-
-
-class GenExpr(ComprehensionScope):
- _astroid_fields = ('elt', 'generators')
-
- def __init__(self):
- self.locals = {}
- self.elt = None
- self.generators = []
-
-
-class DictComp(ComprehensionScope):
- _astroid_fields = ('key', 'value', 'generators')
-
- def __init__(self):
- self.locals = {}
- self.key = None
- self.value = None
- self.generators = []
-
-
-class SetComp(ComprehensionScope):
- _astroid_fields = ('elt', 'generators')
-
- def __init__(self):
- self.locals = {}
- self.elt = None
- self.generators = []
-
-
-class _ListComp(NodeNG):
- """class representing a ListComp node"""
- _astroid_fields = ('elt', 'generators')
- elt = None
- generators = None
-
-if sys.version_info >= (3, 0):
- class ListComp(_ListComp, ComprehensionScope):
- """class representing a ListComp node"""
- def __init__(self):
- self.locals = {}
-else:
- class ListComp(_ListComp):
- """class representing a ListComp node"""
-
-# Function ###################################################################
-
-
-class Lambda(LocalsDictNodeNG, FilterStmtsMixin):
- _astroid_fields = ('args', 'body',)
- name = ''
-
- # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod'
- type = 'function'
-
- def __init__(self):
- self.locals = {}
- self.args = []
- self.body = []
-
- def pytype(self):
- if 'method' in self.type:
- return '%s.instancemethod' % BUILTINS
- return '%s.function' % BUILTINS
-
- def display_type(self):
- if 'method' in self.type:
- return 'Method'
- return 'Function'
-
- def callable(self):
- return True
-
- def argnames(self):
- """return a list of argument names"""
- if self.args.args: # maybe None with builtin functions
- names = _rec_get_names(self.args.args)
- else:
- names = []
- if self.args.vararg:
- names.append(self.args.vararg)
- if self.args.kwarg:
- names.append(self.args.kwarg)
- return names
-
- def infer_call_result(self, caller, context=None):
- """infer what a function is returning when called"""
- return self.body.infer(context)
-
- def scope_lookup(self, node, name, offset=0):
- if node in self.args.defaults or node in self.args.kw_defaults:
- frame = self.parent.frame()
- # line offset to avoid that def func(f=func) resolve the default
- # value to the defined function
- offset = -1
- else:
- # check this is not used in function decorators
- frame = self
- return frame._scope_lookup(node, name, offset)
-
-
-class Function(Statement, Lambda):
- _astroid_fields = ('decorators', 'args', 'body')
-
- special_attributes = set(('__name__', '__doc__', '__dict__'))
- is_function = True
- # attributes below are set by the builder module or by raw factories
- blockstart_tolineno = None
- decorators = None
-
- def __init__(self, name, doc):
- self.locals = {}
- self.args = []
- self.body = []
- self.decorators = None
- self.name = name
- self.doc = doc
- self.extra_decorators = []
- self.instance_attrs = {}
-
- def set_line_info(self, lastchild):
- self.fromlineno = self.lineno
- # lineno is the line number of the first decorator, we want the def statement lineno
- if self.decorators is not None:
- self.fromlineno += sum(node.tolineno - node.lineno + 1
- for node in self.decorators.nodes)
- if self.args.fromlineno < self.fromlineno:
- self.args.fromlineno = self.fromlineno
- self.tolineno = lastchild.tolineno
- self.blockstart_tolineno = self.args.tolineno
-
- def block_range(self, lineno):
- """return block line numbers.
-
- start from the "def" position whatever the given lineno
- """
- return self.fromlineno, self.tolineno
-
- def getattr(self, name, context=None):
- """this method doesn't look in the instance_attrs dictionary since it's
- done by an Instance proxy at inference time.
- """
- if name == '__module__':
- return [cf(self.root().qname())]
- if name in self.instance_attrs:
- return self.instance_attrs[name]
- return std_special_attributes(self, name, False)
-
- def is_method(self):
- """return true if the function node should be considered as a method"""
- # check we are defined in a Class, because this is usually expected
- # (e.g. pylint...) when is_method() return True
- return self.type != 'function' and isinstance(self.parent.frame(), Class)
-
- def decoratornames(self):
- """return a list of decorator qualified names"""
- result = set()
- decoratornodes = []
- if self.decorators is not None:
- decoratornodes += self.decorators.nodes
- decoratornodes += self.extra_decorators
- for decnode in decoratornodes:
- for infnode in decnode.infer():
- result.add(infnode.qname())
- return result
- decoratornames = cached(decoratornames)
-
- def is_bound(self):
- """return true if the function is bound to an Instance or a class"""
- return self.type == 'classmethod'
-
- def is_abstract(self, pass_is_abstract=True):
- """Returns True if the method is abstract.
-
- A method is considered abstract if
- - the only statement is 'raise NotImplementedError', or
- - the only statement is 'pass' and pass_is_abstract is True, or
- - the method is annotated with abc.astractproperty/abc.abstractmethod
- """
- if self.decorators:
- for node in self.decorators.nodes:
- try:
- infered = node.infer().next()
- except InferenceError:
- continue
- if infered and infered.qname() in ('abc.abstractproperty',
- 'abc.abstractmethod'):
- return True
-
- for child_node in self.body:
- if isinstance(child_node, Raise):
- if child_node.raises_not_implemented():
- return True
- if pass_is_abstract and isinstance(child_node, Pass):
- return True
- return False
- # empty function is the same as function with a single "pass" statement
- if pass_is_abstract:
- return True
-
- def is_generator(self):
- """return true if this is a generator function"""
- # XXX should be flagged, not computed
- try:
- return self.nodes_of_class(Yield, skip_klass=(Function, Lambda)).next()
- except StopIteration:
- return False
-
- def infer_call_result(self, caller, context=None):
- """infer what a function is returning when called"""
- if self.is_generator():
- yield Generator()
- return
- returns = self.nodes_of_class(Return, skip_klass=Function)
- for returnnode in returns:
- if returnnode.value is None:
- yield Const(None)
- else:
- try:
- for infered in returnnode.value.infer(context):
- yield infered
- except InferenceError:
- yield YES
-
-
-def _rec_get_names(args, names=None):
- """return a list of all argument names"""
- if names is None:
- names = []
- for arg in args:
- if isinstance(arg, Tuple):
- _rec_get_names(arg.elts, names)
- else:
- names.append(arg.name)
- return names
-
-
-# Class ######################################################################
-
-def _class_type(klass, ancestors=None):
- """return a Class node type to differ metaclass, interface and exception
- from 'regular' classes
- """
- # XXX we have to store ancestors in case we have a ancestor loop
- if klass._type is not None:
- return klass._type
- if klass.name == 'type':
- klass._type = 'metaclass'
- elif klass.name.endswith('Interface'):
- klass._type = 'interface'
- elif klass.name.endswith('Exception'):
- klass._type = 'exception'
- else:
- if ancestors is None:
- ancestors = set()
- if klass in ancestors:
- # XXX we are in loop ancestors, and have found no type
- klass._type = 'class'
- return 'class'
- ancestors.add(klass)
- # print >> sys.stderr, '_class_type', repr(klass)
- for base in klass.ancestors(recurs=False):
- if _class_type(base, ancestors) != 'class':
- klass._type = base.type
- break
- if klass._type is None:
- klass._type = 'class'
- return klass._type
-
-def _iface_hdlr(iface_node):
- """a handler function used by interfaces to handle suspicious
- interface nodes
- """
- return True
-
-
-class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
-
- # some of the attributes below are set by the builder module or
- # by a raw factories
-
- # a dictionary of class instances attributes
- _astroid_fields = ('decorators', 'bases', 'body') # name
-
- decorators = None
- special_attributes = set(('__name__', '__doc__', '__dict__', '__module__',
- '__bases__', '__mro__', '__subclasses__'))
- blockstart_tolineno = None
-
- _type = None
- type = property(_class_type,
- doc="class'type, possible values are 'class' | "
- "'metaclass' | 'interface' | 'exception'")
-
- def __init__(self, name, doc):
- self.instance_attrs = {}
- self.locals = {}
- self.bases = []
- self.body = []
- self.name = name
- self.doc = doc
-
- def _newstyle_impl(self, context=None):
- if context is None:
- context = InferenceContext()
- if self._newstyle is not None:
- return self._newstyle
- for base in self.ancestors(recurs=False, context=context):
- if base._newstyle_impl(context):
- self._newstyle = True
- break
- if self._newstyle is None:
- self._newstyle = False
- return self._newstyle
-
- _newstyle = None
- newstyle = property(_newstyle_impl,
- doc="boolean indicating if it's a new style class"
- "or not")
-
- def set_line_info(self, lastchild):
- self.fromlineno = self.lineno
- self.blockstart_tolineno = self.bases and self.bases[-1].tolineno or self.fromlineno
- if lastchild is not None:
- self.tolineno = lastchild.tolineno
- # else this is a class with only a docstring, then tolineno is (should be) already ok
-
- def block_range(self, lineno):
- """return block line numbers.
-
- start from the "class" position whatever the given lineno
- """
- return self.fromlineno, self.tolineno
-
- def pytype(self):
- if self.newstyle:
- return '%s.type' % BUILTINS
- return '%s.classobj' % BUILTINS
-
- def display_type(self):
- return 'Class'
-
- def callable(self):
- return True
-
- def infer_call_result(self, caller, context=None):
- """infer what a class is returning when called"""
- yield Instance(self)
-
- def scope_lookup(self, node, name, offset=0):
- if node in self.bases:
- frame = self.parent.frame()
- # line offset to avoid that class A(A) resolve the ancestor to
- # the defined class
- offset = -1
- else:
- frame = self
- return frame._scope_lookup(node, name, offset)
-
- # list of parent class as a list of string (i.e. names as they appear
- # in the class definition) XXX bw compat
- def basenames(self):
- return [bnode.as_string() for bnode in self.bases]
- basenames = property(basenames)
-
- def ancestors(self, recurs=True, context=None):
- """return an iterator on the node base classes in a prefixed
- depth first order
-
- :param recurs:
- boolean indicating if it should recurse or return direct
- ancestors only
- """
- # FIXME: should be possible to choose the resolution order
- # XXX inference make infinite loops possible here (see BaseTransformer
- # manipulation in the builder module for instance)
- yielded = set([self])
- if context is None:
- context = InferenceContext()
- for stmt in self.bases:
- with context.restore_path():
- try:
- for baseobj in stmt.infer(context):
- if not isinstance(baseobj, Class):
- # duh ?
- continue
- if baseobj in yielded:
- continue # cf xxx above
- yielded.add(baseobj)
- yield baseobj
- if recurs:
- for grandpa in baseobj.ancestors(True, context):
- if grandpa in yielded:
- continue # cf xxx above
- yielded.add(grandpa)
- yield grandpa
- except InferenceError:
- # XXX log error ?
- continue
-
- def local_attr_ancestors(self, name, context=None):
- """return an iterator on astroid representation of parent classes
- which have defined in their locals
- """
- for astroid in self.ancestors(context=context):
- if name in astroid:
- yield astroid
-
- def instance_attr_ancestors(self, name, context=None):
- """return an iterator on astroid representation of parent classes
- which have defined in their instance attribute dictionary
- """
- for astroid in self.ancestors(context=context):
- if name in astroid.instance_attrs:
- yield astroid
-
- def has_base(self, node):
- return node in self.bases
-
- def local_attr(self, name, context=None):
- """return the list of assign node associated to name in this class
- locals or in its parents
-
- :raises `NotFoundError`:
- if no attribute with this name has been find in this class or
- its parent classes
- """
- try:
- return self.locals[name]
- except KeyError:
- # get if from the first parent implementing it if any
- for class_node in self.local_attr_ancestors(name, context):
- return class_node.locals[name]
- raise NotFoundError(name)
- local_attr = remove_nodes(local_attr, DelAttr)
-
- def instance_attr(self, name, context=None):
- """return the astroid nodes associated to name in this class instance
- attributes dictionary and in its parents
-
- :raises `NotFoundError`:
- if no attribute with this name has been find in this class or
- its parent classes
- """
- values = self.instance_attrs.get(name, [])
- # get all values from parents
- for class_node in self.instance_attr_ancestors(name, context):
- values += class_node.instance_attrs[name]
- if not values:
- raise NotFoundError(name)
- return values
- instance_attr = remove_nodes(instance_attr, DelAttr)
-
- def instanciate_class(self):
- """return Instance of Class node, else return self"""
- return Instance(self)
-
- def getattr(self, name, context=None):
- """this method doesn't look in the instance_attrs dictionary since it's
- done by an Instance proxy at inference time.
-
- It may return a YES object if the attribute has not been actually
- found but a __getattr__ or __getattribute__ method is defined
- """
- values = self.locals.get(name, [])
- if name in self.special_attributes:
- if name == '__module__':
- return [cf(self.root().qname())] + values
- # FIXME: do we really need the actual list of ancestors?
- # returning [Tuple()] + values don't break any test
- # this is ticket http://www.logilab.org/ticket/52785
- # XXX need proper meta class handling + MRO implementation
- if name == '__bases__' or (name == '__mro__' and self.newstyle):
- node = Tuple()
- node.items = self.ancestors(recurs=True, context=context)
- return [node] + values
- return std_special_attributes(self, name)
- # don't modify the list in self.locals!
- values = list(values)
- for classnode in self.ancestors(recurs=True, context=context):
- values += classnode.locals.get(name, [])
- if not values:
- raise NotFoundError(name)
- return values
-
- def igetattr(self, name, context=None):
- """inferred getattr, need special treatment in class to handle
- descriptors
- """
- # set lookup name since this is necessary to infer on import nodes for
- # instance
- context = copy_context(context)
- context.lookupname = name
- try:
- for infered in _infer_stmts(self.getattr(name, context), context,
- frame=self):
- # yield YES object instead of descriptors when necessary
- if not isinstance(infered, Const) and isinstance(infered, Instance):
- try:
- infered._proxied.getattr('__get__', context)
- except NotFoundError:
- yield infered
- else:
- yield YES
- else:
- yield function_to_method(infered, self)
- except NotFoundError:
- if not name.startswith('__') and self.has_dynamic_getattr(context):
- # class handle some dynamic attributes, return a YES object
- yield YES
- else:
- raise InferenceError(name)
-
- def has_dynamic_getattr(self, context=None):
- """return True if the class has a custom __getattr__ or
- __getattribute__ method
- """
- # need to explicitly handle optparse.Values (setattr is not detected)
- if self.name == 'Values' and self.root().name == 'optparse':
- return True
- try:
- self.getattr('__getattr__', context)
- return True
- except NotFoundError:
- #if self.newstyle: XXX cause an infinite recursion error
- try:
- getattribute = self.getattr('__getattribute__', context)[0]
- if getattribute.root().name != BUILTINS:
- # class has a custom __getattribute__ defined
- return True
- except NotFoundError:
- pass
- return False
-
- def methods(self):
- """return an iterator on all methods defined in the class and
- its ancestors
- """
- done = {}
- for astroid in chain(iter((self,)), self.ancestors()):
- for meth in astroid.mymethods():
- if meth.name in done:
- continue
- done[meth.name] = None
- yield meth
-
- def mymethods(self):
- """return an iterator on all methods defined in the class"""
- for member in self.values():
- if isinstance(member, Function):
- yield member
-
- def interfaces(self, herited=True, handler_func=_iface_hdlr):
- """return an iterator on interfaces implemented by the given
- class node
- """
- # FIXME: what if __implements__ = (MyIFace, MyParent.__implements__)...
- try:
- implements = Instance(self).getattr('__implements__')[0]
- except NotFoundError:
- return
- if not herited and not implements.frame() is self:
- return
- found = set()
- missing = False
- for iface in unpack_infer(implements):
- if iface is YES:
- missing = True
- continue
- if not iface in found and handler_func(iface):
- found.add(iface)
- yield iface
- if missing:
- raise InferenceError()
diff -Nru astroid-1.0.1/setup.cfg astroid-1.3.8/setup.cfg
--- astroid-1.0.1/setup.cfg 2013-10-18 15:34:22.000000000 +0000
+++ astroid-1.3.8/setup.cfg 2015-08-02 20:40:06.000000000 +0000
@@ -1,5 +1,8 @@
-[egg_info]
-tag_build =
-tag_date = 0
-tag_svn_revision = 0
-
+[wheel]
+universal = 1
+
+[egg_info]
+tag_build =
+tag_date = 0
+tag_svn_revision = 0
+
diff -Nru astroid-1.0.1/setup.py astroid-1.3.8/setup.py
--- astroid-1.0.1/setup.py 2013-10-18 15:34:05.000000000 +0000
+++ astroid-1.3.8/setup.py 2015-03-09 22:00:27.000000000 +0000
@@ -17,152 +17,28 @@
#
# You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see .
-"""Generic Setup script, takes package info from __pkginfo__.py file.
-"""
-__docformat__ = "restructuredtext en"
-
+"""Setup script for astroid."""
import os
-import sys
-import shutil
-from os.path import isdir, exists, join
-
-try:
- if os.environ.get('NO_SETUPTOOLS'):
- raise ImportError()
- from setuptools import setup
- from setuptools.command import install_lib
- USE_SETUPTOOLS = 1
-except ImportError:
- from distutils.core import setup
- from distutils.command import install_lib
- USE_SETUPTOOLS = 0
-
-try:
- # python3
- from distutils.command.build_py import build_py_2to3 as build_py
-except ImportError:
- # python2.x
- from distutils.command.build_py import build_py
-
-sys.modules.pop('__pkginfo__', None)
-# import optional features
-__pkginfo__ = __import__("__pkginfo__")
-# import required features
-from __pkginfo__ import modname, version, license, description, \
- web, author, author_email
-
-distname = getattr(__pkginfo__, 'distname', modname)
-scripts = getattr(__pkginfo__, 'scripts', [])
-data_files = getattr(__pkginfo__, 'data_files', None)
-subpackage_of = getattr(__pkginfo__, 'subpackage_of', None)
-include_dirs = getattr(__pkginfo__, 'include_dirs', [])
-ext_modules = getattr(__pkginfo__, 'ext_modules', None)
-install_requires = getattr(__pkginfo__, 'install_requires', None)
-dependency_links = getattr(__pkginfo__, 'dependency_links', [])
-classifiers = getattr(__pkginfo__, 'classifiers', [])
-
-STD_BLACKLIST = ('CVS', '.svn', '.hg', 'debian', 'dist', 'build')
-
-IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc', '~')
-
-if exists('README'):
- long_description = open('README').read()
-else:
- long_description = ''
-
-def ensure_scripts(linux_scripts):
- """Creates the proper script names required for each platform
- (taken from 4Suite)
- """
- from distutils import util
- if util.get_platform()[:3] == 'win':
- scripts_ = [script + '.bat' for script in linux_scripts]
- else:
- scripts_ = linux_scripts
- return scripts_
-
-def get_packages(directory, prefix):
- """return a list of subpackages for the given directory"""
- result = []
- for package in os.listdir(directory):
- absfile = join(directory, package)
- if isdir(absfile):
- if exists(join(absfile, '__init__.py')) or \
- package in ('test', 'tests'):
- if prefix:
- result.append('%s.%s' % (prefix, package))
- else:
- result.append(package)
- result += get_packages(absfile, result[-1])
- return result
-
-EMPTY_FILE = '''"""generated file, don't modify or your data will be lost"""
-try:
- __import__('pkg_resources').declare_namespace(__name__)
-except ImportError:
- pass
-'''
-
-class MyInstallLib(install_lib.install_lib):
- """extend install_lib command to handle package __init__.py if necessary
- """
- def run(self):
- """overridden from install_lib class"""
- install_lib.install_lib.run(self)
- # create Products.__init__.py if needed
- if subpackage_of:
- product_init = join(self.install_dir, subpackage_of, '__init__.py')
- if not exists(product_init):
- self.announce('creating %s' % product_init)
- stream = open(product_init, 'w')
- stream.write(EMPTY_FILE)
- stream.close()
-
-
-class MyBuildPy(build_py):
- """extend build_by command to handle include_dirs variable if necessary
- """
- def run(self):
- """overridden from install_lib class"""
- build_py.run(self)
- # manually install included directories if any
- if include_dirs:
- if subpackage_of:
- base = join(subpackage_of, modname)
- else:
- base = modname
- basedir = os.path.join(self.build_lib, base)
- for directory in include_dirs:
- dest = join(basedir, directory)
- shutil.rmtree(dest, ignore_errors=True)
- shutil.copytree(directory, dest)
- if sys.version_info >= (3, 0):
- # process manually python file in include_dirs (test data)
- from distutils.util import run_2to3
- print('running 2to3 on', dest)
- run_2to3([dest])
-
-def install(**kwargs):
- """setup entry point"""
- if USE_SETUPTOOLS:
- if '--force-manifest' in sys.argv:
- sys.argv.remove('--force-manifest')
- # install-layout option was introduced in 2.5.3-1~exp1
- elif sys.version_info < (2, 5, 4) and '--install-layout=deb' in sys.argv:
- sys.argv.remove('--install-layout=deb')
- if subpackage_of:
- package = subpackage_of + '.' + modname
- kwargs['package_dir'] = {package : '.'}
- packages = [package] + get_packages(os.getcwd(), package)
- if USE_SETUPTOOLS:
- kwargs['namespace_packages'] = [subpackage_of]
- else:
- kwargs['package_dir'] = {modname : '.'}
- packages = [modname] + get_packages(os.getcwd(), modname)
- if USE_SETUPTOOLS and install_requires:
- kwargs['install_requires'] = install_requires
- kwargs['dependency_links'] = dependency_links
- kwargs['packages'] = packages
+from setuptools import setup, find_packages
+from setuptools.command import install_lib
+
+pkginfo = 'astroid/__pkginfo__.py'
+
+with open(pkginfo, 'rb') as fobj:
+ exec(compile(fobj.read(), pkginfo, 'exec'), locals())
+
+with open('README') as fobj:
+ long_description = fobj.read()
+
+class AstroidInstallLib(install_lib.install_lib):
+ def byte_compile(self, files):
+ test_datadir = os.path.join('astroid', 'tests', 'testdata')
+ files = [f for f in files if test_datadir not in f]
+ install_lib.install_lib.byte_compile(self, files)
+
+
+
+def install():
return setup(name = distname,
version = version,
license = license,
@@ -172,13 +48,12 @@
author = author,
author_email = author_email,
url = web,
- scripts = ensure_scripts(scripts),
- data_files = data_files,
- ext_modules = ext_modules,
- cmdclass = {'install_lib': MyInstallLib,
- 'build_py': MyBuildPy},
- **kwargs
+ include_package_data = True,
+ install_requires = install_requires,
+ packages = find_packages(),
+ cmdclass={'install_lib': AstroidInstallLib}
)
+
if __name__ == '__main__' :
install()
diff -Nru astroid-1.0.1/test/data/absimport.py astroid-1.3.8/test/data/absimport.py
--- astroid-1.0.1/test/data/absimport.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/absimport.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-from __future__ import absolute_import
-import email
-from email import message
diff -Nru astroid-1.0.1/test/data/all.py astroid-1.3.8/test/data/all.py
--- astroid-1.0.1/test/data/all.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/all.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,9 +0,0 @@
-
-name = 'a'
-_bla = 2
-other = 'o'
-class Aaa: pass
-
-def func(): print 'yo'
-
-__all__ = 'Aaa', '_bla', 'name'
diff -Nru astroid-1.0.1/test/data/appl/__init__.py astroid-1.3.8/test/data/appl/__init__.py
--- astroid-1.0.1/test/data/appl/__init__.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/appl/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-"""
-Init
-"""
diff -Nru astroid-1.0.1/test/data/appl/myConnection.py astroid-1.3.8/test/data/appl/myConnection.py
--- astroid-1.0.1/test/data/appl/myConnection.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/appl/myConnection.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
-import SSL1
-class MyConnection(SSL1.Connection):
-
- """An SSL connection."""
-
- def __init__(self, dummy):
- print 'MyConnection init'
-
-if __name__ == '__main__':
- myConnection = MyConnection(' ')
- raw_input('Press Enter to continue...')
diff -Nru astroid-1.0.1/test/data/email.py astroid-1.3.8/test/data/email.py
--- astroid-1.0.1/test/data/email.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/email.py 1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-"""fake email module to test absolute import doesn't grab this one"""
diff -Nru astroid-1.0.1/test/data/format.py astroid-1.3.8/test/data/format.py
--- astroid-1.0.1/test/data/format.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/format.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,34 +0,0 @@
-"""A multiline string
-"""
-
-function('aeozrijz\
-earzer', hop)
-# XXX write test
-x = [i for i in range(5)
- if i % 4]
-
-fonction(1,
- 2,
- 3,
- 4)
-
-def definition(a,
- b,
- c):
- return a + b + c
-
-class debile(dict,
- object):
- pass
-
-if aaaa: pass
-else:
- aaaa,bbbb = 1,2
- aaaa,bbbb = bbbb,aaaa
-# XXX write test
-hop = \
- aaaa
-
-
-__revision__.lower();
-
diff -Nru astroid-1.0.1/test/data/__init__.py astroid-1.3.8/test/data/__init__.py
--- astroid-1.0.1/test/data/__init__.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-__revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $"
diff -Nru astroid-1.0.1/test/data/module2.py astroid-1.3.8/test/data/module2.py
--- astroid-1.0.1/test/data/module2.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/module2.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,135 +0,0 @@
-from data.module import YO, YOUPI
-import data
-
-
-class Specialization(YOUPI, YO):
- pass
-
-
-
-class Metaclass(type):
- pass
-
-
-
-class Interface:
- pass
-
-
-
-class MyIFace(Interface):
- pass
-
-
-
-class AnotherIFace(Interface):
- pass
-
-
-
-class MyException(Exception):
- pass
-
-
-
-class MyError(MyException):
- pass
-
-
-
-class AbstractClass(object):
-
- def to_override(self, whatever):
- raise NotImplementedError()
-
- def return_something(self, param):
- if param:
- return 'toto'
- return
-
-
-
-class Concrete0:
- __implements__ = MyIFace
-
-
-
-class Concrete1:
- __implements__ = (MyIFace, AnotherIFace)
-
-
-
-class Concrete2:
- __implements__ = (MyIFace, AnotherIFace)
-
-
-
-class Concrete23(Concrete1):
- pass
-
-del YO.member
-del YO
-[SYN1, SYN2] = (Concrete0, Concrete1)
-assert `1`
-b = (1) | (((2) & (3)) ^ (8))
-bb = ((1) | (two)) | (6)
-ccc = ((one) & (two)) & (three)
-dddd = ((x) ^ (o)) ^ (r)
-exec 'c = 3'
-exec 'c = 3' in {}, {}
-
-def raise_string(a=2, *args, **kwargs):
- raise Exception, 'yo'
- yield 'coucou'
- yield
-a = (b) + (2)
-c = (b) * (2)
-c = (b) / (2)
-c = (b) // (2)
-c = (b) - (2)
-c = (b) % (2)
-c = (b) ** (2)
-c = (b) << (2)
-c = (b) >> (2)
-c = ~b
-c = not b
-d = [c]
-e = d[:]
-e = d[a:b:c]
-raise_string(*args, **kwargs)
-print >> stream, 'bonjour'
-print >> stream, 'salut',
-
-def make_class(any, base=data.module.YO, *args, **kwargs):
- """check base is correctly resolved to Concrete0"""
-
-
- class Aaaa(base):
- """dynamic class"""
-
-
- return Aaaa
-from os.path import abspath
-import os as myos
-
-
-class A:
- pass
-
-
-
-class A(A):
- pass
-
-
-def generator():
- """A generator."""
- yield
-
-def not_a_generator():
- """A function that contains generator, but is not one."""
-
- def generator():
- yield
- genl = lambda : (yield)
-
diff -Nru astroid-1.0.1/test/data/module.py astroid-1.3.8/test/data/module.py
--- astroid-1.0.1/test/data/module.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/module.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,89 +0,0 @@
-"""test module for astroid
-"""
-
-__revision__ = '$Id: module.py,v 1.2 2005-11-02 11:56:54 syt Exp $'
-from logilab.common import modutils
-from logilab.common.shellutils import Execute as spawn
-from astroid.utils import *
-import os.path
-MY_DICT = {}
-
-def global_access(key, val):
- """function test"""
- local = 1
- MY_DICT[key] = val
- for i in val:
- if i:
- del MY_DICT[i]
- continue
- else:
- break
- else:
- print '!!!'
-
-
-class YO:
- """hehe"""
- a = 1
-
- def __init__(self):
- try:
- self.yo = 1
- except ValueError, ex:
- pass
- except (NameError, TypeError):
- raise XXXError()
- except:
- raise
-
-
-
-class YOUPI(YO):
- class_attr = None
-
- def __init__(self):
- self.member = None
-
- def method(self):
- """method test"""
- global MY_DICT
- try:
- MY_DICT = {}
- local = None
- autre = [a for (a, b) in MY_DICT if b]
- if b in autre:
- print 'yo',
- else:
- if a in autre:
- print 'hehe'
- global_access(local, val=autre)
- finally:
- return local
-
- def static_method():
- """static method test"""
- assert MY_DICT, '???'
- static_method = staticmethod(static_method)
-
- def class_method(cls):
- """class method test"""
- exec a in b
- class_method = classmethod(class_method)
-
-
-def four_args(a, b, c, d):
- """four arguments (was nested_args)"""
- print a, b, c, d
- while 1:
- if a:
- break
- a += +1
- else:
- b += -2
- if c:
- d = ((a) and (b)) or (c)
- else:
- c = ((a) and (b)) or (d)
- map(lambda x, y: (y, x), a)
-redirect = four_args
-
Binary files /tmp/tehDuGV_EZ/astroid-1.0.1/test/data/MyPyPa-0.1.0-py2.5.egg and /tmp/WwBlO9ZnuM/astroid-1.3.8/test/data/MyPyPa-0.1.0-py2.5.egg differ
Binary files /tmp/tehDuGV_EZ/astroid-1.0.1/test/data/MyPyPa-0.1.0-py2.5.zip and /tmp/WwBlO9ZnuM/astroid-1.3.8/test/data/MyPyPa-0.1.0-py2.5.zip differ
diff -Nru astroid-1.0.1/test/data/noendingnewline.py astroid-1.3.8/test/data/noendingnewline.py
--- astroid-1.0.1/test/data/noendingnewline.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/noendingnewline.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,36 +0,0 @@
-import unittest
-
-
-class TestCase(unittest.TestCase):
-
- def setUp(self):
- unittest.TestCase.setUp(self)
-
-
- def tearDown(self):
- unittest.TestCase.tearDown(self)
-
- def testIt(self):
- self.a = 10
- self.xxx()
-
-
- def xxx(self):
- if False:
- pass
- print 'a'
-
- if False:
- pass
- pass
-
- if False:
- pass
- print 'rara'
-
-
-if __name__ == '__main__':
- print 'test2'
- unittest.main()
-
-
diff -Nru astroid-1.0.1/test/data/nonregr.py astroid-1.3.8/test/data/nonregr.py
--- astroid-1.0.1/test/data/nonregr.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/nonregr.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,57 +0,0 @@
-from __future__ import generators
-
-try:
- enumerate = enumerate
-except NameError:
-
- def enumerate(iterable):
- """emulates the python2.3 enumerate() function"""
- i = 0
- for val in iterable:
- yield i, val
- i += 1
-
-def toto(value):
- for k, v in value:
- print v.get('yo')
-
-
-import imp
-fp, mpath, desc = imp.find_module('optparse',a)
-s_opt = imp.load_module('std_optparse', fp, mpath, desc)
-
-class OptionParser(s_opt.OptionParser):
-
- def parse_args(self, args=None, values=None, real_optparse=False):
- if real_optparse:
- pass
-## return super(OptionParser, self).parse_args()
- else:
- import optcomp
- optcomp.completion(self)
-
-
-class Aaa(object):
- """docstring"""
- def __init__(self):
- self.__setattr__('a','b')
- pass
-
- def one_public(self):
- """docstring"""
- pass
-
- def another_public(self):
- """docstring"""
- pass
-
-class Ccc(Aaa):
- """docstring"""
-
- class Ddd(Aaa):
- """docstring"""
- pass
-
- class Eee(Ddd):
- """docstring"""
- pass
diff -Nru astroid-1.0.1/test/data/notall.py astroid-1.3.8/test/data/notall.py
--- astroid-1.0.1/test/data/notall.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/notall.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,8 +0,0 @@
-
-name = 'a'
-_bla = 2
-other = 'o'
-class Aaa: pass
-
-def func(): print 'yo'
-
diff -Nru astroid-1.0.1/test/data/SSL1/Connection1.py astroid-1.3.8/test/data/SSL1/Connection1.py
--- astroid-1.0.1/test/data/SSL1/Connection1.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/SSL1/Connection1.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,14 +0,0 @@
-"""M2Crypto.SSL.Connection
-
-Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved."""
-
-RCS_id='$Id: Connection1.py,v 1.1 2005-06-13 20:55:22 syt Exp $'
-
-#Some code deleted here
-
-class Connection:
-
- """An SSL connection."""
-
- def __init__(self, ctx, sock=None):
- print 'init Connection'
diff -Nru astroid-1.0.1/test/data/SSL1/__init__.py astroid-1.3.8/test/data/SSL1/__init__.py
--- astroid-1.0.1/test/data/SSL1/__init__.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data/SSL1/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-from Connection1 import Connection
diff -Nru astroid-1.0.1/test/data2/clientmodule_test.py astroid-1.3.8/test/data2/clientmodule_test.py
--- astroid-1.0.1/test/data2/clientmodule_test.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data2/clientmodule_test.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,32 +0,0 @@
-""" docstring for file clientmodule.py """
-from data2.suppliermodule_test import Interface as IFace, DoNothing
-
-class Toto: pass
-
-class Ancestor:
- """ Ancestor method """
- __implements__ = (IFace,)
-
- def __init__(self, value):
- local_variable = 0
- self.attr = 'this method shouldn\'t have a docstring'
- self.__value = value
-
- def get_value(self):
- """ nice docstring ;-) """
- return self.__value
-
- def set_value(self, value):
- self.__value = value
- return 'this method shouldn\'t have a docstring'
-
-class Specialization(Ancestor):
- TYPE = 'final class'
- top = 'class'
-
- def __init__(self, value, _id):
- Ancestor.__init__(self, value)
- self._id = _id
- self.relation = DoNothing()
- self.toto = Toto()
-
diff -Nru astroid-1.0.1/test/data2/suppliermodule_test.py astroid-1.3.8/test/data2/suppliermodule_test.py
--- astroid-1.0.1/test/data2/suppliermodule_test.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/data2/suppliermodule_test.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,13 +0,0 @@
-""" file suppliermodule.py """
-
-class NotImplemented(Exception):
- pass
-
-class Interface:
- def get_value(self):
- raise NotImplemented()
-
- def set_value(self, value):
- raise NotImplemented()
-
-class DoNothing : pass
diff -Nru astroid-1.0.1/test/fulltest.sh astroid-1.3.8/test/fulltest.sh
--- astroid-1.0.1/test/fulltest.sh 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/fulltest.sh 1970-01-01 00:00:00.000000000 +0000
@@ -1,17 +0,0 @@
-#!/bin/sh
-
-if [ $@ ] ; then
- PYVERSIONS=$@
-else
- PYVERSIONS="2.3 2.4 2.5 2.6"
-fi
-PYTEST=`which pytest`
-for ver in $PYVERSIONS; do
- echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
- echo `python$ver -V`
- echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
- python$ver $PYTEST
- echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
- echo `python$ver -V` -OO
- python$ver -OO $PYTEST
-done
diff -Nru astroid-1.0.1/test/regrtest_data/absimp/__init__.py astroid-1.3.8/test/regrtest_data/absimp/__init__.py
--- astroid-1.0.1/test/regrtest_data/absimp/__init__.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/regrtest_data/absimp/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,5 +0,0 @@
-"""a package with absolute import activated
-"""
-
-from __future__ import absolute_import
-
diff -Nru astroid-1.0.1/test/regrtest_data/absimp/sidepackage/__init__.py astroid-1.3.8/test/regrtest_data/absimp/sidepackage/__init__.py
--- astroid-1.0.1/test/regrtest_data/absimp/sidepackage/__init__.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/regrtest_data/absimp/sidepackage/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-"""a side package with nothing in it
-"""
-
diff -Nru astroid-1.0.1/test/regrtest_data/absimp/string.py astroid-1.3.8/test/regrtest_data/absimp/string.py
--- astroid-1.0.1/test/regrtest_data/absimp/string.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/regrtest_data/absimp/string.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-from __future__ import absolute_import
-import string
-print string
diff -Nru astroid-1.0.1/test/regrtest_data/descriptor_crash.py astroid-1.3.8/test/regrtest_data/descriptor_crash.py
--- astroid-1.0.1/test/regrtest_data/descriptor_crash.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/regrtest_data/descriptor_crash.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
-
-import urllib
-
-class Page(object):
- _urlOpen = staticmethod(urllib.urlopen)
-
- def getPage(self, url):
- handle = self._urlOpen(url)
- data = handle.read()
- handle.close()
- return data
diff -Nru astroid-1.0.1/test/regrtest_data/package/absimport.py astroid-1.3.8/test/regrtest_data/package/absimport.py
--- astroid-1.0.1/test/regrtest_data/package/absimport.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/regrtest_data/package/absimport.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,6 +0,0 @@
-from __future__ import absolute_import
-import import_package_subpackage_module # fail
-print import_package_subpackage_module
-
-from . import hello as hola
-
diff -Nru astroid-1.0.1/test/regrtest_data/package/hello.py astroid-1.3.8/test/regrtest_data/package/hello.py
--- astroid-1.0.1/test/regrtest_data/package/hello.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/regrtest_data/package/hello.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,2 +0,0 @@
-"""hello module"""
-
diff -Nru astroid-1.0.1/test/regrtest_data/package/import_package_subpackage_module.py astroid-1.3.8/test/regrtest_data/package/import_package_subpackage_module.py
--- astroid-1.0.1/test/regrtest_data/package/import_package_subpackage_module.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/regrtest_data/package/import_package_subpackage_module.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,49 +0,0 @@
-# pylint: disable-msg=I0011,C0301,W0611
-"""I found some of my scripts trigger off an AttributeError in pylint
-0.8.1 (with common 0.12.0 and astroid 0.13.1).
-
-Traceback (most recent call last):
- File "/usr/bin/pylint", line 4, in ?
- lint.Run(sys.argv[1:])
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__
- linter.check(args)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check
- self.check_file(filepath, modname, checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file
- astroid = self._check_file(filepath, modname, checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file
- self.check_astroid_module(astroid, checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module
- self.astroid_events(astroid, [checker for checker in checkers
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
- self.astroid_events(child, checkers, _reversed_checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
- self.astroid_events(child, checkers, _reversed_checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events
- checker.visit(astroid)
- File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit
- method(node)
- File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import
- self._check_module_attrs(node, module, name_parts[1:])
- File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs
- self.add_message('E0611', args=(name, module.name),
-AttributeError: Import instance has no attribute 'name'
-
-
-You can reproduce it by:
-(1) create package structure like the following:
-
-package/
- __init__.py
- subpackage/
- __init__.py
- module.py
-
-(2) in package/__init__.py write:
-
-import subpackage
-
-(3) run pylint with a script importing package.subpackage.module.
-"""
-__revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 15:59:32 syt Exp $'
-import package.subpackage.module
diff -Nru astroid-1.0.1/test/regrtest_data/package/__init__.py astroid-1.3.8/test/regrtest_data/package/__init__.py
--- astroid-1.0.1/test/regrtest_data/package/__init__.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/regrtest_data/package/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,4 +0,0 @@
-"""package's __init__ file"""
-
-
-import subpackage
diff -Nru astroid-1.0.1/test/regrtest_data/package/subpackage/__init__.py astroid-1.3.8/test/regrtest_data/package/subpackage/__init__.py
--- astroid-1.0.1/test/regrtest_data/package/subpackage/__init__.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/regrtest_data/package/subpackage/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-"""package.subpackage"""
diff -Nru astroid-1.0.1/test/regrtest_data/package/subpackage/module.py astroid-1.3.8/test/regrtest_data/package/subpackage/module.py
--- astroid-1.0.1/test/regrtest_data/package/subpackage/module.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/regrtest_data/package/subpackage/module.py 1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-"""package.subpackage.module"""
diff -Nru astroid-1.0.1/test/unittest_brain.py astroid-1.3.8/test/unittest_brain.py
--- astroid-1.0.1/test/unittest_brain.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/unittest_brain.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,39 +0,0 @@
-# Copyright 2013 Google Inc. All Rights Reserved.
-#
-# This file is part of astroid.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see .
-"""Tests for basic functionality in astroid.brain."""
-
-from astroid import MANAGER
-from logilab.common.testlib import TestCase, unittest_main
-
-
-class HashlibTC(TestCase):
- def test_hashlib(self):
- """Tests that brain extensions for hashlib work."""
- hashlib_module = MANAGER.ast_from_module_name('hashlib')
- for class_name in ['md5', 'sha1']:
- class_obj = hashlib_module[class_name]
- self.assertIn('update', class_obj)
- self.assertIn('digest', class_obj)
- self.assertIn('hexdigest', class_obj)
- self.assertEqual(len(class_obj['__init__'].args.args), 2)
- self.assertEqual(len(class_obj['__init__'].args.defaults), 1)
- self.assertEqual(len(class_obj['update'].args.args), 2)
- self.assertEqual(len(class_obj['digest'].args.args), 1)
- self.assertEqual(len(class_obj['hexdigest'].args.args), 1)
-
-if __name__ == '__main__':
- unittest_main()
diff -Nru astroid-1.0.1/test/unittest_builder.py astroid-1.3.8/test/unittest_builder.py
--- astroid-1.0.1/test/unittest_builder.py 2013-10-18 15:34:05.000000000 +0000
+++ astroid-1.3.8/test/unittest_builder.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,733 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""tests for the astroid builder and rebuilder module"""
-
-import unittest
-import sys
-from os.path import join, abspath, dirname
-
-from logilab.common.testlib import TestCase, unittest_main
-from pprint import pprint
-
-from astroid import builder, nodes, InferenceError, NotFoundError
-from astroid.nodes import Module
-from astroid.bases import YES, BUILTINS
-from astroid.manager import AstroidManager
-
-MANAGER = AstroidManager()
-
-
-from unittest_inference import get_name_node
-
-import data
-from data import module as test_module
-
-DATA = join(dirname(abspath(__file__)), 'data')
-
-class FromToLineNoTC(TestCase):
-
- astroid = builder.AstroidBuilder().file_build(join(DATA, 'format.py'))
-
- def test_callfunc_lineno(self):
- stmts = self.astroid.body
- # on line 4:
- # function('aeozrijz\
- # earzer', hop)
- discard = stmts[0]
- self.assertIsInstance(discard, nodes.Discard)
- self.assertEqual(discard.fromlineno, 4)
- self.assertEqual(discard.tolineno, 5)
- callfunc = discard.value
- self.assertIsInstance(callfunc, nodes.CallFunc)
- self.assertEqual(callfunc.fromlineno, 4)
- self.assertEqual(callfunc.tolineno, 5)
- name = callfunc.func
- self.assertIsInstance(name, nodes.Name)
- self.assertEqual(name.fromlineno, 4)
- self.assertEqual(name.tolineno, 4)
- strarg = callfunc.args[0]
- self.assertIsInstance(strarg, nodes.Const)
- if hasattr(sys, 'pypy_version_info'):
- lineno = 4
- else:
- lineno = 5 # no way for this one in CPython (is 4 actually)
- self.assertEqual(strarg.fromlineno, lineno)
- self.assertEqual(strarg.tolineno, lineno)
- namearg = callfunc.args[1]
- self.assertIsInstance(namearg, nodes.Name)
- self.assertEqual(namearg.fromlineno, 5)
- self.assertEqual(namearg.tolineno, 5)
- # on line 10:
- # fonction(1,
- # 2,
- # 3,
- # 4)
- discard = stmts[2]
- self.assertIsInstance(discard, nodes.Discard)
- self.assertEqual(discard.fromlineno, 10)
- self.assertEqual(discard.tolineno, 13)
- callfunc = discard.value
- self.assertIsInstance(callfunc, nodes.CallFunc)
- self.assertEqual(callfunc.fromlineno, 10)
- self.assertEqual(callfunc.tolineno, 13)
- name = callfunc.func
- self.assertIsInstance(name, nodes.Name)
- self.assertEqual(name.fromlineno, 10)
- self.assertEqual(name.tolineno, 10)
- for i, arg in enumerate(callfunc.args):
- self.assertIsInstance(arg, nodes.Const)
- self.assertEqual(arg.fromlineno, 10+i)
- self.assertEqual(arg.tolineno, 10+i)
-
- def test_function_lineno(self):
- stmts = self.astroid.body
- # on line 15:
- # def definition(a,
- # b,
- # c):
- # return a + b + c
- function = stmts[3]
- self.assertIsInstance(function, nodes.Function)
- self.assertEqual(function.fromlineno, 15)
- self.assertEqual(function.tolineno, 18)
- return_ = function.body[0]
- self.assertIsInstance(return_, nodes.Return)
- self.assertEqual(return_.fromlineno, 18)
- self.assertEqual(return_.tolineno, 18)
- if sys.version_info < (3, 0):
- self.assertEqual(function.blockstart_tolineno, 17)
- else:
- self.skipTest('FIXME http://bugs.python.org/issue10445 '
- '(no line number on function args)')
-
- def test_decorated_function_lineno(self):
- astroid = builder.AstroidBuilder().string_build('''
-@decorator
-def function(
- arg):
- print (arg)
-''', __name__, __file__)
- function = astroid['function']
- self.assertEqual(function.fromlineno, 3) # XXX discussable, but that's what is expected by pylint right now
- self.assertEqual(function.tolineno, 5)
- self.assertEqual(function.decorators.fromlineno, 2)
- self.assertEqual(function.decorators.tolineno, 2)
- if sys.version_info < (3, 0):
- self.assertEqual(function.blockstart_tolineno, 4)
- else:
- self.skipTest('FIXME http://bugs.python.org/issue10445 '
- '(no line number on function args)')
-
-
- def test_class_lineno(self):
- stmts = self.astroid.body
- # on line 20:
- # class debile(dict,
- # object):
- # pass
- class_ = stmts[4]
- self.assertIsInstance(class_, nodes.Class)
- self.assertEqual(class_.fromlineno, 20)
- self.assertEqual(class_.tolineno, 22)
- self.assertEqual(class_.blockstart_tolineno, 21)
- pass_ = class_.body[0]
- self.assertIsInstance(pass_, nodes.Pass)
- self.assertEqual(pass_.fromlineno, 22)
- self.assertEqual(pass_.tolineno, 22)
-
- def test_if_lineno(self):
- stmts = self.astroid.body
- # on line 20:
- # if aaaa: pass
- # else:
- # aaaa,bbbb = 1,2
- # aaaa,bbbb = bbbb,aaaa
- if_ = stmts[5]
- self.assertIsInstance(if_, nodes.If)
- self.assertEqual(if_.fromlineno, 24)
- self.assertEqual(if_.tolineno, 27)
- self.assertEqual(if_.blockstart_tolineno, 24)
- self.assertEqual(if_.orelse[0].fromlineno, 26)
- self.assertEqual(if_.orelse[1].tolineno, 27)
-
- def test_for_while_lineno(self):
- for code in ('''
-for a in range(4):
- print (a)
- break
-else:
- print ("bouh")
-''', '''
-while a:
- print (a)
- break
-else:
- print ("bouh")
-''',
- ):
- astroid = builder.AstroidBuilder().string_build(code, __name__, __file__)
- stmt = astroid.body[0]
- self.assertEqual(stmt.fromlineno, 2)
- self.assertEqual(stmt.tolineno, 6)
- self.assertEqual(stmt.blockstart_tolineno, 2)
- self.assertEqual(stmt.orelse[0].fromlineno, 6) # XXX
- self.assertEqual(stmt.orelse[0].tolineno, 6)
-
-
- def test_try_except_lineno(self):
- astroid = builder.AstroidBuilder().string_build('''
-try:
- print (a)
-except:
- pass
-else:
- print ("bouh")
-''', __name__, __file__)
- try_ = astroid.body[0]
- self.assertEqual(try_.fromlineno, 2)
- self.assertEqual(try_.tolineno, 7)
- self.assertEqual(try_.blockstart_tolineno, 2)
- self.assertEqual(try_.orelse[0].fromlineno, 7) # XXX
- self.assertEqual(try_.orelse[0].tolineno, 7)
- hdlr = try_.handlers[0]
- self.assertEqual(hdlr.fromlineno, 4)
- self.assertEqual(hdlr.tolineno, 5)
- self.assertEqual(hdlr.blockstart_tolineno, 4)
-
-
- def test_try_finally_lineno(self):
- astroid = builder.AstroidBuilder().string_build('''
-try:
- print (a)
-finally:
- print ("bouh")
-''', __name__, __file__)
- try_ = astroid.body[0]
- self.assertEqual(try_.fromlineno, 2)
- self.assertEqual(try_.tolineno, 5)
- self.assertEqual(try_.blockstart_tolineno, 2)
- self.assertEqual(try_.finalbody[0].fromlineno, 5) # XXX
- self.assertEqual(try_.finalbody[0].tolineno, 5)
-
-
- def test_try_finally_25_lineno(self):
- astroid = builder.AstroidBuilder().string_build('''
-try:
- print (a)
-except:
- pass
-finally:
- print ("bouh")
-''', __name__, __file__)
- try_ = astroid.body[0]
- self.assertEqual(try_.fromlineno, 2)
- self.assertEqual(try_.tolineno, 7)
- self.assertEqual(try_.blockstart_tolineno, 2)
- self.assertEqual(try_.finalbody[0].fromlineno, 7) # XXX
- self.assertEqual(try_.finalbody[0].tolineno, 7)
-
-
- def test_with_lineno(self):
- astroid = builder.AstroidBuilder().string_build('''
-from __future__ import with_statement
-with file("/tmp/pouet") as f:
- print (f)
-''', __name__, __file__)
- with_ = astroid.body[1]
- self.assertEqual(with_.fromlineno, 3)
- self.assertEqual(with_.tolineno, 4)
- self.assertEqual(with_.blockstart_tolineno, 3)
-
-
-
-class BuilderTC(TestCase):
-
- def setUp(self):
- self.builder = builder.AstroidBuilder()
-
- def test_border_cases(self):
- """check that a file with no trailing new line is parseable"""
- self.builder.file_build(join(DATA, 'noendingnewline.py'), 'data.noendingnewline')
- self.assertRaises(builder.AstroidBuildingException,
- self.builder.file_build, join(DATA, 'inexistant.py'), 'whatever')
-
- def test_inspect_build0(self):
- """test astroid tree build from a living object"""
- builtin_astroid = MANAGER.ast_from_module_name(BUILTINS)
- if sys.version_info < (3, 0):
- fclass = builtin_astroid['file']
- self.assertIn('name', fclass)
- self.assertIn('mode', fclass)
- self.assertIn('read', fclass)
- self.assertTrue(fclass.newstyle)
- self.assertTrue(fclass.pytype(), '%s.type' % BUILTINS)
- self.assertIsInstance(fclass['read'], nodes.Function)
- # check builtin function has args.args == None
- dclass = builtin_astroid['dict']
- self.assertIsNone(dclass['has_key'].args.args)
- # just check type and object are there
- builtin_astroid.getattr('type')
- objectastroid = builtin_astroid.getattr('object')[0]
- self.assertIsInstance(objectastroid.getattr('__new__')[0], nodes.Function)
- # check open file alias
- builtin_astroid.getattr('open')
- # check 'help' is there (defined dynamically by site.py)
- builtin_astroid.getattr('help')
- # check property has __init__
- pclass = builtin_astroid['property']
- self.assertIn('__init__', pclass)
- self.assertIsInstance(builtin_astroid['None'], nodes.Const)
- self.assertIsInstance(builtin_astroid['True'], nodes.Const)
- self.assertIsInstance(builtin_astroid['False'], nodes.Const)
- if sys.version_info < (3, 0):
- self.assertIsInstance(builtin_astroid['Exception'], nodes.From)
- self.assertIsInstance(builtin_astroid['NotImplementedError'], nodes.From)
- else:
- self.assertIsInstance(builtin_astroid['Exception'], nodes.Class)
- self.assertIsInstance(builtin_astroid['NotImplementedError'], nodes.Class)
-
- def test_inspect_build1(self):
- time_astroid = MANAGER.ast_from_module_name('time')
- self.assertTrue(time_astroid)
- self.assertEqual(time_astroid['time'].args.defaults, [])
-
- def test_inspect_build2(self):
- """test astroid tree build from a living object"""
- try:
- from mx import DateTime
- except ImportError:
- self.skipTest('test skipped: mxDateTime is not available')
- else:
- dt_astroid = self.builder.inspect_build(DateTime)
- dt_astroid.getattr('DateTime')
- # this one is failing since DateTimeType.__module__ = 'builtins' !
- #dt_astroid.getattr('DateTimeType')
-
- def test_inspect_build3(self):
- self.builder.inspect_build(unittest)
-
- def test_inspect_build_instance(self):
- """test astroid tree build from a living object"""
- if sys.version_info >= (3, 0):
- self.skipTest('The module "exceptions" is gone in py3.x')
- import exceptions
- builtin_astroid = self.builder.inspect_build(exceptions)
- fclass = builtin_astroid['OSError']
- # things like OSError.strerror are now (2.5) data descriptors on the
- # class instead of entries in the __dict__ of an instance
- container = fclass
- self.assertIn('errno', container)
- self.assertIn('strerror', container)
- self.assertIn('filename', container)
-
- def test_inspect_build_type_object(self):
- builtin_astroid = MANAGER.ast_from_module_name(BUILTINS)
-
- infered = list(builtin_astroid.igetattr('object'))
- self.assertEqual(len(infered), 1)
- infered = infered[0]
- self.assertEqual(infered.name, 'object')
- infered.as_string() # no crash test
-
- infered = list(builtin_astroid.igetattr('type'))
- self.assertEqual(len(infered), 1)
- infered = infered[0]
- self.assertEqual(infered.name, 'type')
- infered.as_string() # no crash test
-
- def test_package_name(self):
- """test base properties and method of a astroid module"""
- datap = self.builder.file_build(join(DATA, '__init__.py'), 'data')
- self.assertEqual(datap.name, 'data')
- self.assertEqual(datap.package, 1)
- datap = self.builder.file_build(join(DATA, '__init__.py'), 'data.__init__')
- self.assertEqual(datap.name, 'data')
- self.assertEqual(datap.package, 1)
-
- def test_yield_parent(self):
- """check if we added discard nodes as yield parent (w/ compiler)"""
- data = """
-def yiell():
- yield 0
- if noe:
- yield more
-"""
- func = self.builder.string_build(data).body[0]
- self.assertIsInstance(func, nodes.Function)
- stmt = func.body[0]
- self.assertIsInstance(stmt, nodes.Discard)
- self.assertIsInstance(stmt.value, nodes.Yield)
- self.assertIsInstance(func.body[1].body[0], nodes.Discard)
- self.assertIsInstance(func.body[1].body[0].value, nodes.Yield)
-
- def test_object(self):
- obj_astroid = self.builder.inspect_build(object)
- self.assertIn('__setattr__', obj_astroid)
-
- def test_newstyle_detection(self):
- data = '''
-class A:
- "old style"
-
-class B(A):
- "old style"
-
-class C(object):
- "new style"
-
-class D(C):
- "new style"
-
-__metaclass__ = type
-
-class E(A):
- "old style"
-
-class F:
- "new style"
-'''
- mod_astroid = self.builder.string_build(data, __name__, __file__)
- self.assertFalse(mod_astroid['A'].newstyle)
- self.assertFalse(mod_astroid['B'].newstyle)
- self.assertTrue(mod_astroid['C'].newstyle)
- self.assertTrue(mod_astroid['D'].newstyle)
- self.assertFalse(mod_astroid['E'].newstyle)
- self.assertTrue(mod_astroid['F'].newstyle)
-
- def test_globals(self):
- data = '''
-CSTE = 1
-
-def update_global():
- global CSTE
- CSTE += 1
-
-def global_no_effect():
- global CSTE2
- print (CSTE)
-'''
- astroid = self.builder.string_build(data, __name__, __file__)
- self.assertEqual(len(astroid.getattr('CSTE')), 2)
- self.assertIsInstance(astroid.getattr('CSTE')[0], nodes.AssName)
- self.assertEqual(astroid.getattr('CSTE')[0].fromlineno, 2)
- self.assertEqual(astroid.getattr('CSTE')[1].fromlineno, 6)
- self.assertRaises(NotFoundError,
- astroid.getattr, 'CSTE2')
- self.assertRaises(InferenceError,
- astroid['global_no_effect'].ilookup('CSTE2').next)
-
- def test_socket_build(self):
- import socket
- astroid = self.builder.module_build(socket)
- # XXX just check the first one. Actually 3 objects are inferred (look at
- # the socket module) but the last one as those attributes dynamically
- # set and astroid is missing this.
- for fclass in astroid.igetattr('socket'):
- #print fclass.root().name, fclass.name, fclass.lineno
- self.assertIn('connect', fclass)
- self.assertIn('send', fclass)
- self.assertIn('close', fclass)
- break
-
- def test_gen_expr_var_scope(self):
- data = 'l = list(n for n in range(10))\n'
- astroid = self.builder.string_build(data, __name__, __file__)
- # n unavailable outside gen expr scope
- self.assertNotIn('n', astroid)
- # test n is inferable anyway
- n = get_name_node(astroid, 'n')
- self.assertIsNot(n.scope(), astroid)
- self.assertEqual([i.__class__ for i in n.infer()],
- [YES.__class__])
-
-class FileBuildTC(TestCase):
-
- module = builder.AstroidBuilder().file_build(join(DATA, 'module.py'), 'data.module')
-
- def test_module_base_props(self):
- """test base properties and method of a astroid module"""
- module = self.module
- self.assertEqual(module.name, 'data.module')
- self.assertEqual(module.doc, "test module for astroid\n")
- self.assertEqual(module.fromlineno, 0)
- self.assertIsNone(module.parent)
- self.assertEqual(module.frame(), module)
- self.assertEqual(module.root(), module)
- self.assertEqual(module.file, join(abspath(data.__path__[0]), 'module.py'))
- self.assertEqual(module.pure_python, 1)
- self.assertEqual(module.package, 0)
- self.assertFalse(module.is_statement)
- self.assertEqual(module.statement(), module)
- self.assertEqual(module.statement(), module)
-
- def test_module_locals(self):
- """test the 'locals' dictionary of a astroid module"""
- module = self.module
- _locals = module.locals
- self.assertIs(_locals, module.globals)
- keys = sorted(_locals.keys())
- should = ['MY_DICT', 'YO', 'YOUPI',
- '__revision__', 'global_access','modutils', 'four_args',
- 'os', 'redirect', 'spawn', 'LocalsVisitor', 'ASTWalker']
- should.sort()
- self.assertEqual(keys, should)
-
- def test_function_base_props(self):
- """test base properties and method of a astroid function"""
- module = self.module
- function = module['global_access']
- self.assertEqual(function.name, 'global_access')
- self.assertEqual(function.doc, 'function test')
- self.assertEqual(function.fromlineno, 11)
- self.assertTrue(function.parent)
- self.assertEqual(function.frame(), function)
- self.assertEqual(function.parent.frame(), module)
- self.assertEqual(function.root(), module)
- self.assertEqual([n.name for n in function.args.args], ['key', 'val'])
- self.assertEqual(function.type, 'function')
-
- def test_function_locals(self):
- """test the 'locals' dictionary of a astroid function"""
- _locals = self.module['global_access'].locals
- self.assertEqual(len(_locals), 4)
- keys = sorted(_locals.keys())
- self.assertEqual(keys, ['i', 'key', 'local', 'val'])
-
- def test_class_base_props(self):
- """test base properties and method of a astroid class"""
- module = self.module
- klass = module['YO']
- self.assertEqual(klass.name, 'YO')
- self.assertEqual(klass.doc, 'hehe')
- self.assertEqual(klass.fromlineno, 25)
- self.assertTrue(klass.parent)
- self.assertEqual(klass.frame(), klass)
- self.assertEqual(klass.parent.frame(), module)
- self.assertEqual(klass.root(), module)
- self.assertEqual(klass.basenames, [])
- self.assertEqual(klass.newstyle, False)
-
- def test_class_locals(self):
- """test the 'locals' dictionary of a astroid class"""
- module = self.module
- klass1 = module['YO']
- locals1 = klass1.locals
- keys = sorted(locals1.keys())
- self.assertEqual(keys, ['__init__', 'a'])
- klass2 = module['YOUPI']
- locals2 = klass2.locals
- keys = locals2.keys()
- keys.sort()
- self.assertEqual(keys, ['__init__', 'class_attr', 'class_method',
- 'method', 'static_method'])
-
- def test_class_instance_attrs(self):
- module = self.module
- klass1 = module['YO']
- klass2 = module['YOUPI']
- self.assertEqual(klass1.instance_attrs.keys(), ['yo'])
- self.assertEqual(klass2.instance_attrs.keys(), ['member'])
-
- def test_class_basenames(self):
- module = self.module
- klass1 = module['YO']
- klass2 = module['YOUPI']
- self.assertEqual(klass1.basenames, [])
- self.assertEqual(klass2.basenames, ['YO'])
-
- def test_method_base_props(self):
- """test base properties and method of a astroid method"""
- klass2 = self.module['YOUPI']
- # "normal" method
- method = klass2['method']
- self.assertEqual(method.name, 'method')
- self.assertEqual([n.name for n in method.args.args], ['self'])
- self.assertEqual(method.doc, 'method test')
- self.assertEqual(method.fromlineno, 47)
- self.assertEqual(method.type, 'method')
- # class method
- method = klass2['class_method']
- self.assertEqual([n.name for n in method.args.args], ['cls'])
- self.assertEqual(method.type, 'classmethod')
- # static method
- method = klass2['static_method']
- self.assertEqual(method.args.args, [])
- self.assertEqual(method.type, 'staticmethod')
-
- def test_method_locals(self):
- """test the 'locals' dictionary of a astroid method"""
- method = self.module['YOUPI']['method']
- _locals = method.locals
- keys = sorted(_locals)
- if sys.version_info < (3, 0):
- self.assertEqual(len(_locals), 5)
- self.assertEqual(keys, ['a', 'autre', 'b', 'local', 'self'])
- else:# ListComp variables are no more accessible outside
- self.assertEqual(len(_locals), 3)
- self.assertEqual(keys, ['autre', 'local', 'self'])
-
-
-class ModuleBuildTC(FileBuildTC):
-
- def setUp(self):
- abuilder = builder.AstroidBuilder()
- self.module = abuilder.module_build(test_module)
-
-
-class MoreTC(TestCase):
-
- def setUp(self):
- self.builder = builder.AstroidBuilder()
-
- def test_infered_build(self):
- code = '''class A: pass
-A.type = "class"
-
-def A_ass_type(self):
- print (self)
-A.ass_type = A_ass_type
- '''
- astroid = self.builder.string_build(code)
- lclass = list(astroid.igetattr('A'))
- self.assertEqual(len(lclass), 1)
- lclass = lclass[0]
- self.assertIn('ass_type', lclass.locals)
- self.assertIn('type', lclass.locals)
-
- def test_augassign_attr(self):
- astroid = self.builder.string_build("""class Counter:
- v = 0
- def inc(self):
- self.v += 1
- """, __name__, __file__)
- # Check self.v += 1 generate AugAssign(AssAttr(...)), not AugAssign(GetAttr(AssName...))
-
- def test_dumb_module(self):
- astroid = self.builder.string_build("pouet")
-
- def test_infered_dont_pollute(self):
- code = '''
-def func(a=None):
- a.custom_attr = 0
-def func2(a={}):
- a.custom_attr = 0
- '''
- astroid = self.builder.string_build(code)
- nonetype = nodes.const_factory(None)
- self.assertNotIn('custom_attr', nonetype.locals)
- self.assertNotIn('custom_attr', nonetype.instance_attrs)
- nonetype = nodes.const_factory({})
- self.assertNotIn('custom_attr', nonetype.locals)
- self.assertNotIn('custom_attr', nonetype.instance_attrs)
-
-
- def test_asstuple(self):
- code = 'a, b = range(2)'
- astroid = self.builder.string_build(code)
- self.assertIn('b', astroid.locals)
- code = '''
-def visit_if(self, node):
- node.test, body = node.tests[0]
-'''
- astroid = self.builder.string_build(code)
- self.assertIn('body', astroid['visit_if'].locals)
-
- def test_build_constants(self):
- '''test expected values of constants after rebuilding'''
- code = '''
-def func():
- return None
- return
- return 'None'
-'''
- astroid = self.builder.string_build(code)
- none, nothing, chain = [ret.value for ret in astroid.body[0].body]
- self.assertIsInstance(none, nodes.Const)
- self.assertIsNone(none.value)
- self.assertIsNone(nothing)
- self.assertIsInstance(chain, nodes.Const)
- self.assertEqual(chain.value, 'None')
-
-
- def test_lgc_classproperty(self):
- '''test expected values of constants after rebuilding'''
- code = '''
-from logilab.common.decorators import classproperty
-
-class A(object):
- @classproperty
- def hop(cls):
- return None
-'''
- astroid = self.builder.string_build(code)
- self.assertEqual(astroid['A']['hop'].type, 'classmethod')
-
-
-if sys.version_info < (3, 0):
- guess_encoding = builder._guess_encoding
-
- class TestGuessEncoding(TestCase):
-
- def testEmacs(self):
- e = guess_encoding('# -*- coding: UTF-8 -*-')
- self.assertEqual(e, 'UTF-8')
- e = guess_encoding('# -*- coding:UTF-8 -*-')
- self.assertEqual(e, 'UTF-8')
- e = guess_encoding('''
- ### -*- coding: ISO-8859-1 -*-
- ''')
- self.assertEqual(e, 'ISO-8859-1')
- e = guess_encoding('''
-
- ### -*- coding: ISO-8859-1 -*-
- ''')
- self.assertIsNone(e)
-
- def testVim(self):
- e = guess_encoding('# vim:fileencoding=UTF-8')
- self.assertEqual(e, 'UTF-8')
- e = guess_encoding('''
- ### vim:fileencoding=ISO-8859-1
- ''')
- self.assertEqual(e, 'ISO-8859-1')
- e = guess_encoding('''
-
- ### vim:fileencoding= ISO-8859-1
- ''')
- self.assertIsNone(e)
-
- def test_wrong_coding(self):
- # setting "coding" varaible
- e = guess_encoding("coding = UTF-8")
- self.assertIsNone(e)
- # setting a dictionnary entry
- e = guess_encoding("coding:UTF-8")
- self.assertIsNone(e)
- # setting an arguement
- e = guess_encoding("def do_something(a_word_with_coding=None):")
- self.assertIsNone(e)
-
-
- def testUTF8(self):
- e = guess_encoding('\xef\xbb\xbf any UTF-8 data')
- self.assertEqual(e, 'UTF-8')
- e = guess_encoding(' any UTF-8 data \xef\xbb\xbf')
- self.assertIsNone(e)
-
-if __name__ == '__main__':
- unittest_main()
diff -Nru astroid-1.0.1/test/unittest_inference.py astroid-1.3.8/test/unittest_inference.py
--- astroid-1.0.1/test/unittest_inference.py 2013-10-18 15:34:05.000000000 +0000
+++ astroid-1.3.8/test/unittest_inference.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,1183 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""tests for the astroid inference capabilities
-"""
-from os.path import join, dirname, abspath
-import sys
-from StringIO import StringIO
-
-from logilab.common.testlib import TestCase, unittest_main, require_version
-
-from astroid import InferenceError, builder, nodes
-from astroid.inference import infer_end as inference_infer_end
-from astroid.bases import YES, Instance, BoundMethod, UnboundMethod,\
- path_wrapper, BUILTINS
-
-def get_name_node(start_from, name, index=0):
- return [n for n in start_from.nodes_of_class(nodes.Name) if n.name == name][index]
-
-def get_node_of_class(start_from, klass):
- return start_from.nodes_of_class(klass).next()
-
-builder = builder.AstroidBuilder()
-
-class InferenceUtilsTC(TestCase):
-
- def test_path_wrapper(self):
- def infer_default(self, *args):
- raise InferenceError
- infer_default = path_wrapper(infer_default)
- infer_end = path_wrapper(inference_infer_end)
- self.assertRaises(InferenceError,
- infer_default(1).next)
- self.assertEqual(infer_end(1).next(), 1)
-
-if sys.version_info < (3, 0):
- EXC_MODULE = 'exceptions'
-else:
- EXC_MODULE = BUILTINS
-
-class InferenceTC(TestCase):
-
- CODE = '''
-
-class C(object):
- "new style"
- attr = 4
-
- def meth1(self, arg1, optarg=0):
- var = object()
- print ("yo", arg1, optarg)
- self.iattr = "hop"
- return var
-
- def meth2(self):
- self.meth1(*self.meth3)
-
- def meth3(self, d=attr):
- b = self.attr
- c = self.iattr
- return b, c
-
-ex = Exception("msg")
-v = C().meth1(1)
-m_unbound = C.meth1
-m_bound = C().meth1
-a, b, c = ex, 1, "bonjour"
-[d, e, f] = [ex, 1.0, ("bonjour", v)]
-g, h = f
-i, (j, k) = "glup", f
-
-a, b= b, a # Gasp !
-'''
-
- astroid = builder.string_build(CODE, __name__, __file__)
-
- def test_module_inference(self):
- infered = self.astroid.infer()
- obj = infered.next()
- self.assertEqual(obj.name, __name__)
- self.assertEqual(obj.root().name, __name__)
- self.assertRaises(StopIteration, infered.next)
-
- def test_class_inference(self):
- infered = self.astroid['C'].infer()
- obj = infered.next()
- self.assertEqual(obj.name, 'C')
- self.assertEqual(obj.root().name, __name__)
- self.assertRaises(StopIteration, infered.next)
-
- def test_function_inference(self):
- infered = self.astroid['C']['meth1'].infer()
- obj = infered.next()
- self.assertEqual(obj.name, 'meth1')
- self.assertEqual(obj.root().name, __name__)
- self.assertRaises(StopIteration, infered.next)
-
- def test_builtin_name_inference(self):
- infered = self.astroid['C']['meth1']['var'].infer()
- var = infered.next()
- self.assertEqual(var.name, 'object')
- self.assertEqual(var.root().name, BUILTINS)
- self.assertRaises(StopIteration, infered.next)
-
- def test_tupleassign_name_inference(self):
- infered = self.astroid['a'].infer()
- exc = infered.next()
- self.assertIsInstance(exc, Instance)
- self.assertEqual(exc.name, 'Exception')
- self.assertEqual(exc.root().name, EXC_MODULE)
- self.assertRaises(StopIteration, infered.next)
- infered = self.astroid['b'].infer()
- const = infered.next()
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, 1)
- self.assertRaises(StopIteration, infered.next)
- infered = self.astroid['c'].infer()
- const = infered.next()
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, "bonjour")
- self.assertRaises(StopIteration, infered.next)
-
- def test_listassign_name_inference(self):
- infered = self.astroid['d'].infer()
- exc = infered.next()
- self.assertIsInstance(exc, Instance)
- self.assertEqual(exc.name, 'Exception')
- self.assertEqual(exc.root().name, EXC_MODULE)
- self.assertRaises(StopIteration, infered.next)
- infered = self.astroid['e'].infer()
- const = infered.next()
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, 1.0)
- self.assertRaises(StopIteration, infered.next)
- infered = self.astroid['f'].infer()
- const = infered.next()
- self.assertIsInstance(const, nodes.Tuple)
- self.assertRaises(StopIteration, infered.next)
-
- def test_advanced_tupleassign_name_inference1(self):
- infered = self.astroid['g'].infer()
- const = infered.next()
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, "bonjour")
- self.assertRaises(StopIteration, infered.next)
- infered = self.astroid['h'].infer()
- var = infered.next()
- self.assertEqual(var.name, 'object')
- self.assertEqual(var.root().name, BUILTINS)
- self.assertRaises(StopIteration, infered.next)
-
- def test_advanced_tupleassign_name_inference2(self):
- infered = self.astroid['i'].infer()
- const = infered.next()
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, u"glup")
- self.assertRaises(StopIteration, infered.next)
- infered = self.astroid['j'].infer()
- const = infered.next()
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, "bonjour")
- self.assertRaises(StopIteration, infered.next)
- infered = self.astroid['k'].infer()
- var = infered.next()
- self.assertEqual(var.name, 'object')
- self.assertEqual(var.root().name, BUILTINS)
- self.assertRaises(StopIteration, infered.next)
-
- def test_swap_assign_inference(self):
- infered = self.astroid.locals['a'][1].infer()
- const = infered.next()
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, 1)
- self.assertRaises(StopIteration, infered.next)
- infered = self.astroid.locals['b'][1].infer()
- exc = infered.next()
- self.assertIsInstance(exc, Instance)
- self.assertEqual(exc.name, 'Exception')
- self.assertEqual(exc.root().name, EXC_MODULE)
- self.assertRaises(StopIteration, infered.next)
-
- def test_getattr_inference1(self):
- infered = self.astroid['ex'].infer()
- exc = infered.next()
- self.assertIsInstance(exc, Instance)
- self.assertEqual(exc.name, 'Exception')
- self.assertEqual(exc.root().name, EXC_MODULE)
- self.assertRaises(StopIteration, infered.next)
-
- def test_getattr_inference2(self):
- infered = get_node_of_class(self.astroid['C']['meth2'], nodes.Getattr).infer()
- meth1 = infered.next()
- self.assertEqual(meth1.name, 'meth1')
- self.assertEqual(meth1.root().name, __name__)
- self.assertRaises(StopIteration, infered.next)
-
- def test_getattr_inference3(self):
- infered = self.astroid['C']['meth3']['b'].infer()
- const = infered.next()
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, 4)
- self.assertRaises(StopIteration, infered.next)
-
- def test_getattr_inference4(self):
- infered = self.astroid['C']['meth3']['c'].infer()
- const = infered.next()
- self.assertIsInstance(const, nodes.Const)
- self.assertEqual(const.value, "hop")
- self.assertRaises(StopIteration, infered.next)
-
- def test_callfunc_inference(self):
- infered = self.astroid['v'].infer()
- meth1 = infered.next()
- self.assertIsInstance(meth1, Instance)
- self.assertEqual(meth1.name, 'object')
- self.assertEqual(meth1.root().name, BUILTINS)
- self.assertRaises(StopIteration, infered.next)
-
- def test_unbound_method_inference(self):
- infered = self.astroid['m_unbound'].infer()
- meth1 = infered.next()
- self.assertIsInstance(meth1, UnboundMethod)
- self.assertEqual(meth1.name, 'meth1')
- self.assertEqual(meth1.parent.frame().name, 'C')
- self.assertRaises(StopIteration, infered.next)
-
- def test_bound_method_inference(self):
- infered = self.astroid['m_bound'].infer()
- meth1 = infered.next()
- self.assertIsInstance(meth1, BoundMethod)
- self.assertEqual(meth1.name, 'meth1')
- self.assertEqual(meth1.parent.frame().name, 'C')
- self.assertRaises(StopIteration, infered.next)
-
- def test_args_default_inference1(self):
- optarg = get_name_node(self.astroid['C']['meth1'], 'optarg')
- infered = optarg.infer()
- obj1 = infered.next()
- self.assertIsInstance(obj1, nodes.Const)
- self.assertEqual(obj1.value, 0)
- obj1 = infered.next()
- self.assertIs(obj1, YES, obj1)
- self.assertRaises(StopIteration, infered.next)
-
- def test_args_default_inference2(self):
- infered = self.astroid['C']['meth3'].ilookup('d')
- obj1 = infered.next()
- self.assertIsInstance(obj1, nodes.Const)
- self.assertEqual(obj1.value, 4)
- obj1 = infered.next()
- self.assertIs(obj1, YES, obj1)
- self.assertRaises(StopIteration, infered.next)
-
- def test_inference_restrictions(self):
- infered = get_name_node(self.astroid['C']['meth1'], 'arg1').infer()
- obj1 = infered.next()
- self.assertIs(obj1, YES, obj1)
- self.assertRaises(StopIteration, infered.next)
-
- def test_ancestors_inference(self):
- code = '''
-class A:
- pass
-
-class A(A):
- pass
- '''
- astroid = builder.string_build(code, __name__, __file__)
- a1 = astroid.locals['A'][0]
- a2 = astroid.locals['A'][1]
- a2_ancestors = list(a2.ancestors())
- self.assertEqual(len(a2_ancestors), 1)
- self.assertIs(a2_ancestors[0], a1)
-
- def test_ancestors_inference2(self):
- code = '''
-class A:
- pass
-
-class B(A): pass
-
-class A(B):
- pass
- '''
- astroid = builder.string_build(code, __name__, __file__)
- a1 = astroid.locals['A'][0]
- a2 = astroid.locals['A'][1]
- a2_ancestors = list(a2.ancestors())
- self.assertEqual(len(a2_ancestors), 2)
- self.assertIs(a2_ancestors[0], astroid.locals['B'][0])
- self.assertIs(a2_ancestors[1], a1)
-
-
- def test_f_arg_f(self):
- code = '''
-def f(f=1):
- return f
-
-a = f()
- '''
- astroid = builder.string_build(code, __name__, __file__)
- a = astroid['a']
- a_infered = a.infered()
- self.assertEqual(a_infered[0].value, 1)
- self.assertEqual(len(a_infered), 1)
-
- def test_exc_ancestors(self):
- code = '''
-def f():
- raise NotImplementedError
- '''
- astroid = builder.string_build(code, __name__, __file__)
- error = astroid.nodes_of_class(nodes.Name).next()
- nie = error.infered()[0]
- self.assertIsInstance(nie, nodes.Class)
- nie_ancestors = [c.name for c in nie.ancestors()]
- if sys.version_info < (3, 0):
- self.assertEqual(nie_ancestors, ['RuntimeError', 'StandardError', 'Exception', 'BaseException', 'object'])
- else:
- self.assertEqual(nie_ancestors, ['RuntimeError', 'Exception', 'BaseException', 'object'])
-
- def test_except_inference(self):
- code = '''
-try:
- print (hop)
-except NameError, ex:
- ex1 = ex
-except Exception, ex:
- ex2 = ex
- raise
- '''
- if sys.version_info >= (3, 0):
- code = code.replace(', ex:', ' as ex:')
- astroid = builder.string_build(code, __name__, __file__)
- ex1 = astroid['ex1']
- ex1_infer = ex1.infer()
- ex1 = ex1_infer.next()
- self.assertIsInstance(ex1, Instance)
- self.assertEqual(ex1.name, 'NameError')
- self.assertRaises(StopIteration, ex1_infer.next)
- ex2 = astroid['ex2']
- ex2_infer = ex2.infer()
- ex2 = ex2_infer.next()
- self.assertIsInstance(ex2, Instance)
- self.assertEqual(ex2.name, 'Exception')
- self.assertRaises(StopIteration, ex2_infer.next)
-
- def test_del1(self):
- code = '''
-del undefined_attr
- '''
- delete = builder.string_build(code, __name__, __file__).body[0]
- self.assertRaises(InferenceError, delete.infer)
-
- def test_del2(self):
- code = '''
-a = 1
-b = a
-del a
-c = a
-a = 2
-d = a
- '''
- astroid = builder.string_build(code, __name__, __file__)
- n = astroid['b']
- n_infer = n.infer()
- infered = n_infer.next()
- self.assertIsInstance(infered, nodes.Const)
- self.assertEqual(infered.value, 1)
- self.assertRaises(StopIteration, n_infer.next)
- n = astroid['c']
- n_infer = n.infer()
- self.assertRaises(InferenceError, n_infer.next)
- n = astroid['d']
- n_infer = n.infer()
- infered = n_infer.next()
- self.assertIsInstance(infered, nodes.Const)
- self.assertEqual(infered.value, 2)
- self.assertRaises(StopIteration, n_infer.next)
-
- def test_builtin_types(self):
- code = '''
-l = [1]
-t = (2,)
-d = {}
-s = ''
-s2 = '_'
- '''
- astroid = builder.string_build(code, __name__, __file__)
- n = astroid['l']
- infered = n.infer().next()
- self.assertIsInstance(infered, nodes.List)
- self.assertIsInstance(infered, Instance)
- self.assertEqual(infered.getitem(0).value, 1)
- self.assertIsInstance(infered._proxied, nodes.Class)
- self.assertEqual(infered._proxied.name, 'list')
- self.assertIn('append', infered._proxied.locals)
- n = astroid['t']
- infered = n.infer().next()
- self.assertIsInstance(infered, nodes.Tuple)
- self.assertIsInstance(infered, Instance)
- self.assertEqual(infered.getitem(0).value, 2)
- self.assertIsInstance(infered._proxied, nodes.Class)
- self.assertEqual(infered._proxied.name, 'tuple')
- n = astroid['d']
- infered = n.infer().next()
- self.assertIsInstance(infered, nodes.Dict)
- self.assertIsInstance(infered, Instance)
- self.assertIsInstance(infered._proxied, nodes.Class)
- self.assertEqual(infered._proxied.name, 'dict')
- self.assertIn('get', infered._proxied.locals)
- n = astroid['s']
- infered = n.infer().next()
- self.assertIsInstance(infered, nodes.Const)
- self.assertIsInstance(infered, Instance)
- self.assertEqual(infered.name, 'str')
- self.assertIn('lower', infered._proxied.locals)
- n = astroid['s2']
- infered = n.infer().next()
- self.assertEqual(infered.getitem(0).value, '_')
-
- @require_version('2.7')
- def test_builtin_types_py27(self):
- code = 's = {1}'
- astroid = builder.string_build(code, __name__, __file__)
- n = astroid['s']
- infered = n.infer().next()
- self.assertIsInstance(infered, nodes.Set)
- self.assertIsInstance(infered, Instance)
- self.assertEqual(infered.name, 'set')
- self.assertIn('remove', infered._proxied.locals)
-
- def test_unicode_type(self):
- if sys.version_info >= (3, 0):
- self.skipTest('unicode removed on py >= 3.0')
- code = '''u = u""'''
- astroid = builder.string_build(code, __name__, __file__)
- n = astroid['u']
- infered = n.infer().next()
- self.assertIsInstance(infered, nodes.Const)
- self.assertIsInstance(infered, Instance)
- self.assertEqual(infered.name, 'unicode')
- self.assertIn('lower', infered._proxied.locals)
-
- def test_descriptor_are_callable(self):
- code = '''
-class A:
- statm = staticmethod(open)
- clsm = classmethod('whatever')
- '''
- astroid = builder.string_build(code, __name__, __file__)
- statm = astroid['A'].igetattr('statm').next()
- self.assertTrue(statm.callable())
- clsm = astroid['A'].igetattr('clsm').next()
- self.assertTrue(clsm.callable())
-
- def test_bt_ancestor_crash(self):
- code = '''
-class Warning(Warning):
- pass
- '''
- astroid = builder.string_build(code, __name__, __file__)
- w = astroid['Warning']
- ancestors = w.ancestors()
- ancestor = ancestors.next()
- self.assertEqual(ancestor.name, 'Warning')
- self.assertEqual(ancestor.root().name, EXC_MODULE)
- ancestor = ancestors.next()
- self.assertEqual(ancestor.name, 'Exception')
- self.assertEqual(ancestor.root().name, EXC_MODULE)
- ancestor = ancestors.next()
- self.assertEqual(ancestor.name, 'BaseException')
- self.assertEqual(ancestor.root().name, EXC_MODULE)
- ancestor = ancestors.next()
- self.assertEqual(ancestor.name, 'object')
- self.assertEqual(ancestor.root().name, BUILTINS)
- self.assertRaises(StopIteration, ancestors.next)
-
- def test_qqch(self):
- code = '''
-from logilab.common.modutils import load_module_from_name
-xxx = load_module_from_name('__pkginfo__')
- '''
- astroid = builder.string_build(code, __name__, __file__)
- xxx = astroid['xxx']
- self.assertSetEqual(set(n.__class__ for n in xxx.infered()),
- set([nodes.Const, YES.__class__]))
-
- def test_method_argument(self):
- code = '''
-class ErudiEntitySchema:
- """a entity has a type, a set of subject and or object relations"""
- def __init__(self, e_type, **kwargs):
- kwargs['e_type'] = e_type.capitalize().encode()
-
- def meth(self, e_type, *args, **kwargs):
- kwargs['e_type'] = e_type.capitalize().encode()
- print(args)
- '''
- astroid = builder.string_build(code, __name__, __file__)
- arg = get_name_node(astroid['ErudiEntitySchema']['__init__'], 'e_type')
- self.assertEqual([n.__class__ for n in arg.infer()],
- [YES.__class__])
- arg = get_name_node(astroid['ErudiEntitySchema']['__init__'], 'kwargs')
- self.assertEqual([n.__class__ for n in arg.infer()],
- [nodes.Dict])
- arg = get_name_node(astroid['ErudiEntitySchema']['meth'], 'e_type')
- self.assertEqual([n.__class__ for n in arg.infer()],
- [YES.__class__])
- arg = get_name_node(astroid['ErudiEntitySchema']['meth'], 'args')
- self.assertEqual([n.__class__ for n in arg.infer()],
- [nodes.Tuple])
- arg = get_name_node(astroid['ErudiEntitySchema']['meth'], 'kwargs')
- self.assertEqual([n.__class__ for n in arg.infer()],
- [nodes.Dict])
-
-
- def test_tuple_then_list(self):
- code = '''
-def test_view(rql, vid, tags=()):
- tags = list(tags)
- tags.append(vid)
- '''
- astroid = builder.string_build(code, __name__, __file__)
- name = get_name_node(astroid['test_view'], 'tags', -1)
- it = name.infer()
- tags = it.next()
- self.assertEqual(tags.__class__, Instance)
- self.assertEqual(tags._proxied.name, 'list')
- self.assertRaises(StopIteration, it.next)
-
-
-
- def test_mulassign_inference(self):
- code = '''
-
-def first_word(line):
- """Return the first word of a line"""
-
- return line.split()[0]
-
-def last_word(line):
- """Return last word of a line"""
-
- return line.split()[-1]
-
-def process_line(word_pos):
- """Silly function: returns (ok, callable) based on argument.
-
- For test purpose only.
- """
-
- if word_pos > 0:
- return (True, first_word)
- elif word_pos < 0:
- return (True, last_word)
- else:
- return (False, None)
-
-if __name__ == '__main__':
-
- line_number = 0
- for a_line in file('test_callable.py'):
- tupletest = process_line(line_number)
- (ok, fct) = process_line(line_number)
- if ok:
- fct(a_line)
-'''
- astroid = builder.string_build(code, __name__, __file__)
- self.assertEqual(len(list(astroid['process_line'].infer_call_result(
- None))), 3)
- self.assertEqual(len(list(astroid['tupletest'].infer())), 3)
- values = ['Function(first_word)', 'Function(last_word)', 'Const(NoneType)']
- self.assertEqual([str(infered)
- for infered in astroid['fct'].infer()], values)
-
- def test_float_complex_ambiguity(self):
- code = '''
-def no_conjugate_member(magic_flag):
- """should not raise E1101 on something.conjugate"""
- if magic_flag:
- something = 1.0
- else:
- something = 1.0j
- if isinstance(something, float):
- return something
- return something.conjugate()
- '''
- astroid = builder.string_build(code, __name__, __file__)
- self.assertEqual([i.value for i in
- astroid['no_conjugate_member'].ilookup('something')], [1.0, 1.0j])
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'something', -1).infer()], [1.0, 1.0j])
-
- def test_lookup_cond_branches(self):
- code = '''
-def no_conjugate_member(magic_flag):
- """should not raise E1101 on something.conjugate"""
- something = 1.0
- if magic_flag:
- something = 1.0j
- return something.conjugate()
- '''
- astroid = builder.string_build(code, __name__, __file__)
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'something', -1).infer()], [1.0, 1.0j])
-
-
- def test_simple_subscript(self):
- code = '''
-a = [1, 2, 3][0]
-b = (1, 2, 3)[1]
-c = (1, 2, 3)[-1]
-d = a + b + c
-print (d)
-e = {'key': 'value'}
-f = e['key']
-print (f)
- '''
- astroid = builder.string_build(code, __name__, __file__)
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'a', -1).infer()], [1])
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'b', -1).infer()], [2])
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'c', -1).infer()], [3])
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'd', -1).infer()], [6])
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'f', -1).infer()], ['value'])
-
- #def test_simple_tuple(self):
- #"""test case for a simple tuple value"""
- ## XXX tuple inference is not implemented ...
- #code = """
-#a = (1,)
-#b = (22,)
-#some = a + b
-#"""
- #astroid = builder.string_build(code, __name__, __file__)
- #self.assertEqual(astroid['some'].infer.next().as_string(), "(1, 22)")
-
- def test_simple_for(self):
- code = '''
-for a in [1, 2, 3]:
- print (a)
-for b,c in [(1,2), (3,4)]:
- print (b)
- print (c)
-
-print ([(d,e) for e,d in ([1,2], [3,4])])
- '''
- astroid = builder.string_build(code, __name__, __file__)
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'a', -1).infer()], [1, 2, 3])
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'b', -1).infer()], [1, 3])
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'c', -1).infer()], [2, 4])
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'd', -1).infer()], [2, 4])
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'e', -1).infer()], [1, 3])
-
-
- def test_simple_for_genexpr(self):
- code = '''
-print ((d,e) for e,d in ([1,2], [3,4]))
- '''
- astroid = builder.string_build(code, __name__, __file__)
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'd', -1).infer()], [2, 4])
- self.assertEqual([i.value for i in
- get_name_node(astroid, 'e', -1).infer()], [1, 3])
-
-
- def test_builtin_help(self):
- code = '''
-help()
- '''
- # XXX failing since __builtin__.help assignment has
- # been moved into a function...
- astroid = builder.string_build(code, __name__, __file__)
- node = get_name_node(astroid, 'help', -1)
- infered = list(node.infer())
- self.assertEqual(len(infered), 1, infered)
- self.assertIsInstance(infered[0], Instance)
- self.assertEqual(str(infered[0]),
- 'Instance of site._Helper')
-
- def test_builtin_open(self):
- code = '''
-open("toto.txt")
- '''
- astroid = builder.string_build(code, __name__, __file__)
- node = get_name_node(astroid, 'open', -1)
- infered = list(node.infer())
- self.assertEqual(len(infered), 1)
- if hasattr(sys, 'pypy_version_info'):
- self.assertIsInstance(infered[0], nodes.Class)
- self.assertEqual(infered[0].name, 'file')
- else:
- self.assertIsInstance(infered[0], nodes.Function)
- self.assertEqual(infered[0].name, 'open')
-
- def test_callfunc_context_func(self):
- code = '''
-def mirror(arg=None):
- return arg
-
-un = mirror(1)
- '''
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(astroid.igetattr('un'))
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.Const)
- self.assertEqual(infered[0].value, 1)
-
- def test_callfunc_context_lambda(self):
- code = '''
-mirror = lambda x=None: x
-
-un = mirror(1)
- '''
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(astroid.igetattr('mirror'))
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.Lambda)
- infered = list(astroid.igetattr('un'))
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.Const)
- self.assertEqual(infered[0].value, 1)
-
- def test_factory_method(self):
- code = '''
-class Super(object):
- @classmethod
- def instance(cls):
- return cls()
-
-class Sub(Super):
- def method(self):
- print ('method called')
-
-sub = Sub.instance()
- '''
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(astroid.igetattr('sub'))
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], Instance)
- self.assertEqual(infered[0]._proxied.name, 'Sub')
-
-
- def test_import_as(self):
- code = '''
-import os.path as osp
-print (osp.dirname(__file__))
-
-from os.path import exists as e
-assert e(__file__)
-
-from new import code as make_code
-print (make_code)
- '''
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(astroid.igetattr('osp'))
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.Module)
- self.assertEqual(infered[0].name, 'os.path')
- infered = list(astroid.igetattr('e'))
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.Function)
- self.assertEqual(infered[0].name, 'exists')
- if sys.version_info >= (3, 0):
- self.skipTest(' module has been removed')
- infered = list(astroid.igetattr('make_code'))
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], Instance)
- self.assertEqual(str(infered[0]),
- 'Instance of %s.type' % BUILTINS)
-
- def _test_const_infered(self, node, value):
- infered = list(node.infer())
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.Const)
- self.assertEqual(infered[0].value, value)
-
- def test_unary_not(self):
- for code in ('a = not (1,); b = not ()',
- 'a = not {1:2}; b = not {}'):
- astroid = builder.string_build(code, __name__, __file__)
- self._test_const_infered(astroid['a'], False)
- self._test_const_infered(astroid['b'], True)
-
- def test_binary_op_int_add(self):
- astroid = builder.string_build('a = 1 + 2', __name__, __file__)
- self._test_const_infered(astroid['a'], 3)
-
- def test_binary_op_int_sub(self):
- astroid = builder.string_build('a = 1 - 2', __name__, __file__)
- self._test_const_infered(astroid['a'], -1)
-
- def test_binary_op_float_div(self):
- astroid = builder.string_build('a = 1 / 2.', __name__, __file__)
- self._test_const_infered(astroid['a'], 1 / 2.)
-
- def test_binary_op_str_mul(self):
- astroid = builder.string_build('a = "*" * 40', __name__, __file__)
- self._test_const_infered(astroid['a'], "*" * 40)
-
- def test_binary_op_bitand(self):
- astroid = builder.string_build('a = 23&20', __name__, __file__)
- self._test_const_infered(astroid['a'], 23&20)
-
- def test_binary_op_bitor(self):
- astroid = builder.string_build('a = 23|8', __name__, __file__)
- self._test_const_infered(astroid['a'], 23|8)
-
- def test_binary_op_bitxor(self):
- astroid = builder.string_build('a = 23^9', __name__, __file__)
- self._test_const_infered(astroid['a'], 23^9)
-
- def test_binary_op_shiftright(self):
- astroid = builder.string_build('a = 23 >>1', __name__, __file__)
- self._test_const_infered(astroid['a'], 23>>1)
-
- def test_binary_op_shiftleft(self):
- astroid = builder.string_build('a = 23 <<1', __name__, __file__)
- self._test_const_infered(astroid['a'], 23<<1)
-
-
- def test_binary_op_list_mul(self):
- for code in ('a = [[]] * 2', 'a = 2 * [[]]'):
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(astroid['a'].infer())
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.List)
- self.assertEqual(len(infered[0].elts), 2)
- self.assertIsInstance(infered[0].elts[0], nodes.List)
- self.assertIsInstance(infered[0].elts[1], nodes.List)
-
- def test_binary_op_list_mul_none(self):
- 'test correct handling on list multiplied by None'
- astroid = builder.string_build( 'a = [1] * None\nb = [1] * "r"')
- infered = astroid['a'].infered()
- self.assertEqual(len(infered), 1)
- self.assertEqual(infered[0], YES)
- infered = astroid['b'].infered()
- self.assertEqual(len(infered), 1)
- self.assertEqual(infered[0], YES)
-
-
- def test_binary_op_tuple_add(self):
- astroid = builder.string_build('a = (1,) + (2,)', __name__, __file__)
- infered = list(astroid['a'].infer())
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.Tuple)
- self.assertEqual(len(infered[0].elts), 2)
- self.assertEqual(infered[0].elts[0].value, 1)
- self.assertEqual(infered[0].elts[1].value, 2)
-
- def test_binary_op_custom_class(self):
- code = '''
-class myarray:
- def __init__(self, array):
- self.array = array
- def __mul__(self, x):
- return myarray([2,4,6])
- def astype(self):
- return "ASTYPE"
-
-def randint(maximum):
- if maximum is not None:
- return myarray([1,2,3]) * 2
- else:
- return int(5)
-
-x = randint(1)
- '''
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(astroid.igetattr('x'))
- self.assertEqual(len(infered), 2)
- value = [str(v) for v in infered]
- # The __name__ trick here makes it work when invoked directly
- # (__name__ == '__main__') and through pytest (__name__ ==
- # 'unittest_inference')
- self.assertEqual(value, ['Instance of %s.myarray' % __name__,
- 'Instance of %s.int' % BUILTINS])
-
- def test_nonregr_lambda_arg(self):
- code = '''
-def f(g = lambda: None):
- g().x
-'''
- astroid = builder.string_build(code, __name__, __file__)
- callfuncnode = astroid['f'].body[0].value.expr
- infered = list(callfuncnode.infer())
- self.assertEqual(len(infered), 2, infered)
- infered.remove(YES)
- self.assertIsInstance(infered[0], nodes.Const)
- self.assertIsNone(infered[0].value)
-
- def test_nonregr_getitem_empty_tuple(self):
- code = '''
-def f(x):
- a = ()[x]
- '''
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(astroid['f'].ilookup('a'))
- self.assertEqual(len(infered), 1)
- self.assertEqual(infered[0], YES)
-
- def test_python25_generator_exit(self):
- sys.stderr = StringIO()
- data = "b = {}[str(0)+''].a"
- astroid = builder.string_build(data, __name__, __file__)
- list(astroid['b'].infer())
- output = sys.stderr.getvalue()
- # I have no idea how to test for this in another way...
- self.assertNotIn("RuntimeError", output, "Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in ignored")
- sys.stderr = sys.__stderr__
-
- def test_python25_relative_import(self):
- data = "from ...logilab.common import date; print (date)"
- # !! FIXME also this relative import would not work 'in real' (no __init__.py in test/)
- # the test works since we pretend we have a package by passing the full modname
- astroid = builder.string_build(data, 'astroid.test.unittest_inference', __file__)
- infered = get_name_node(astroid, 'date').infer().next()
- self.assertIsInstance(infered, nodes.Module)
- self.assertEqual(infered.name, 'logilab.common.date')
-
- def test_python25_no_relative_import(self):
- fname = join(abspath(dirname(__file__)), 'regrtest_data', 'package', 'absimport.py')
- astroid = builder.file_build(fname, 'absimport')
- self.assertTrue(astroid.absolute_import_activated(), True)
- infered = get_name_node(astroid, 'import_package_subpackage_module').infer().next()
- # failed to import since absolute_import is activated
- self.assertIs(infered, YES)
-
- def test_nonregr_absolute_import(self):
- fname = join(abspath(dirname(__file__)), 'regrtest_data', 'absimp', 'string.py')
- astroid = builder.file_build(fname, 'absimp.string')
- self.assertTrue(astroid.absolute_import_activated(), True)
- infered = get_name_node(astroid, 'string').infer().next()
- self.assertIsInstance(infered, nodes.Module)
- self.assertEqual(infered.name, 'string')
- self.assertIn('ascii_letters', infered.locals)
-
- def test_mechanize_open(self):
- try:
- import mechanize
- except ImportError:
- self.skipTest('require mechanize installed')
- data = '''from mechanize import Browser
-print (Browser)
-b = Browser()
-'''
- astroid = builder.string_build(data, __name__, __file__)
- browser = get_name_node(astroid, 'Browser').infer().next()
- self.assertIsInstance(browser, nodes.Class)
- bopen = list(browser.igetattr('open'))
- self.skipTest('the commit said: "huum, see that later"')
- self.assertEqual(len(bopen), 1)
- self.assertIsInstance(bopen[0], nodes.Function)
- self.assertTrue(bopen[0].callable())
- b = get_name_node(astroid, 'b').infer().next()
- self.assertIsInstance(b, Instance)
- bopen = list(b.igetattr('open'))
- self.assertEqual(len(bopen), 1)
- self.assertIsInstance(bopen[0], BoundMethod)
- self.assertTrue(bopen[0].callable())
-
- def test_property(self):
- code = '''
-from smtplib import SMTP
-class SendMailController(object):
-
- @property
- def smtp(self):
- return SMTP(mailhost, port)
-
- @property
- def me(self):
- return self
-
-my_smtp = SendMailController().smtp
-my_me = SendMailController().me
-'''
- decorators = set(['%s.property' % BUILTINS])
- astroid = builder.string_build(code, __name__, __file__)
- self.assertEqual(astroid['SendMailController']['smtp'].decoratornames(),
- decorators)
- propinfered = list(astroid.body[2].value.infer())
- self.assertEqual(len(propinfered), 1)
- propinfered = propinfered[0]
- self.assertIsInstance(propinfered, Instance)
- self.assertEqual(propinfered.name, 'SMTP')
- self.assertEqual(propinfered.root().name, 'smtplib')
- self.assertEqual(astroid['SendMailController']['me'].decoratornames(),
- decorators)
- propinfered = list(astroid.body[3].value.infer())
- self.assertEqual(len(propinfered), 1)
- propinfered = propinfered[0]
- self.assertIsInstance(propinfered, Instance)
- self.assertEqual(propinfered.name, 'SendMailController')
- self.assertEqual(propinfered.root().name, __name__)
-
-
- def test_im_func_unwrap(self):
- code = '''
-class EnvBasedTC:
- def pactions(self):
- pass
-pactions = EnvBasedTC.pactions.im_func
-print (pactions)
-
-class EnvBasedTC2:
- pactions = EnvBasedTC.pactions.im_func
- print (pactions)
-
-'''
- astroid = builder.string_build(code, __name__, __file__)
- pactions = get_name_node(astroid, 'pactions')
- infered = list(pactions.infer())
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.Function)
- pactions = get_name_node(astroid['EnvBasedTC2'], 'pactions')
- infered = list(pactions.infer())
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.Function)
-
- def test_augassign(self):
- code = '''
-a = 1
-a += 2
-print (a)
-'''
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(get_name_node(astroid, 'a').infer())
-
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], nodes.Const)
- self.assertEqual(infered[0].value, 3)
-
- def test_nonregr_func_arg(self):
- code = '''
-def foo(self, bar):
- def baz():
- pass
- def qux():
- return baz
- spam = bar(None, qux)
- print (spam)
-'''
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(get_name_node(astroid['foo'], 'spam').infer())
- self.assertEqual(len(infered), 1)
- self.assertIs(infered[0], YES)
-
- def test_nonregr_func_global(self):
- code = '''
-active_application = None
-
-def get_active_application():
- global active_application
- return active_application
-
-class Application(object):
- def __init__(self):
- global active_application
- active_application = self
-
-class DataManager(object):
- def __init__(self, app=None):
- self.app = get_active_application()
- def test(self):
- p = self.app
- print (p)
- '''
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(Instance(astroid['DataManager']).igetattr('app'))
- self.assertEqual(len(infered), 2, infered) # None / Instance(Application)
- infered = list(get_name_node(astroid['DataManager']['test'], 'p').infer())
- self.assertEqual(len(infered), 2, infered)
- for node in infered:
- if isinstance(node, Instance) and node.name == 'Application':
- break
- else:
- self.fail('expected to find an instance of Application in %s' % infered)
-
- def test_list_inference(self):
- """#20464"""
- code = '''
-import optparse
-
-A = []
-B = []
-
-def test():
- xyz = [
- "foobar=%s" % options.ca,
- ] + A + B
-
- if options.bind is not None:
- xyz.append("bind=%s" % options.bind)
- return xyz
-
-def main():
- global options
-
- parser = optparse.OptionParser()
- (options, args) = parser.parse_args()
-
-Z = test()
- '''
- astroid = builder.string_build(code, __name__, __file__)
- infered = list(astroid['Z'].infer())
- self.assertEqual(len(infered), 1, infered)
- self.assertIsInstance(infered[0], Instance)
- self.assertIsInstance(infered[0]._proxied, nodes.Class)
- self.assertEqual(infered[0]._proxied.name, 'list')
-
- def test__new__(self):
- code = '''
-class NewTest(object):
- "doc"
- def __new__(cls, arg):
- self = object.__new__(cls)
- self.arg = arg
- return self
-
-n = NewTest()
- '''
- astroid = builder.string_build(code, __name__, __file__)
- self.assertRaises(InferenceError, list, astroid['NewTest'].igetattr('arg'))
- n = astroid['n'].infer().next()
- infered = list(n.igetattr('arg'))
- self.assertEqual(len(infered), 1, infered)
-
-
- def test_two_parents_from_same_module(self):
- code = '''
-from data import nonregr
-class Xxx(nonregr.Aaa, nonregr.Ccc):
- "doc"
- '''
- astroid = builder.string_build(code, __name__, __file__)
- parents = list(astroid['Xxx'].ancestors())
- self.assertEqual(len(parents), 3, parents) # Aaa, Ccc, object
-
- def test_pluggable_inference(self):
- code = '''
-from collections import namedtuple
-A = namedtuple('A', ['a', 'b'])
-B = namedtuple('B', 'a b')
- '''
- astroid = builder.string_build(code, __name__, __file__)
- aclass = astroid['A'].infered()[0]
- self.assertIsInstance(aclass, nodes.Class)
- self.assertIn('a', aclass.instance_attrs)
- self.assertIn('b', aclass.instance_attrs)
- bclass = astroid['B'].infered()[0]
- self.assertIsInstance(bclass, nodes.Class)
- self.assertIn('a', bclass.instance_attrs)
- self.assertIn('b', bclass.instance_attrs)
-
-
-if __name__ == '__main__':
- unittest_main()
diff -Nru astroid-1.0.1/test/unittest_inspector.py astroid-1.3.8/test/unittest_inspector.py
--- astroid-1.0.1/test/unittest_inspector.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/unittest_inspector.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,93 +0,0 @@
-# Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE).
-# http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This program is free software; you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or (at your option) any later
-# version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-"""
- for the visitors.diadefs module
-"""
-
-import sys
-from os.path import join, abspath, dirname
-
-from logilab.common.testlib import TestCase, unittest_main
-
-from astroid import nodes, inspector
-from astroid.bases import Instance, YES
-
-from astroid.manager import AstroidManager, _silent_no_wrap
-
-MANAGER = AstroidManager()
-
-def astroid_wrapper(func, modname):
- return func(modname)
-
-
-DATA2 = join(dirname(abspath(__file__)), 'data2')
-
-
-class LinkerTC(TestCase):
-
- def setUp(self):
- self.project = MANAGER.project_from_files([DATA2], astroid_wrapper)
- self.linker = inspector.Linker(self.project)
- self.linker.visit(self.project)
-
- def test_class_implements(self):
- klass = self.project.get_module('data2.clientmodule_test')['Ancestor']
- self.assertTrue(hasattr(klass, 'implements'))
- self.assertEqual(len(klass.implements), 1)
- self.assertTrue(isinstance(klass.implements[0], nodes.Class))
- self.assertEqual(klass.implements[0].name, "Interface")
- klass = self.project.get_module('data2.clientmodule_test')['Specialization']
- self.assertTrue(hasattr(klass, 'implements'))
- self.assertEqual(len(klass.implements), 0)
-
- def test_locals_assignment_resolution(self):
- klass = self.project.get_module('data2.clientmodule_test')['Specialization']
- self.assertTrue(hasattr(klass, 'locals_type'))
- type_dict = klass.locals_type
- self.assertEqual(len(type_dict), 2)
- keys = sorted(type_dict.keys())
- self.assertEqual(keys, ['TYPE', 'top'])
- self.assertEqual(len(type_dict['TYPE']), 1)
- self.assertEqual(type_dict['TYPE'][0].value, 'final class')
- self.assertEqual(len(type_dict['top']), 1)
- self.assertEqual(type_dict['top'][0].value, 'class')
-
- def test_instance_attrs_resolution(self):
- klass = self.project.get_module('data2.clientmodule_test')['Specialization']
- self.assertTrue(hasattr(klass, 'instance_attrs_type'))
- type_dict = klass.instance_attrs_type
- self.assertEqual(len(type_dict), 3)
- keys = sorted(type_dict.keys())
- self.assertEqual(keys, ['_id', 'relation', 'toto'])
- self.assertTrue(isinstance(type_dict['relation'][0], Instance), type_dict['relation'])
- self.assertEqual(type_dict['relation'][0].name, 'DoNothing')
- self.assertTrue(isinstance(type_dict['toto'][0], Instance), type_dict['toto'])
- self.assertEqual(type_dict['toto'][0].name, 'Toto')
- self.assertIs(type_dict['_id'][0], YES)
-
-
-class LinkerTC2(LinkerTC):
-
- def setUp(self):
- self.project = MANAGER.project_from_files([DATA2], func_wrapper=_silent_no_wrap)
- self.linker = inspector.Linker(self.project)
- self.linker.visit(self.project)
-
-__all__ = ('LinkerTC', 'LinkerTC2')
-
-
-if __name__ == '__main__':
- unittest_main()
diff -Nru astroid-1.0.1/test/unittest_lookup.py astroid-1.3.8/test/unittest_lookup.py
--- astroid-1.0.1/test/unittest_lookup.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/unittest_lookup.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,360 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""tests for the astroid variable lookup capabilities
-"""
-import sys
-from os.path import join, abspath, dirname
-
-from logilab.common.testlib import TestCase, unittest_main, require_version
-
-from astroid import builder, nodes, scoped_nodes, \
- InferenceError, NotFoundError, UnresolvableName
-from astroid.scoped_nodes import builtin_lookup, Function
-from astroid.bases import YES
-from unittest_inference import get_name_node
-
-builder = builder.AstroidBuilder()
-DATA = join(dirname(abspath(__file__)), 'data')
-MODULE = builder.file_build(join(DATA, 'module.py'), 'data.module')
-MODULE2 = builder.file_build(join(DATA, 'module2.py'), 'data.module2')
-NONREGR = builder.file_build(join(DATA, 'nonregr.py'), 'data.nonregr')
-
-class LookupTC(TestCase):
-
- def test_limit(self):
- code = '''
-l = [a
- for a,b in list]
-
-a = 1
-b = a
-a = None
-
-def func():
- c = 1
- '''
- astroid = builder.string_build(code, __name__, __file__)
- # a & b
- a = astroid.nodes_of_class(nodes.Name).next()
- self.assertEqual(a.lineno, 2)
- if sys.version_info < (3, 0):
- self.assertEqual(len(astroid.lookup('b')[1]), 2)
- self.assertEqual(len(astroid.lookup('a')[1]), 3)
- b = astroid.locals['b'][1]
- else:
- self.assertEqual(len(astroid.lookup('b')[1]), 1)
- self.assertEqual(len(astroid.lookup('a')[1]), 2)
- b = astroid.locals['b'][0]
- stmts = a.lookup('a')[1]
- self.assertEqual(len(stmts), 1)
- self.assertEqual(b.lineno, 6)
- b_infer = b.infer()
- b_value = b_infer.next()
- self.assertEqual(b_value.value, 1)
- # c
- self.assertRaises(StopIteration, b_infer.next)
- func = astroid.locals['func'][0]
- self.assertEqual(len(func.lookup('c')[1]), 1)
-
- def test_module(self):
- astroid = builder.string_build('pass', __name__, __file__)
- # built-in objects
- none = astroid.ilookup('None').next()
- self.assertIsNone(none.value)
- obj = astroid.ilookup('object').next()
- self.assertIsInstance(obj, nodes.Class)
- self.assertEqual(obj.name, 'object')
- self.assertRaises(InferenceError, astroid.ilookup('YOAA').next)
-
- # XXX
- self.assertEqual(len(list(NONREGR.ilookup('enumerate'))), 2)
-
- def test_class_ancestor_name(self):
- code = '''
-class A:
- pass
-
-class A(A):
- pass
- '''
- astroid = builder.string_build(code, __name__, __file__)
- cls1 = astroid.locals['A'][0]
- cls2 = astroid.locals['A'][1]
- name = cls2.nodes_of_class(nodes.Name).next()
- self.assertEqual(name.infer().next(), cls1)
-
- ### backport those test to inline code
- def test_method(self):
- method = MODULE['YOUPI']['method']
- my_dict = method.ilookup('MY_DICT').next()
- self.assertTrue(isinstance(my_dict, nodes.Dict), my_dict)
- none = method.ilookup('None').next()
- self.assertIsNone(none.value)
- self.assertRaises(InferenceError, method.ilookup('YOAA').next)
-
-
- def test_function_argument_with_default(self):
- make_class = MODULE2['make_class']
- base = make_class.ilookup('base').next()
- self.assertTrue(isinstance(base, nodes.Class), base.__class__)
- self.assertEqual(base.name, 'YO')
- self.assertEqual(base.root().name, 'data.module')
-
-
- def test_class(self):
- klass = MODULE['YOUPI']
- my_dict = klass.ilookup('MY_DICT').next()
- self.assertIsInstance(my_dict, nodes.Dict)
- none = klass.ilookup('None').next()
- self.assertIsNone(none.value)
- obj = klass.ilookup('object').next()
- self.assertIsInstance(obj, nodes.Class)
- self.assertEqual(obj.name, 'object')
- self.assertRaises(InferenceError, klass.ilookup('YOAA').next)
-
-
- def test_inner_classes(self):
- ddd = list(NONREGR['Ccc'].ilookup('Ddd'))
- self.assertEqual(ddd[0].name, 'Ddd')
-
-
- def test_loopvar_hiding(self):
- astroid = builder.string_build("""
-x = 10
-for x in range(5):
- print (x)
-
-if x > 0:
- print ('#' * x)
- """, __name__, __file__)
- xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'x']
- # inside the loop, only one possible assignment
- self.assertEqual(len(xnames[0].lookup('x')[1]), 1)
- # outside the loop, two possible assignments
- self.assertEqual(len(xnames[1].lookup('x')[1]), 2)
- self.assertEqual(len(xnames[2].lookup('x')[1]), 2)
-
- def test_list_comps(self):
- astroid = builder.string_build("""
-print ([ i for i in range(10) ])
-print ([ i for i in range(10) ])
-print ( list( i for i in range(10) ) )
- """, __name__, __file__)
- xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i']
- self.assertEqual(len(xnames[0].lookup('i')[1]), 1)
- self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2)
- self.assertEqual(len(xnames[1].lookup('i')[1]), 1)
- self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3)
- self.assertEqual(len(xnames[2].lookup('i')[1]), 1)
- self.assertEqual(xnames[2].lookup('i')[1][0].lineno, 4)
-
- def test_list_comp_target(self):
- """test the list comprehension target"""
- astroid = builder.string_build("""
-ten = [ var for var in range(10) ]
-var
- """)
- var = astroid.body[1].value
- if sys.version_info < (3, 0):
- self.assertEqual(var.infered(), [YES])
- else:
- self.assertRaises(UnresolvableName, var.infered)
-
- @require_version('2.7')
- def test_dict_comps(self):
- astroid = builder.string_build("""
-print ({ i: j for i in range(10) for j in range(10) })
-print ({ i: j for i in range(10) for j in range(10) })
- """, __name__, __file__)
- xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i']
- self.assertEqual(len(xnames[0].lookup('i')[1]), 1)
- self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2)
- self.assertEqual(len(xnames[1].lookup('i')[1]), 1)
- self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3)
-
- xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'j']
- self.assertEqual(len(xnames[0].lookup('i')[1]), 1)
- self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2)
- self.assertEqual(len(xnames[1].lookup('i')[1]), 1)
- self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3)
-
- @require_version('2.7')
- def test_set_comps(self):
- astroid = builder.string_build("""
-print ({ i for i in range(10) })
-print ({ i for i in range(10) })
- """, __name__, __file__)
- xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'i']
- self.assertEqual(len(xnames[0].lookup('i')[1]), 1)
- self.assertEqual(xnames[0].lookup('i')[1][0].lineno, 2)
- self.assertEqual(len(xnames[1].lookup('i')[1]), 1)
- self.assertEqual(xnames[1].lookup('i')[1][0].lineno, 3)
-
- @require_version('2.7')
- def test_set_comp_closure(self):
- astroid = builder.string_build("""
-ten = { var for var in range(10) }
-var
- """)
- var = astroid.body[1].value
- self.assertRaises(UnresolvableName, var.infered)
-
- def test_generator_attributes(self):
- tree = builder.string_build("""
-def count():
- "test"
- yield 0
-
-iterer = count()
-num = iterer.next()
- """)
- next = tree.body[2].value.func # Getattr
- gener = next.expr.infered()[0] # Generator
- if sys.version_info < (3, 0):
- self.assertIsInstance(gener.getattr('next')[0], Function)
- else:
- self.assertIsInstance(gener.getattr('__next__')[0], Function)
- self.assertIsInstance(gener.getattr('send')[0], Function)
- self.assertIsInstance(gener.getattr('throw')[0], Function)
- self.assertIsInstance(gener.getattr('close')[0], Function)
-
- def test_explicit___name__(self):
- code = '''
-class Pouet:
- __name__ = "pouet"
-p1 = Pouet()
-
-class PouetPouet(Pouet): pass
-p2 = Pouet()
-
-class NoName: pass
-p3 = NoName()
-'''
- astroid = builder.string_build(code, __name__, __file__)
- p1 = astroid['p1'].infer().next()
- self.assertTrue(p1.getattr('__name__'))
- p2 = astroid['p2'].infer().next()
- self.assertTrue(p2.getattr('__name__'))
- self.assertTrue(astroid['NoName'].getattr('__name__'))
- p3 = astroid['p3'].infer().next()
- self.assertRaises(NotFoundError, p3.getattr, '__name__')
-
-
- def test_function_module_special(self):
- astroid = builder.string_build('''
-def initialize(linter):
- """initialize linter with checkers in this package """
- package_load(linter, __path__[0])
- ''', 'data.__init__', 'data/__init__.py')
- path = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == '__path__'][0]
- self.assertEqual(len(path.lookup('__path__')[1]), 1)
-
-
- def test_builtin_lookup(self):
- self.assertEqual(builtin_lookup('__dict__')[1], ())
- intstmts = builtin_lookup('int')[1]
- self.assertEqual(len(intstmts), 1)
- self.assertIsInstance(intstmts[0], nodes.Class)
- self.assertEqual(intstmts[0].name, 'int')
- self.assertIs(intstmts[0], nodes.const_factory(1)._proxied)
-
-
- def test_decorator_arguments_lookup(self):
- code = '''
-def decorator(value):
- def wrapper(function):
- return function
- return wrapper
-
-class foo:
- member = 10
-
- @decorator(member) #This will cause pylint to complain
- def test(self):
- pass
- '''
- astroid = builder.string_build(code, __name__, __file__)
- member = get_name_node(astroid['foo'], 'member')
- it = member.infer()
- obj = it.next()
- self.assertIsInstance(obj, nodes.Const)
- self.assertEqual(obj.value, 10)
- self.assertRaises(StopIteration, it.next)
-
-
- def test_inner_decorator_member_lookup(self):
- code = '''
-class FileA:
- def decorator(bla):
- return bla
-
- @decorator
- def funcA():
- return 4
- '''
- astroid = builder.string_build(code, __name__, __file__)
- decname = get_name_node(astroid['FileA'], 'decorator')
- it = decname.infer()
- obj = it.next()
- self.assertIsInstance(obj, nodes.Function)
- self.assertRaises(StopIteration, it.next)
-
-
- def test_static_method_lookup(self):
- code = '''
-class FileA:
- @staticmethod
- def funcA():
- return 4
-
-
-class Test:
- FileA = [1,2,3]
-
- def __init__(self):
- print (FileA.funcA())
- '''
- astroid = builder.string_build(code, __name__, __file__)
- it = astroid['Test']['__init__'].ilookup('FileA')
- obj = it.next()
- self.assertIsInstance(obj, nodes.Class)
- self.assertRaises(StopIteration, it.next)
-
-
- def test_global_delete(self):
- code = '''
-def run2():
- f = Frobble()
-
-class Frobble:
- pass
-Frobble.mumble = True
-
-del Frobble
-
-def run1():
- f = Frobble()
-'''
- astroid = builder.string_build(code, __name__, __file__)
- stmts = astroid['run2'].lookup('Frobbel')[1]
- self.assertEqual(len(stmts), 0)
- stmts = astroid['run1'].lookup('Frobbel')[1]
- self.assertEqual(len(stmts), 0)
-
-if __name__ == '__main__':
- unittest_main()
diff -Nru astroid-1.0.1/test/unittest_manager.py astroid-1.3.8/test/unittest_manager.py
--- astroid-1.0.1/test/unittest_manager.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/unittest_manager.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,113 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-from logilab.common.testlib import TestCase, unittest_main
-
-import sys
-from os.path import join, abspath, dirname
-from astroid.manager import AstroidManager, _silent_no_wrap
-from astroid.bases import BUILTINS
-
-DATA = join(dirname(abspath(__file__)), 'data')
-
-class AstroidManagerTC(TestCase):
- def setUp(self):
- self.manager = AstroidManager()
- self.manager.astroid_cache.clear()
-
- def test_ast_from_module(self):
- import unittest
- astroid = self.manager.ast_from_module(unittest)
- self.assertEqual(astroid.pure_python, True)
- import time
- astroid = self.manager.ast_from_module(time)
- self.assertEqual(astroid.pure_python, False)
-
- def test_ast_from_class(self):
- astroid = self.manager.ast_from_class(int)
- self.assertEqual(astroid.name, 'int')
- self.assertEqual(astroid.parent.frame().name, BUILTINS)
-
- astroid = self.manager.ast_from_class(object)
- self.assertEqual(astroid.name, 'object')
- self.assertEqual(astroid.parent.frame().name, BUILTINS)
- self.assertIn('__setattr__', astroid)
-
- def _test_ast_from_zip(self, archive):
- origpath = sys.path[:]
- sys.modules.pop('mypypa', None)
- archive_path = join(DATA, archive)
- sys.path.insert(0, archive_path)
- try:
- module = self.manager.ast_from_module_name('mypypa')
- self.assertEqual(module.name, 'mypypa')
- self.assertTrue(module.file.endswith('%s/mypypa' % archive),
- module.file)
- finally:
- # remove the module, else after importing egg, we don't get the zip
- if 'mypypa' in self.manager.astroid_cache:
- del self.manager.astroid_cache['mypypa']
- del self.manager._mod_file_cache[('mypypa', None)]
- if archive_path in sys.path_importer_cache:
- del sys.path_importer_cache[archive_path]
- sys.path = origpath
-
- def test_ast_from_module_name_egg(self):
- self._test_ast_from_zip('MyPyPa-0.1.0-py2.5.egg')
-
- def test_ast_from_module_name_zip(self):
- self._test_ast_from_zip('MyPyPa-0.1.0-py2.5.zip')
-
- def test_from_directory(self):
- obj = self.manager.project_from_files([DATA], _silent_no_wrap, 'data')
- self.assertEqual(obj.name, 'data')
- self.assertEqual(obj.path, join(DATA, '__init__.py'))
-
- def test_project_node(self):
- obj = self.manager.project_from_files([DATA], _silent_no_wrap, 'data')
- expected = set(['SSL1', '__init__', 'all', 'appl', 'format', 'module',
- 'module2', 'noendingnewline', 'nonregr', 'notall'])
- expected = ['data', 'data.SSL1', 'data.SSL1.Connection1',
- 'data.absimport', 'data.all',
- 'data.appl', 'data.appl.myConnection', 'data.email', 'data.format',
- 'data.module', 'data.module2', 'data.noendingnewline',
- 'data.nonregr', 'data.notall']
- self.assertListEqual(sorted(k for k in obj.keys()), expected)
-
- def test_do_not_expose_main(self):
- obj = self.manager.ast_from_module_name('__main__')
- self.assertEqual(obj.name, '__main__')
- self.assertEqual(obj.items(), [])
-
-
-class BorgAstroidManagerTC(TestCase):
-
- def test_borg(self):
- """test that the AstroidManager is really a borg, i.e. that two different
- instances has same cache"""
- first_manager = AstroidManager()
- built = first_manager.ast_from_module_name(BUILTINS)
-
- second_manager = AstroidManager()
- second_built = first_manager.ast_from_module_name(BUILTINS)
- self.assertIs(built, second_built)
-
-
-if __name__ == '__main__':
- unittest_main()
-
-
diff -Nru astroid-1.0.1/test/unittest_nodes.py astroid-1.3.8/test/unittest_nodes.py
--- astroid-1.0.1/test/unittest_nodes.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/unittest_nodes.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,418 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""tests for specific behaviour of astroid nodes
-"""
-import sys
-
-from logilab.common import testlib
-from astroid.node_classes import unpack_infer
-from astroid.bases import BUILTINS, YES, InferenceContext
-from astroid.exceptions import AstroidBuildingException, NotFoundError
-from astroid import builder, nodes
-
-from data import module as test_module
-
-from os.path import join, abspath, dirname
-
-DATA = join(dirname(abspath(__file__)), 'data')
-
-abuilder = builder.AstroidBuilder()
-
-class AsString(testlib.TestCase):
-
- def test_varargs_kwargs_as_string(self):
- ast = abuilder.string_build( 'raise_string(*args, **kwargs)').body[0]
- self.assertEqual(ast.as_string(), 'raise_string(*args, **kwargs)')
-
- def test_module_as_string(self):
- """check as_string on a whole module prepared to be returned identically
- """
- data = open(join(DATA, 'module.py')).read()
- self.assertMultiLineEqual(MODULE.as_string(), data)
-
- def test_module2_as_string(self):
- """check as_string on a whole module prepared to be returned identically
- """
- data = open(join(DATA, 'module2.py')).read()
- self.assertMultiLineEqual(MODULE2.as_string(), data)
-
- @testlib.require_version('2.7')
- def test_2_7_as_string(self):
- """check as_string for python syntax >= 2.7"""
- code = '''one_two = {1, 2}
-b = {v: k for (k, v) in enumerate('string')}
-cdd = {k for k in b}\n\n'''
- ast = abuilder.string_build(code)
- self.assertMultiLineEqual(ast.as_string(), code)
-
- @testlib.require_version('3.0')
- def test_3k_as_string(self):
- """check as_string for python 3k syntax"""
- code = '''print()
-
-def function(var):
- nonlocal counter
- try:
- hello
- except NameError as nexc:
- (*hell, o) = b'hello'
- raise AttributeError from nexc
-\n'''
- # TODO : annotations and keywords for class definition are not yet implemented
- _todo = '''
-def function(var:int):
- nonlocal counter
-
-class Language(metaclass=Natural):
- """natural language"""
- '''
- ast = abuilder.string_build(code)
- self.assertEqual(ast.as_string(), code)
-
-
-class _NodeTC(testlib.TestCase):
- """test transformation of If Node"""
- CODE = None
- @property
- def astroid(self):
- try:
- return self.__class__.__dict__['CODE_Astroid']
- except KeyError:
- astroid = abuilder.string_build(self.CODE)
- self.__class__.CODE_Astroid = astroid
- return astroid
-
-
-class IfNodeTC(_NodeTC):
- """test transformation of If Node"""
- CODE = """
-if 0:
- print()
-
-if True:
- print()
-else:
- pass
-
-if "":
- print()
-elif []:
- raise
-
-if 1:
- print()
-elif True:
- print()
-elif func():
- pass
-else:
- raise
- """
-
- def test_if_elif_else_node(self):
- """test transformation for If node"""
- self.assertEqual(len(self.astroid.body), 4)
- for stmt in self.astroid.body:
- self.assertIsInstance( stmt, nodes.If)
- self.assertFalse(self.astroid.body[0].orelse) # simple If
- self.assertIsInstance(self.astroid.body[1].orelse[0], nodes.Pass) # If / else
- self.assertIsInstance(self.astroid.body[2].orelse[0], nodes.If) # If / elif
- self.assertIsInstance(self.astroid.body[3].orelse[0].orelse[0], nodes.If)
-
- def test_block_range(self):
- # XXX ensure expected values
- self.assertEqual(self.astroid.block_range(1), (0, 22))
- self.assertEqual(self.astroid.block_range(10), (0, 22)) # XXX (10, 22) ?
- self.assertEqual(self.astroid.body[1].block_range(5), (5, 6))
- self.assertEqual(self.astroid.body[1].block_range(6), (6, 6))
- self.assertEqual(self.astroid.body[1].orelse[0].block_range(7), (7, 8))
- self.assertEqual(self.astroid.body[1].orelse[0].block_range(8), (8, 8))
-
-
-class TryExceptNodeTC(_NodeTC):
- CODE = """
-try:
- print ('pouet')
-except IOError:
- pass
-except UnicodeError:
- print()
-else:
- print()
- """
- def test_block_range(self):
- # XXX ensure expected values
- self.assertEqual(self.astroid.body[0].block_range(1), (1, 8))
- self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
- self.assertEqual(self.astroid.body[0].block_range(3), (3, 8))
- self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
- self.assertEqual(self.astroid.body[0].block_range(5), (5, 5))
- self.assertEqual(self.astroid.body[0].block_range(6), (6, 6))
- self.assertEqual(self.astroid.body[0].block_range(7), (7, 7))
- self.assertEqual(self.astroid.body[0].block_range(8), (8, 8))
-
-
-class TryFinallyNodeTC(_NodeTC):
- CODE = """
-try:
- print ('pouet')
-finally:
- print ('pouet')
- """
- def test_block_range(self):
- # XXX ensure expected values
- self.assertEqual(self.astroid.body[0].block_range(1), (1, 4))
- self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
- self.assertEqual(self.astroid.body[0].block_range(3), (3, 4))
- self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
-
-
-class TryFinally25NodeTC(_NodeTC):
- CODE = """
-try:
- print('pouet')
-except Exception:
- print ('oops')
-finally:
- print ('pouet')
- """
- def test_block_range(self):
- # XXX ensure expected values
- self.assertEqual(self.astroid.body[0].block_range(1), (1, 6))
- self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
- self.assertEqual(self.astroid.body[0].block_range(3), (3, 4))
- self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
- self.assertEqual(self.astroid.body[0].block_range(5), (5, 5))
- self.assertEqual(self.astroid.body[0].block_range(6), (6, 6))
-
-
-class TryExcept2xNodeTC(_NodeTC):
- CODE = """
-try:
- hello
-except AttributeError, (retval, desc):
- pass
- """
- def test_tuple_attribute(self):
- if sys.version_info >= (3, 0):
- self.skipTest('syntax removed from py3.x')
- handler = self.astroid.body[0].handlers[0]
- self.assertIsInstance(handler.name, nodes.Tuple)
-
-
-MODULE = abuilder.module_build(test_module)
-MODULE2 = abuilder.file_build(join(DATA, 'module2.py'), 'data.module2')
-
-
-class ImportNodeTC(testlib.TestCase):
-
- def test_import_self_resolve(self):
- myos = MODULE2.igetattr('myos').next()
- self.assertTrue(isinstance(myos, nodes.Module), myos)
- self.assertEqual(myos.name, 'os')
- self.assertEqual(myos.qname(), 'os')
- self.assertEqual(myos.pytype(), '%s.module' % BUILTINS)
-
- def test_from_self_resolve(self):
- spawn = MODULE.igetattr('spawn').next()
- self.assertTrue(isinstance(spawn, nodes.Class), spawn)
- self.assertEqual(spawn.root().name, 'logilab.common.shellutils')
- self.assertEqual(spawn.qname(), 'logilab.common.shellutils.Execute')
- self.assertEqual(spawn.pytype(), '%s.classobj' % BUILTINS)
- abspath = MODULE2.igetattr('abspath').next()
- self.assertTrue(isinstance(abspath, nodes.Function), abspath)
- self.assertEqual(abspath.root().name, 'os.path')
- self.assertEqual(abspath.qname(), 'os.path.abspath')
- self.assertEqual(abspath.pytype(), '%s.function' % BUILTINS)
-
- def test_real_name(self):
- from_ = MODULE['spawn']
- self.assertEqual(from_.real_name('spawn'), 'Execute')
- imp_ = MODULE['os']
- self.assertEqual(imp_.real_name('os'), 'os')
- self.assertRaises(NotFoundError, imp_.real_name, 'os.path')
- imp_ = MODULE['spawn']
- self.assertEqual(imp_.real_name('spawn'), 'Execute')
- self.assertRaises(NotFoundError, imp_.real_name, 'Execute')
- imp_ = MODULE2['YO']
- self.assertEqual(imp_.real_name('YO'), 'YO')
- self.assertRaises(NotFoundError, imp_.real_name, 'data')
-
- def test_as_string(self):
- ast = MODULE['modutils']
- self.assertEqual(ast.as_string(), "from logilab.common import modutils")
- ast = MODULE['spawn']
- self.assertEqual(ast.as_string(), "from logilab.common.shellutils import Execute as spawn")
- ast = MODULE['os']
- self.assertEqual(ast.as_string(), "import os.path")
- code = """from . import here
-from .. import door
-from .store import bread
-from ..cave import wine\n\n"""
- ast = abuilder.string_build(code)
- self.assertMultiLineEqual(ast.as_string(), code)
-
- def test_bad_import_inference(self):
- # Explication of bug
- '''When we import PickleError from nonexistent, a call to the infer
- method of this From node will be made by unpack_infer.
- inference.infer_from will try to import this module, which will fail and
- raise a InferenceException (by mixins.do_import_module). The infer_name
- will catch this exception and yield and YES instead.
- '''
-
- code = '''try:
- from pickle import PickleError
-except ImportError:
- from nonexistent import PickleError
-
-try:
- pass
-except PickleError:
- pass
- '''
-
- astroid = abuilder.string_build(code)
- from_node = astroid.body[1].handlers[0].body[0]
- handler_type = astroid.body[1].handlers[0].type
-
- excs = list(unpack_infer(handler_type))
-
- def test_absolute_import(self):
- astroid = abuilder.file_build(self.datapath('absimport.py'))
- ctx = InferenceContext()
- ctx.lookupname = 'message'
- # will fail if absolute import failed
- astroid['message'].infer(ctx).next()
- ctx.lookupname = 'email'
- m = astroid['email'].infer(ctx).next()
- self.assertFalse(m.file.startswith(self.datapath('email.py')))
-
-
-class CmpNodeTC(testlib.TestCase):
- def test_as_string(self):
- ast = abuilder.string_build("a == 2").body[0]
- self.assertEqual(ast.as_string(), "a == 2")
-
-
-class ConstNodeTC(testlib.TestCase):
-
- def _test(self, value):
- node = nodes.const_factory(value)
- self.assertIsInstance(node._proxied, nodes.Class)
- self.assertEqual(node._proxied.name, value.__class__.__name__)
- self.assertIs(node.value, value)
- self.assertTrue(node._proxied.parent)
- self.assertEqual(node._proxied.root().name, value.__class__.__module__)
-
- def test_none(self):
- self._test(None)
-
- def test_bool(self):
- self._test(True)
-
- def test_int(self):
- self._test(1)
-
- def test_float(self):
- self._test(1.0)
-
- def test_complex(self):
- self._test(1.0j)
-
- def test_str(self):
- self._test('a')
-
- def test_unicode(self):
- self._test(u'a')
-
-
-class NameNodeTC(testlib.TestCase):
- def test_assign_to_True(self):
- """test that True and False assignements don't crash"""
- code = """True = False
-def hello(False):
- pass
-del True
- """
- if sys.version_info >= (3, 0):
- self.assertRaises(SyntaxError,#might become AstroidBuildingException
- abuilder.string_build, code)
- else:
- ast = abuilder.string_build(code)
- ass_true = ast['True']
- self.assertIsInstance(ass_true, nodes.AssName)
- self.assertEqual(ass_true.name, "True")
- del_true = ast.body[2].targets[0]
- self.assertIsInstance(del_true, nodes.DelName)
- self.assertEqual(del_true.name, "True")
-
-
-class ArgumentsNodeTC(testlib.TestCase):
- def test_linenumbering(self):
- ast = abuilder.string_build('''
-def func(a,
- b): pass
-x = lambda x: None
- ''')
- self.assertEqual(ast['func'].args.fromlineno, 2)
- self.assertFalse(ast['func'].args.is_statement)
- xlambda = ast['x'].infer().next()
- self.assertEqual(xlambda.args.fromlineno, 4)
- self.assertEqual(xlambda.args.tolineno, 4)
- self.assertFalse(xlambda.args.is_statement)
- if sys.version_info < (3, 0):
- self.assertEqual(ast['func'].args.tolineno, 3)
- else:
- self.skipTest('FIXME http://bugs.python.org/issue10445 '
- '(no line number on function args)')
-
-
-class SliceNodeTC(testlib.TestCase):
- def test(self):
- for code in ('a[0]', 'a[1:3]', 'a[:-1:step]', 'a[:,newaxis]',
- 'a[newaxis,:]', 'del L[::2]', 'del A[1]', 'del Br[:]'):
- ast = abuilder.string_build(code).body[0]
- self.assertEqual(ast.as_string(), code)
-
- def test_slice_and_subscripts(self):
- code = """a[:1] = bord[2:]
-a[:1] = bord[2:]
-del bree[3:d]
-bord[2:]
-del av[d::f], a[df:]
-a[:1] = bord[2:]
-del SRC[::1,newaxis,1:]
-tous[vals] = 1010
-del thousand[key]
-del a[::2], a[:-1:step]
-del Fee.form[left:]
-aout.vals = miles.of_stuff
-del (ccok, (name.thing, foo.attrib.value)), Fee.form[left:]
-if all[1] == bord[0:]:
- pass\n\n"""
- ast = abuilder.string_build(code)
- self.assertEqual(ast.as_string(), code)
-
-class EllipsisNodeTC(testlib.TestCase):
- def test(self):
- ast = abuilder.string_build('a[...]').body[0]
- self.assertEqual(ast.as_string(), 'a[...]')
-
-if __name__ == '__main__':
- testlib.unittest_main()
diff -Nru astroid-1.0.1/test/unittest_python3.py astroid-1.3.8/test/unittest_python3.py
--- astroid-1.0.1/test/unittest_python3.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/unittest_python3.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,43 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-import sys
-
-from logilab.common.testlib import TestCase, unittest_main, require_version
-
-from astroid.node_classes import Assign
-from astroid.manager import AstroidManager
-from astroid.builder import AstroidBuilder
-
-
-class Python3TC(TestCase):
- def setUp(self):
- self.manager = AstroidManager()
- self.builder = AstroidBuilder(self.manager)
- self.manager.astroid_cache.clear()
-
- @require_version('3.0')
- def test_starred_notation(self):
- astroid = self.builder.string_build("*a, b = [1, 2, 3]", 'test', 'test')
-
- # Get the star node
- node = next(next(next(astroid.get_children()).get_children()).get_children())
-
- self.assertTrue(isinstance(node.ass_type(), Assign))
-
-if __name__ == '__main__':
- unittest_main()
diff -Nru astroid-1.0.1/test/unittest_regrtest.py astroid-1.3.8/test/unittest_regrtest.py
--- astroid-1.0.1/test/unittest_regrtest.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/unittest_regrtest.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,143 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-
-from logilab.common.testlib import unittest_main, TestCase
-
-from astroid import ResolveError, MANAGER, Instance, nodes, YES, InferenceError
-from astroid.builder import AstroidBuilder
-from astroid.raw_building import build_module
-from astroid.manager import AstroidManager
-
-import sys
-from os.path import join, abspath, dirname
-
-class NonRegressionTC(TestCase):
-
- def setUp(self):
- sys.path.insert(0, join(dirname(abspath(__file__)), 'regrtest_data'))
-
- def tearDown(self):
- sys.path.pop(0)
-
- def brainless_manager(self):
- manager = AstroidManager()
- # avoid caching into the AstroidManager borg since we get problems
- # with other tests :
- manager.__dict__ = {}
- manager.astroid_cache = {}
- manager._mod_file_cache = {}
- manager.transforms = {}
- return manager
-
- def test_module_path(self):
- man = self.brainless_manager()
- mod = man.ast_from_module_name('package.import_package_subpackage_module')
- package = mod.igetattr('package').next()
- self.assertEqual(package.name, 'package')
- subpackage = package.igetattr('subpackage').next()
- self.assertIsInstance(subpackage, nodes.Module)
- self.assertTrue(subpackage.package)
- self.assertEqual(subpackage.name, 'package.subpackage')
- module = subpackage.igetattr('module').next()
- self.assertEqual(module.name, 'package.subpackage.module')
-
-
- def test_package_sidepackage(self):
- manager = self.brainless_manager()
- assert 'package.sidepackage' not in MANAGER.astroid_cache
- package = manager.ast_from_module_name('absimp')
- self.assertIsInstance(package, nodes.Module)
- self.assertTrue(package.package)
- subpackage = package.getattr('sidepackage')[0].infer().next()
- self.assertIsInstance(subpackage, nodes.Module)
- self.assertTrue(subpackage.package)
- self.assertEqual(subpackage.name, 'absimp.sidepackage')
-
-
- def test_living_property(self):
- builder = AstroidBuilder()
- builder._done = {}
- builder._module = sys.modules[__name__]
- builder.object_build(build_module('module_name', ''), Whatever)
-
-
- def test_new_style_class_detection(self):
- try:
- import pygtk
- except ImportError:
- self.skipTest('test skipped: pygtk is not available')
- # XXX may fail on some pygtk version, because objects in
- # gobject._gobject have __module__ set to gobject :(
- builder = AstroidBuilder()
- data = """
-import pygtk
-pygtk.require("2.6")
-import gobject
-
-class A(gobject.GObject):
- pass
-"""
- astroid = builder.string_build(data, __name__, __file__)
- a = astroid['A']
- self.assertTrue(a.newstyle)
-
-
- def test_pylint_config_attr(self):
- try:
- from pylint import lint
- except ImportError:
- self.skipTest('pylint not available')
- mod = MANAGER.ast_from_module_name('pylint.lint')
- pylinter = mod['PyLinter']
- expect = ['OptionsManagerMixIn', 'object', 'MessagesHandlerMixIn',
- 'ReportsHandlerMixIn', 'BaseTokenChecker', 'BaseChecker',
- 'OptionsProviderMixIn', 'ASTWalker']
- self.assertListEqual([c.name for c in pylinter.ancestors()],
- expect)
- self.assertTrue(list(Instance(pylinter).getattr('config')))
- infered = list(Instance(pylinter).igetattr('config'))
- self.assertEqual(len(infered), 1)
- self.assertEqual(infered[0].root().name, 'optparse')
- self.assertEqual(infered[0].name, 'Values')
-
- def test_numpy_crash(self):
- """test don't crash on numpy"""
- #a crash occured somewhere in the past, and an
- # InferenceError instead of a crash was better, but now we even infer!
- try:
- import numpy
- except ImportError:
- self.skipTest('test skipped: numpy is not available')
- builder = AstroidBuilder()
- data = """
-from numpy import multiply
-
-multiply(1, 2, 3)
-"""
- astroid = builder.string_build(data, __name__, __file__)
- callfunc = astroid.body[1].value.func
- infered = callfunc.infered()
- self.assertEqual(len(infered), 1)
- self.assertIsInstance(infered[0], Instance)
-
-
-class Whatever(object):
- a = property(lambda x: x, lambda x: x)
-
-if __name__ == '__main__':
- unittest_main()
diff -Nru astroid-1.0.1/test/unittest_scoped_nodes.py astroid-1.3.8/test/unittest_scoped_nodes.py
--- astroid-1.0.1/test/unittest_scoped_nodes.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/unittest_scoped_nodes.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,669 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""tests for specific behaviour of astroid scoped nodes (i.e. module, class and
-function)
-"""
-
-import sys
-from os.path import join, abspath, dirname
-
-from logilab.common.testlib import TestCase, unittest_main
-
-from astroid import builder, nodes, scoped_nodes, \
- InferenceError, NotFoundError, NoDefault
-from astroid.bases import BUILTINS, Instance, BoundMethod, UnboundMethod
-from astroid.test_utils import extract_node
-
-abuilder = builder.AstroidBuilder()
-DATA = join(dirname(abspath(__file__)), 'data')
-REGRTEST_DATA = join(dirname(abspath(__file__)), 'regrtest_data')
-MODULE = abuilder.file_build(join(DATA, 'module.py'), 'data.module')
-MODULE2 = abuilder.file_build(join(DATA, 'module2.py'), 'data.module2')
-NONREGR = abuilder.file_build(join(DATA, 'nonregr.py'), 'data.nonregr')
-
-PACK = abuilder.file_build(join(DATA, '__init__.py'), 'data')
-
-def _test_dict_interface(self, node, test_attr):
- self.assertIs(node[test_attr], node[test_attr])
- self.assertIn(test_attr, node)
- node.keys()
- node.values()
- node.items()
- iter(node)
-
-
-class ModuleNodeTC(TestCase):
-
- def test_special_attributes(self):
- self.assertEqual(len(MODULE.getattr('__name__')), 1)
- self.assertIsInstance(MODULE.getattr('__name__')[0], nodes.Const)
- self.assertEqual(MODULE.getattr('__name__')[0].value, 'data.module')
- self.assertEqual(len(MODULE.getattr('__doc__')), 1)
- self.assertIsInstance(MODULE.getattr('__doc__')[0], nodes.Const)
- self.assertEqual(MODULE.getattr('__doc__')[0].value, 'test module for astroid\n')
- self.assertEqual(len(MODULE.getattr('__file__')), 1)
- self.assertIsInstance(MODULE.getattr('__file__')[0], nodes.Const)
- self.assertEqual(MODULE.getattr('__file__')[0].value, join(DATA, 'module.py'))
- self.assertEqual(len(MODULE.getattr('__dict__')), 1)
- self.assertIsInstance(MODULE.getattr('__dict__')[0], nodes.Dict)
- self.assertRaises(NotFoundError, MODULE.getattr, '__path__')
- self.assertEqual(len(PACK.getattr('__path__')), 1)
- self.assertIsInstance(PACK.getattr('__path__')[0], nodes.List)
-
- def test_dict_interface(self):
- _test_dict_interface(self, MODULE, 'YO')
-
- def test_getattr(self):
- yo = MODULE.getattr('YO')[0]
- self.assertIsInstance(yo, nodes.Class)
- self.assertEqual(yo.name, 'YO')
- red = MODULE.igetattr('redirect').next()
- self.assertIsInstance(red, nodes.Function)
- self.assertEqual(red.name, 'four_args')
- spawn = MODULE.igetattr('spawn').next()
- self.assertIsInstance(spawn, nodes.Class)
- self.assertEqual(spawn.name, 'Execute')
- # resolve packageredirection
- sys.path.insert(1, DATA)
- mod = abuilder.file_build(join(DATA, 'appl/myConnection.py'),
- 'appl.myConnection')
- try:
- ssl = mod.igetattr('SSL1').next()
- cnx = ssl.igetattr('Connection').next()
- self.assertEqual(cnx.__class__, nodes.Class)
- self.assertEqual(cnx.name, 'Connection')
- self.assertEqual(cnx.root().name, 'SSL1.Connection1')
- finally:
- del sys.path[1]
- self.assertEqual(len(NONREGR.getattr('enumerate')), 2)
- # raise ResolveError
- self.assertRaises(InferenceError, MODULE.igetattr, 'YOAA')
-
- def test_wildard_import_names(self):
- m = abuilder.file_build(join(DATA, 'all.py'), 'all')
- self.assertEqual(m.wildcard_import_names(), ['Aaa', '_bla', 'name'])
- m = abuilder.file_build(join(DATA, 'notall.py'), 'notall')
- res = sorted(m.wildcard_import_names())
- self.assertEqual(res, ['Aaa', 'func', 'name', 'other'])
-
- def test_module_getattr(self):
- data = '''
-appli = application
-appli += 2
-del appli
- '''
- astroid = abuilder.string_build(data, __name__, __file__)
- # test del statement not returned by getattr
- self.assertEqual(len(astroid.getattr('appli')), 2,
- astroid.getattr('appli'))
-
- def test_relative_to_absolute_name(self):
- # package
- mod = nodes.Module('very.multi.package', 'doc')
- mod.package = True
- modname = mod.relative_to_absolute_name('utils', 1)
- self.assertEqual(modname, 'very.multi.package.utils')
- modname = mod.relative_to_absolute_name('utils', 2)
- self.assertEqual(modname, 'very.multi.utils')
- modname = mod.relative_to_absolute_name('utils', 0)
- self.assertEqual(modname, 'very.multi.package.utils')
- modname = mod.relative_to_absolute_name('', 1)
- self.assertEqual(modname, 'very.multi.package')
- # non package
- mod = nodes.Module('very.multi.module', 'doc')
- mod.package = False
- modname = mod.relative_to_absolute_name('utils', 0)
- self.assertEqual(modname, 'very.multi.utils')
- modname = mod.relative_to_absolute_name('utils', 1)
- self.assertEqual(modname, 'very.multi.utils')
- modname = mod.relative_to_absolute_name('utils', 2)
- self.assertEqual(modname, 'very.utils')
- modname = mod.relative_to_absolute_name('', 1)
- self.assertEqual(modname, 'very.multi')
-
- def test_import_1(self):
- data = '''from . import subpackage'''
- astroid = abuilder.string_build(data, 'package', join(REGRTEST_DATA, 'package', '__init__.py'))
- sys.path.insert(1, REGRTEST_DATA)
- try:
- m = astroid.import_module('', level=1)
- self.assertEqual(m.name, 'package')
- infered = list(astroid.igetattr('subpackage'))
- self.assertEqual(len(infered), 1)
- self.assertEqual(infered[0].name, 'package.subpackage')
- finally:
- del sys.path[1]
-
-
- def test_import_2(self):
- data = '''from . import subpackage as pouet'''
- astroid = abuilder.string_build(data, 'package', join(dirname(abspath(__file__)), 'regrtest_data', 'package', '__init__.py'))
- sys.path.insert(1, REGRTEST_DATA)
- try:
- m = astroid.import_module('', level=1)
- self.assertEqual(m.name, 'package')
- infered = list(astroid.igetattr('pouet'))
- self.assertEqual(len(infered), 1)
- self.assertEqual(infered[0].name, 'package.subpackage')
- finally:
- del sys.path[1]
-
-
-class FunctionNodeTC(TestCase):
-
- def test_special_attributes(self):
- func = MODULE2['make_class']
- self.assertEqual(len(func.getattr('__name__')), 1)
- self.assertIsInstance(func.getattr('__name__')[0], nodes.Const)
- self.assertEqual(func.getattr('__name__')[0].value, 'make_class')
- self.assertEqual(len(func.getattr('__doc__')), 1)
- self.assertIsInstance(func.getattr('__doc__')[0], nodes.Const)
- self.assertEqual(func.getattr('__doc__')[0].value, 'check base is correctly resolved to Concrete0')
- self.assertEqual(len(MODULE.getattr('__dict__')), 1)
- self.assertIsInstance(MODULE.getattr('__dict__')[0], nodes.Dict)
-
- def test_dict_interface(self):
- _test_dict_interface(self, MODULE['global_access'], 'local')
-
- def test_default_value(self):
- func = MODULE2['make_class']
- self.assertIsInstance(func.args.default_value('base'), nodes.Getattr)
- self.assertRaises(NoDefault, func.args.default_value, 'args')
- self.assertRaises(NoDefault, func.args.default_value, 'kwargs')
- self.assertRaises(NoDefault, func.args.default_value, 'any')
- #self.assertIsInstance(func.mularg_class('args'), nodes.Tuple)
- #self.assertIsInstance(func.mularg_class('kwargs'), nodes.Dict)
- #self.assertIsNone(func.mularg_class('base'))
-
- def test_navigation(self):
- function = MODULE['global_access']
- self.assertEqual(function.statement(), function)
- l_sibling = function.previous_sibling()
- # check taking parent if child is not a stmt
- self.assertIsInstance(l_sibling, nodes.Assign)
- child = function.args.args[0]
- self.assertIs(l_sibling, child.previous_sibling())
- r_sibling = function.next_sibling()
- self.assertIsInstance(r_sibling, nodes.Class)
- self.assertEqual(r_sibling.name, 'YO')
- self.assertIs(r_sibling, child.next_sibling())
- last = r_sibling.next_sibling().next_sibling().next_sibling()
- self.assertIsInstance(last, nodes.Assign)
- self.assertIsNone(last.next_sibling())
- first = l_sibling.previous_sibling().previous_sibling().previous_sibling().previous_sibling().previous_sibling()
- self.assertIsNone(first.previous_sibling())
-
- def test_nested_args(self):
- if sys.version_info >= (3, 0):
- self.skipTest("nested args has been removed in py3.x")
- code = '''
-def nested_args(a, (b, c, d)):
- "nested arguments test"
- '''
- tree = abuilder.string_build(code)
- func = tree['nested_args']
- self.assertEqual(sorted(func.locals), ['a', 'b', 'c', 'd'])
- self.assertEqual(func.args.format_args(), 'a, (b, c, d)')
-
- def test_four_args(self):
- func = MODULE['four_args']
- #self.assertEqual(func.args.args, ['a', ('b', 'c', 'd')])
- local = sorted(func.keys())
- self.assertEqual(local, ['a', 'b', 'c', 'd'])
- self.assertEqual(func.type, 'function')
-
- def test_format_args(self):
- func = MODULE2['make_class']
- self.assertEqual(func.args.format_args(), 'any, base=data.module.YO, *args, **kwargs')
- func = MODULE['four_args']
- self.assertEqual(func.args.format_args(), 'a, b, c, d')
-
- def test_is_generator(self):
- self.assertTrue(MODULE2['generator'].is_generator())
- self.assertFalse(MODULE2['not_a_generator'].is_generator())
- self.assertFalse(MODULE2['make_class'].is_generator())
-
- def test_is_abstract(self):
- method = MODULE2['AbstractClass']['to_override']
- self.assertTrue(method.is_abstract(pass_is_abstract=False))
- self.assertEqual(method.qname(), 'data.module2.AbstractClass.to_override')
- self.assertEqual(method.pytype(), '%s.instancemethod' % BUILTINS)
- method = MODULE2['AbstractClass']['return_something']
- self.assertFalse(method.is_abstract(pass_is_abstract=False))
- # non regression : test raise "string" doesn't cause an exception in is_abstract
- func = MODULE2['raise_string']
- self.assertFalse(func.is_abstract(pass_is_abstract=False))
-
- def test_is_abstract_decorated(self):
- methods = extract_node("""
- import abc
-
- class Klass(object):
- @abc.abstractproperty
- def prop(self): #@
- pass
-
- @abc.abstractmethod
- def method1(self): #@
- pass
-
- some_other_decorator = lambda x: x
- @some_other_decorator
- def method2(self): #@
- pass
-
- """)
- self.assertTrue(methods[0].is_abstract(pass_is_abstract=False))
- self.assertTrue(methods[1].is_abstract(pass_is_abstract=False))
- self.assertFalse(methods[2].is_abstract(pass_is_abstract=False))
-
-## def test_raises(self):
-## method = MODULE2['AbstractClass']['to_override']
-## self.assertEqual([str(term) for term in method.raises()],
-## ["CallFunc(Name('NotImplementedError'), [], None, None)"] )
-
-## def test_returns(self):
-## method = MODULE2['AbstractClass']['return_something']
-## # use string comp since Node doesn't handle __cmp__
-## self.assertEqual([str(term) for term in method.returns()],
-## ["Const('toto')", "Const(None)"])
-
- def test_lambda_pytype(self):
- data = '''
-def f():
- g = lambda: None
- '''
- astroid = abuilder.string_build(data, __name__, __file__)
- g = list(astroid['f'].ilookup('g'))[0]
- self.assertEqual(g.pytype(), '%s.function' % BUILTINS)
-
- def test_lambda_qname(self):
- astroid = abuilder.string_build('''
-lmbd = lambda: None
-''', __name__, __file__)
- self.assertEqual('%s.' % __name__, astroid['lmbd'].parent.value.qname())
-
- def test_is_method(self):
- data = '''
-class A:
- def meth1(self):
- return 1
- @classmethod
- def meth2(cls):
- return 2
- @staticmethod
- def meth3():
- return 3
-
-def function():
- return 0
-
-@staticmethod
-def sfunction():
- return -1
- '''
- astroid = abuilder.string_build(data, __name__, __file__)
- self.assertTrue(astroid['A']['meth1'].is_method())
- self.assertTrue(astroid['A']['meth2'].is_method())
- self.assertTrue(astroid['A']['meth3'].is_method())
- self.assertFalse(astroid['function'].is_method())
- self.assertFalse(astroid['sfunction'].is_method())
-
- def test_argnames(self):
- if sys.version_info < (3, 0):
- code = 'def f(a, (b, c), *args, **kwargs): pass'
- else:
- code = 'def f(a, b, c, *args, **kwargs): pass'
- astroid = abuilder.string_build(code, __name__, __file__)
- self.assertEqual(astroid['f'].argnames(), ['a', 'b', 'c', 'args', 'kwargs'])
-
- def test_return_nothing(self):
- """test infered value on a function with empty return"""
- data = '''
-def func():
- return
-
-a = func()
-'''
- astroid = abuilder.string_build(data, __name__, __file__)
- call = astroid.body[1].value
- func_vals = call.infered()
- self.assertEqual(len(func_vals), 1)
- self.assertIsInstance(func_vals[0], nodes.Const)
- self.assertIsNone(func_vals[0].value)
-
- def test_func_instance_attr(self):
- """test instance attributes for functions"""
- data= """
-def test():
- print(test.bar)
-
-test.bar = 1
-test()
- """
- astroid = abuilder.string_build(data, 'mod', __file__)
- func = astroid.body[2].value.func.infered()[0]
- self.assertIsInstance(func, nodes.Function)
- self.assertEqual(func.name, 'test')
- one = func.getattr('bar')[0].infered()[0]
- self.assertIsInstance(one, nodes.Const)
- self.assertEqual(one.value, 1)
-
-
-class ClassNodeTC(TestCase):
-
- def test_dict_interface(self):
- _test_dict_interface(self, MODULE['YOUPI'], 'method')
-
- def test_cls_special_attributes_1(self):
- cls = MODULE['YO']
- self.assertEqual(len(cls.getattr('__bases__')), 1)
- self.assertEqual(len(cls.getattr('__name__')), 1)
- self.assertIsInstance(cls.getattr('__name__')[0], nodes.Const)
- self.assertEqual(cls.getattr('__name__')[0].value, 'YO')
- self.assertEqual(len(cls.getattr('__doc__')), 1)
- self.assertIsInstance(cls.getattr('__doc__')[0], nodes.Const)
- self.assertEqual(cls.getattr('__doc__')[0].value, 'hehe')
- self.assertEqual(len(cls.getattr('__module__')), 1)
- self.assertIsInstance(cls.getattr('__module__')[0], nodes.Const)
- self.assertEqual(cls.getattr('__module__')[0].value, 'data.module')
- self.assertEqual(len(cls.getattr('__dict__')), 1)
- self.assertRaises(NotFoundError, cls.getattr, '__mro__')
- for cls in (nodes.List._proxied, nodes.Const(1)._proxied):
- self.assertEqual(len(cls.getattr('__bases__')), 1)
- self.assertEqual(len(cls.getattr('__name__')), 1)
- self.assertEqual(len(cls.getattr('__doc__')), 1, (cls, cls.getattr('__doc__')))
- self.assertEqual(cls.getattr('__doc__')[0].value, cls.doc)
- self.assertEqual(len(cls.getattr('__module__')), 1)
- self.assertEqual(len(cls.getattr('__dict__')), 1)
- self.assertEqual(len(cls.getattr('__mro__')), 1)
-
- def test_cls_special_attributes_2(self):
- astroid = abuilder.string_build('''
-class A: pass
-class B: pass
-
-A.__bases__ += (B,)
-''', __name__, __file__)
- self.assertEqual(len(astroid['A'].getattr('__bases__')), 2)
- self.assertIsInstance(astroid['A'].getattr('__bases__')[0], nodes.Tuple)
- self.assertIsInstance(astroid['A'].getattr('__bases__')[1], nodes.AssAttr)
-
- def test_instance_special_attributes(self):
- for inst in (Instance(MODULE['YO']), nodes.List(), nodes.Const(1)):
- self.assertRaises(NotFoundError, inst.getattr, '__mro__')
- self.assertRaises(NotFoundError, inst.getattr, '__bases__')
- self.assertRaises(NotFoundError, inst.getattr, '__name__')
- self.assertEqual(len(inst.getattr('__dict__')), 1)
- self.assertEqual(len(inst.getattr('__doc__')), 1)
-
- def test_navigation(self):
- klass = MODULE['YO']
- self.assertEqual(klass.statement(), klass)
- l_sibling = klass.previous_sibling()
- self.assertTrue(isinstance(l_sibling, nodes.Function), l_sibling)
- self.assertEqual(l_sibling.name, 'global_access')
- r_sibling = klass.next_sibling()
- self.assertIsInstance(r_sibling, nodes.Class)
- self.assertEqual(r_sibling.name, 'YOUPI')
-
- def test_local_attr_ancestors(self):
- klass2 = MODULE['YOUPI']
- it = klass2.local_attr_ancestors('__init__')
- anc_klass = it.next()
- self.assertIsInstance(anc_klass, nodes.Class)
- self.assertEqual(anc_klass.name, 'YO')
- self.assertRaises(StopIteration, it.next)
- it = klass2.local_attr_ancestors('method')
- self.assertRaises(StopIteration, it.next)
-
- def test_instance_attr_ancestors(self):
- klass2 = MODULE['YOUPI']
- it = klass2.instance_attr_ancestors('yo')
- anc_klass = it.next()
- self.assertIsInstance(anc_klass, nodes.Class)
- self.assertEqual(anc_klass.name, 'YO')
- self.assertRaises(StopIteration, it.next)
- klass2 = MODULE['YOUPI']
- it = klass2.instance_attr_ancestors('member')
- self.assertRaises(StopIteration, it.next)
-
- def test_methods(self):
- klass2 = MODULE['YOUPI']
- methods = sorted([m.name for m in klass2.methods()])
- self.assertEqual(methods, ['__init__', 'class_method',
- 'method', 'static_method'])
- methods = [m.name for m in klass2.mymethods()]
- methods.sort()
- self.assertEqual(methods, ['__init__', 'class_method',
- 'method', 'static_method'])
- klass2 = MODULE2['Specialization']
- methods = [m.name for m in klass2.mymethods()]
- methods.sort()
- self.assertEqual(methods, [])
- method_locals = klass2.local_attr('method')
- self.assertEqual(len(method_locals), 1)
- self.assertEqual(method_locals[0].name, 'method')
- self.assertRaises(NotFoundError, klass2.local_attr, 'nonexistant')
- methods = [m.name for m in klass2.methods()]
- methods.sort()
- self.assertEqual(methods, ['__init__', 'class_method',
- 'method', 'static_method'])
-
- #def test_rhs(self):
- # my_dict = MODULE['MY_DICT']
- # self.assertIsInstance(my_dict.rhs(), nodes.Dict)
- # a = MODULE['YO']['a']
- # value = a.rhs()
- # self.assertIsInstance(value, nodes.Const)
- # self.assertEqual(value.value, 1)
-
- def test_ancestors(self):
- klass = MODULE['YOUPI']
- ancs = [a.name for a in klass.ancestors()]
- self.assertEqual(ancs, ['YO'])
- klass = MODULE2['Specialization']
- ancs = [a.name for a in klass.ancestors()]
- self.assertEqual(ancs, ['YOUPI', 'YO'])
-
- def test_type(self):
- klass = MODULE['YOUPI']
- self.assertEqual(klass.type, 'class')
- klass = MODULE2['Metaclass']
- self.assertEqual(klass.type, 'metaclass')
- klass = MODULE2['MyException']
- self.assertEqual(klass.type, 'exception')
- klass = MODULE2['MyIFace']
- self.assertEqual(klass.type, 'interface')
- klass = MODULE2['MyError']
- self.assertEqual(klass.type, 'exception')
-
- def test_interfaces(self):
- for klass, interfaces in (('Concrete0', ['MyIFace']),
- ('Concrete1', ['MyIFace', 'AnotherIFace']),
- ('Concrete2', ['MyIFace', 'AnotherIFace']),
- ('Concrete23', ['MyIFace', 'AnotherIFace'])):
- klass = MODULE2[klass]
- self.assertEqual([i.name for i in klass.interfaces()],
- interfaces)
-
- def test_concat_interfaces(self):
- astroid = abuilder.string_build('''
-class IMachin: pass
-
-class Correct2:
- """docstring"""
- __implements__ = (IMachin,)
-
-class BadArgument:
- """docstring"""
- __implements__ = (IMachin,)
-
-class InterfaceCanNowBeFound:
- """docstring"""
- __implements__ = BadArgument.__implements__ + Correct2.__implements__
-
- ''')
- self.assertEqual([i.name for i in astroid['InterfaceCanNowBeFound'].interfaces()],
- ['IMachin'])
-
- def test_inner_classes(self):
- eee = NONREGR['Ccc']['Eee']
- self.assertEqual([n.name for n in eee.ancestors()], ['Ddd', 'Aaa', 'object'])
-
-
- def test_classmethod_attributes(self):
- data = '''
-class WebAppObject(object):
- def registered(cls, application):
- cls.appli = application
- cls.schema = application.schema
- cls.config = application.config
- return cls
- registered = classmethod(registered)
- '''
- astroid = abuilder.string_build(data, __name__, __file__)
- cls = astroid['WebAppObject']
- self.assertEqual(sorted(cls.locals.keys()),
- ['appli', 'config', 'registered', 'schema'])
-
-
- def test_class_getattr(self):
- data = '''
-class WebAppObject(object):
- appli = application
- appli += 2
- del self.appli
- '''
- astroid = abuilder.string_build(data, __name__, __file__)
- cls = astroid['WebAppObject']
- # test del statement not returned by getattr
- self.assertEqual(len(cls.getattr('appli')), 2)
-
-
- def test_instance_getattr(self):
- data = '''
-class WebAppObject(object):
- def __init__(self, application):
- self.appli = application
- self.appli += 2
- del self.appli
- '''
- astroid = abuilder.string_build(data, __name__, __file__)
- inst = Instance(astroid['WebAppObject'])
- # test del statement not returned by getattr
- self.assertEqual(len(inst.getattr('appli')), 2)
-
-
- def test_instance_getattr_with_class_attr(self):
- data = '''
-class Parent:
- aa = 1
- cc = 1
-
-class Klass(Parent):
- aa = 0
- bb = 0
-
- def incr(self, val):
- self.cc = self.aa
- if val > self.aa:
- val = self.aa
- if val < self.bb:
- val = self.bb
- self.aa += val
- '''
- astroid = abuilder.string_build(data, __name__, __file__)
- inst = Instance(astroid['Klass'])
- self.assertEqual(len(inst.getattr('aa')), 3, inst.getattr('aa'))
- self.assertEqual(len(inst.getattr('bb')), 1, inst.getattr('bb'))
- self.assertEqual(len(inst.getattr('cc')), 2, inst.getattr('cc'))
-
-
- def test_getattr_method_transform(self):
- data = '''
-class Clazz(object):
-
- def m1(self, value):
- self.value = value
- m2 = m1
-
-def func(arg1, arg2):
- "function that will be used as a method"
- return arg1.value + arg2
-
-Clazz.m3 = func
-inst = Clazz()
-inst.m4 = func
- '''
- astroid = abuilder.string_build(data, __name__, __file__)
- cls = astroid['Clazz']
- # test del statement not returned by getattr
- for method in ('m1', 'm2', 'm3'):
- inferred = list(cls.igetattr(method))
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], UnboundMethod)
- inferred = list(Instance(cls).igetattr(method))
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], BoundMethod)
- inferred = list(Instance(cls).igetattr('m4'))
- self.assertEqual(len(inferred), 1)
- self.assertIsInstance(inferred[0], nodes.Function)
-
- def test_getattr_from_grandpa(self):
- data = '''
-class Future:
- attr = 1
-
-class Present(Future):
- pass
-
-class Past(Present):
- pass
-'''
- astroid = abuilder.string_build(data)
- past = astroid['Past']
- attr = past.getattr('attr')
- self.assertEqual(len(attr), 1)
- attr1 = attr[0]
- self.assertIsInstance(attr1, nodes.AssName)
- self.assertEqual(attr1.name, 'attr')
-
- def test_function_with_decorator_lineno(self):
- data = '''
-@f(a=2,
- b=3)
-def g1(x):
- print(x)
-
-@f(a=2,
- b=3)
-def g2():
- pass
-'''
- astroid = abuilder.string_build(data)
- self.assertEqual(astroid['g1'].fromlineno, 4)
- self.assertEqual(astroid['g1'].tolineno, 5)
- self.assertEqual(astroid['g2'].fromlineno, 9)
- self.assertEqual(astroid['g2'].tolineno, 10)
-
-
-__all__ = ('ModuleNodeTC', 'ImportNodeTC', 'FunctionNodeTC', 'ClassNodeTC')
-
-if __name__ == '__main__':
- unittest_main()
diff -Nru astroid-1.0.1/test/unittest_utils.py astroid-1.3.8/test/unittest_utils.py
--- astroid-1.0.1/test/unittest_utils.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test/unittest_utils.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,102 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-from logilab.common.testlib import TestCase, unittest_main
-
-from astroid import builder, nodes
-from astroid.node_classes import are_exclusive
-
-builder = builder.AstroidBuilder()
-
-class AreExclusiveTC(TestCase):
- def test_not_exclusive(self):
- astroid = builder.string_build("""
-x = 10
-for x in range(5):
- print (x)
-
-if x > 0:
- print ('#' * x)
- """, __name__, __file__)
- xass1 = astroid.locals['x'][0]
- assert xass1.lineno == 2
- xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'x']
- assert len(xnames) == 3
- assert xnames[1].lineno == 6
- self.assertEqual(are_exclusive(xass1, xnames[1]), False)
- self.assertEqual(are_exclusive(xass1, xnames[2]), False)
-
- def test_if(self):
- astroid = builder.string_build('''
-
-if 1:
- a = 1
- a = 2
-elif 2:
- a = 12
- a = 13
-else:
- a = 3
- a = 4
- ''')
- a1 = astroid.locals['a'][0]
- a2 = astroid.locals['a'][1]
- a3 = astroid.locals['a'][2]
- a4 = astroid.locals['a'][3]
- a5 = astroid.locals['a'][4]
- a6 = astroid.locals['a'][5]
- self.assertEqual(are_exclusive(a1, a2), False)
- self.assertEqual(are_exclusive(a1, a3), True)
- self.assertEqual(are_exclusive(a1, a5), True)
- self.assertEqual(are_exclusive(a3, a5), True)
- self.assertEqual(are_exclusive(a3, a4), False)
- self.assertEqual(are_exclusive(a5, a6), False)
-
- def test_try_except(self):
- astroid = 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 = astroid.locals['exclusive_func2'][0]
- f2 = astroid.locals['exclusive_func2'][1]
- f3 = astroid.locals['exclusive_func2'][2]
- f4 = astroid.locals['exclusive_func2'][3]
- self.assertEqual(are_exclusive(f1, f2), True)
- self.assertEqual(are_exclusive(f1, f3), True)
- self.assertEqual(are_exclusive(f1, f4), False)
- self.assertEqual(are_exclusive(f2, f4), True)
- self.assertEqual(are_exclusive(f3, f4), True)
- self.assertEqual(are_exclusive(f3, f2), True)
-
- self.assertEqual(are_exclusive(f2, f1), True)
- self.assertEqual(are_exclusive(f4, f1), False)
- self.assertEqual(are_exclusive(f4, f2), True)
-
-if __name__ == '__main__':
- unittest_main()
-
diff -Nru astroid-1.0.1/test_utils.py astroid-1.3.8/test_utils.py
--- astroid-1.0.1/test_utils.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/test_utils.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,183 +0,0 @@
-"""Utility functions for test code that uses astroid ASTs as input."""
-import textwrap
-
-from astroid import nodes
-from astroid import builder
-
-# The name of the transient function that is used to
-# wrap expressions to be extracted when calling
-# extract_node.
-_TRANSIENT_FUNCTION = '__'
-
-# The comment used to select a statement to be extracted
-# when calling extract_node.
-_STATEMENT_SELECTOR = '#@'
-
-
-def _extract_expressions(node):
- """Find expressions in a call to _TRANSIENT_FUNCTION and extract them.
-
- The function walks the AST recursively to search for expressions that
- are wrapped into a call to _TRANSIENT_FUNCTION. If it finds such an
- expression, it completely removes the function call node from the tree,
- replacing it by the wrapped expression inside the parent.
-
- :param node: An astroid node.
- :type node: astroid.bases.NodeNG
- :yields: The sequence of wrapped expressions on the modified tree
- expression can be found.
- """
- if (isinstance(node, nodes.CallFunc)
- and isinstance(node.func, nodes.Name)
- and node.func.name == _TRANSIENT_FUNCTION):
- real_expr = node.args[0]
- real_expr.parent = node.parent
- # Search for node in all _astng_fields (the fields checked when
- # get_children is called) of its parent. Some of those fields may
- # be lists or tuples, in which case the elements need to be checked.
- # When we find it, replace it by real_expr, so that the AST looks
- # like no call to _TRANSIENT_FUNCTION ever took place.
- for name in node.parent._astng_fields:
- child = getattr(node.parent, name)
- if isinstance(child, (list, tuple)):
- for idx, compound_child in enumerate(child):
- if compound_child is node:
- child[idx] = real_expr
- elif child is node:
- setattr(node.parent, name, real_expr)
- yield real_expr
- else:
- for child in node.get_children():
- for result in _extract_expressions(child):
- yield result
-
-
-def _find_statement_by_line(node, line):
- """Extracts the statement on a specific line from an AST.
-
- If the line number of node matches line, it will be returned;
- otherwise its children are iterated and the function is called
- recursively.
-
- :param node: An astroid node.
- :type node: astroid.bases.NodeNG
- :param line: The line number of the statement to extract.
- :type line: int
- :returns: The statement on the line, or None if no statement for the line
- can be found.
- :rtype: astroid.bases.NodeNG or None
- """
- if isinstance(node, (nodes.Class, nodes.Function)):
- # This is an inaccuracy in the AST: the nodes that can be
- # decorated do not carry explicit information on which line
- # the actual definition (class/def), but .fromline seems to
- # be close enough.
- node_line = node.fromlineno
- else:
- node_line = node.lineno
-
- if node_line == line:
- return node
-
- for child in node.get_children():
- result = _find_statement_by_line(child, line)
- if result:
- return result
-
- return None
-
-def extract_node(code, module_name=''):
- """Parses some Python code as a module and extracts a designated AST node.
-
- Statements:
- To extract one or more statement nodes, append #@ to the end of the line
-
- Examples:
- >>> def x():
- >>> def y():
- >>> return 1 #@
-
- The return statement will be extracted.
-
- >>> class X(object):
- >>> def meth(self): #@
- >>> pass
-
- The funcion object 'meth' will be extracted.
-
- Expressions:
- To extract arbitrary expressions, surround them with the fake
- function call __(...). After parsing, the surrounded expression
- will be returned and the whole AST (accessible via the returned
- node's parent attribute) will look like the function call was
- never there in the first place.
-
- Examples:
- >>> a = __(1)
-
- The const node will be extracted.
-
- >>> def x(d=__(foo.bar)): pass
-
- The node containing the default argument will be extracted.
-
- >>> def foo(a, b):
- >>> return 0 < __(len(a)) < b
-
- The node containing the function call 'len' will be extracted.
-
- If no statements or expressions are selected, the last toplevel
- statement will be returned.
-
- If the selected statement is a discard statement, (i.e. an expression
- turned into a statement), the wrapped expression is returned instead.
-
- For convenience, singleton lists are unpacked.
-
- :param str code: A piece of Python code that is parsed as
- a module. Will be passed through textwrap.dedent first.
- :param str module_name: The name of the module.
- :returns: The designated node from the parse tree, or a list of nodes.
- :rtype: astroid.bases.NodeNG, or a list of nodes.
- """
- def _extract(node):
- if isinstance(node, nodes.Discard):
- return node.value
- else:
- return node
-
- requested_lines = []
- for idx, line in enumerate(code.splitlines()):
- if line.strip().endswith(_STATEMENT_SELECTOR):
- requested_lines.append(idx + 1)
-
- tree = build_module(code, module_name=module_name)
- extracted = []
- if requested_lines:
- for line in requested_lines:
- extracted.append(_find_statement_by_line(tree, line))
- else:
- # Modifies the tree.
- extracted = list(_extract_expressions(tree))
-
- if not extracted:
- extracted.append(tree.body[-1])
-
- extracted = [_extract(node) for node in extracted]
- if len(extracted) == 1:
- return extracted[0]
- else:
- return extracted
-
-
-def build_module(code, module_name=''):
- """Parses a string module with a builder.
- :param code: The code for the module.
- :type code: str
- :param module_name: The name for the module
- :type module_name: str
- :returns: The module AST.
- :rtype: astroid.bases.NodeNG
- """
- code = textwrap.dedent(code)
- return builder.AstroidBuilder(None).string_build(code, modname=module_name)
diff -Nru astroid-1.0.1/tox.ini astroid-1.3.8/tox.ini
--- astroid-1.0.1/tox.ini 1970-01-01 00:00:00.000000000 +0000
+++ astroid-1.3.8/tox.ini 2015-08-02 19:35:46.000000000 +0000
@@ -0,0 +1,19 @@
+[tox]
+# official list is
+#envlist = py27, py33, py34
+envlist = py27, py33, pylint
+
+[testenv:pylint]
+deps =
+ logilab-common
+ six
+ hg+https://bitbucket.org/logilab/astroid
+ pylint==1.4.3
+commands = pylint -rn --rcfile={toxinidir}/pylintrc {envsitepackagesdir}/astroid
+
+[testenv]
+deps =
+ logilab-common
+ six
+
+commands = python -m unittest discover -s {envsitepackagesdir}/astroid/tests -p "unittest*.py"
diff -Nru astroid-1.0.1/utils.py astroid-1.3.8/utils.py
--- astroid-1.0.1/utils.py 2013-07-29 15:04:25.000000000 +0000
+++ astroid-1.3.8/utils.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,236 +0,0 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of astroid.
-#
-# astroid is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# astroid is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with astroid. If not, see .
-"""this module contains some utilities to navigate in the tree or to
-extract information from it
-"""
-
-__docformat__ = "restructuredtext en"
-
-from astroid.exceptions import AstroidBuildingException
-from astroid.builder import parse
-
-
-class ASTWalker:
- """a walker visiting a tree in preorder, calling on the handler:
-
- * visit_ on entering a node, where class name is the class of
- the node in lower case
-
- * leave_ on leaving a node, where class name is the class of
- the node in lower case
- """
-
- def __init__(self, handler):
- self.handler = handler
- self._cache = {}
-
- def walk(self, node, _done=None):
- """walk on the tree from , getting callbacks from handler"""
- if _done is None:
- _done = set()
- if node in _done:
- raise AssertionError((id(node), node, node.parent))
- _done.add(node)
- self.visit(node)
- for child_node in node.get_children():
- self.handler.set_context(node, child_node)
- assert child_node is not node
- self.walk(child_node, _done)
- self.leave(node)
- assert node.parent is not node
-
- def get_callbacks(self, node):
- """get callbacks from handler for the visited node"""
- klass = node.__class__
- methods = self._cache.get(klass)
- if methods is None:
- handler = self.handler
- kid = klass.__name__.lower()
- e_method = getattr(handler, 'visit_%s' % kid,
- getattr(handler, 'visit_default', None))
- l_method = getattr(handler, 'leave_%s' % kid,
- getattr(handler, 'leave_default', None))
- self._cache[klass] = (e_method, l_method)
- else:
- e_method, l_method = methods
- return e_method, l_method
-
- def visit(self, node):
- """walk on the tree from , getting callbacks from handler"""
- method = self.get_callbacks(node)[0]
- if method is not None:
- method(node)
-
- def leave(self, node):
- """walk on the tree from , getting callbacks from handler"""
- method = self.get_callbacks(node)[1]
- if method is not None:
- method(node)
-
-
-class LocalsVisitor(ASTWalker):
- """visit a project by traversing the locals dictionary"""
- def __init__(self):
- ASTWalker.__init__(self, self)
- self._visited = {}
-
- def visit(self, node):
- """launch the visit starting from the given node"""
- if node in self._visited:
- return
- self._visited[node] = 1 # FIXME: use set ?
- methods = self.get_callbacks(node)
- if methods[0] is not None:
- methods[0](node)
- if 'locals' in node.__dict__: # skip Instance and other proxy
- for name, local_node in node.items():
- self.visit(local_node)
- if methods[1] is not None:
- return methods[1](node)
-
-
-def _check_children(node):
- """a helper function to check children - parent relations"""
- for child in node.get_children():
- ok = False
- if child is None:
- print "Hm, child of %s is None" % node
- continue
- if not hasattr(child, 'parent'):
- print " ERROR: %s has child %s %x with no parent" % (node, child, id(child))
- elif not child.parent:
- print " ERROR: %s has child %s %x with parent %r" % (node, child, id(child), child.parent)
- elif child.parent is not node:
- print " ERROR: %s %x has child %s %x with wrong parent %s" % (node,
- id(node), child, id(child), child.parent)
- else:
- ok = True
- if not ok:
- print "lines;", node.lineno, child.lineno
- print "of module", node.root(), node.root().name
- raise AstroidBuildingException
- _check_children(child)
-
-
-class TreeTester(object):
- '''A helper class to see _ast tree and compare with astroid tree
-
- indent: string for tree indent representation
- lineno: bool to tell if we should print the line numbers
-
- >>> tester = TreeTester('print')
- >>> print tester.native_tree_repr()
-
-
- . body = [
- .
- . . nl = True
- . ]
- >>> print tester.astroid_tree_repr()
- Module()
- body = [
- Print()
- dest =
- values = [
- ]
- ]
- '''
-
- indent = '. '
- lineno = False
-
- def __init__(self, sourcecode):
- self._string = ''
- self.sourcecode = sourcecode
- self._ast_node = None
- self.build_ast()
-
- def build_ast(self):
- """build the _ast tree from the source code"""
- self._ast_node = parse(self.sourcecode)
-
- def native_tree_repr(self, node=None, indent=''):
- """get a nice representation of the _ast tree"""
- self._string = ''
- if node is None:
- node = self._ast_node
- self._native_repr_tree(node, indent)
- return self._string
-
-
- def _native_repr_tree(self, node, indent, _done=None):
- """recursive method for the native tree representation"""
- from _ast import Load as _Load, Store as _Store, Del as _Del
- from _ast import AST as Node
- if _done is None:
- _done = set()
- if node in _done:
- self._string += '\nloop in tree: %r (%s)' % (node,
- getattr(node, 'lineno', None))
- return
- _done.add(node)
- self._string += '\n' + indent + '<%s>' % node.__class__.__name__
- indent += self.indent
- if not hasattr(node, '__dict__'):
- self._string += '\n' + self.indent + " ** node has no __dict__ " + str(node)
- return
- node_dict = node.__dict__
- if hasattr(node, '_attributes'):
- for a in node._attributes:
- attr = node_dict[a]
- if attr is None:
- continue
- if a in ("lineno", "col_offset") and not self.lineno:
- continue
- self._string +='\n' + indent + a + " = " + repr(attr)
- for field in node._fields or ():
- attr = node_dict[field]
- if attr is None:
- continue
- if isinstance(attr, list):
- if not attr:
- continue
- self._string += '\n' + indent + field + ' = ['
- for elt in attr:
- self._native_repr_tree(elt, indent, _done)
- self._string += '\n' + indent + ']'
- continue
- if isinstance(attr, (_Load, _Store, _Del)):
- continue
- if isinstance(attr, Node):
- self._string += '\n' + indent + field + " = "
- self._native_repr_tree(attr, indent, _done)
- else:
- self._string += '\n' + indent + field + " = " + repr(attr)
-
-
- def build_astroid_tree(self):
- """build astroid tree from the _ast tree
- """
- from astroid.builder import AstroidBuilder
- tree = AstroidBuilder().string_build(self.sourcecode)
- return tree
-
- def astroid_tree_repr(self, ids=False):
- """build the astroid tree and return a nice tree representation"""
- mod = self.build_astroid_tree()
- return mod.repr_tree(ids)
-
-
-__all__ = ('LocalsVisitor', 'ASTWalker',)
-