astroid-1.4.4/ 0000777 0000000 0000000 00000000000 12646224174 011327 5 ustar 0000000 0000000 astroid-1.4.4/astroid/ 0000777 0000000 0000000 00000000000 12646224174 012774 5 ustar 0000000 0000000 astroid-1.4.4/astroid/arguments.py 0000666 0000000 0000000 00000022444 12646222644 015361 0 ustar 0000000 0000000 # 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 .
from astroid import bases
from astroid import context as contextmod
from astroid import exceptions
from astroid import nodes
from astroid import util
import six
class CallSite(object):
"""Class for understanding arguments passed into a call site
It needs a call context, which contains the arguments and the
keyword arguments that were passed into a given call site.
In order to infer what an argument represents, call
:meth:`infer_argument` with the corresponding function node
and the argument name.
"""
def __init__(self, callcontext):
args = callcontext.args
keywords = callcontext.keywords
self.duplicated_keywords = set()
self._unpacked_args = self._unpack_args(args)
self._unpacked_kwargs = self._unpack_keywords(keywords)
self.positional_arguments = [
arg for arg in self._unpacked_args
if arg is not util.YES
]
self.keyword_arguments = {
key: value for key, value in self._unpacked_kwargs.items()
if value is not util.YES
}
@classmethod
def from_call(cls, call_node):
"""Get a CallSite object from the given Call node."""
callcontext = contextmod.CallContext(call_node.args,
call_node.keywords)
return cls(callcontext)
def has_invalid_arguments(self):
"""Check if in the current CallSite were passed *invalid* arguments
This can mean multiple things. For instance, if an unpacking
of an invalid object was passed, then this method will return True.
Other cases can be when the arguments can't be inferred by astroid,
for example, by passing objects which aren't known statically.
"""
return len(self.positional_arguments) != len(self._unpacked_args)
def has_invalid_keywords(self):
"""Check if in the current CallSite were passed *invalid* keyword arguments
For instance, unpacking a dictionary with integer keys is invalid
(**{1:2}), because the keys must be strings, which will make this
method to return True. Other cases where this might return True if
objects which can't be inferred were passed.
"""
return len(self.keyword_arguments) != len(self._unpacked_kwargs)
def _unpack_keywords(self, keywords):
values = {}
context = contextmod.InferenceContext()
for name, value in keywords:
if name is None:
# Then it's an unpacking operation (**)
try:
inferred = next(value.infer(context=context))
except exceptions.InferenceError:
values[name] = util.YES
continue
if not isinstance(inferred, nodes.Dict):
# Not something we can work with.
values[name] = util.YES
continue
for dict_key, dict_value in inferred.items:
try:
dict_key = next(dict_key.infer(context=context))
except exceptions.InferenceError:
values[name] = util.YES
continue
if not isinstance(dict_key, nodes.Const):
values[name] = util.YES
continue
if not isinstance(dict_key.value, six.string_types):
values[name] = util.YES
continue
if dict_key.value in values:
# The name is already in the dictionary
values[dict_key.value] = util.YES
self.duplicated_keywords.add(dict_key.value)
continue
values[dict_key.value] = dict_value
else:
values[name] = value
return values
@staticmethod
def _unpack_args(args):
values = []
context = contextmod.InferenceContext()
for arg in args:
if isinstance(arg, nodes.Starred):
try:
inferred = next(arg.value.infer(context=context))
except exceptions.InferenceError:
values.append(util.YES)
continue
if inferred is util.YES:
values.append(util.YES)
continue
if not hasattr(inferred, 'elts'):
values.append(util.YES)
continue
values.extend(inferred.elts)
else:
values.append(arg)
return values
def infer_argument(self, funcnode, name, context):
"""infer a function argument value according to the call context"""
if name in self.duplicated_keywords:
raise exceptions.InferenceError(name)
# Look into the keywords first, maybe it's already there.
try:
return self.keyword_arguments[name].infer(context)
except KeyError:
pass
# Too many arguments given and no variable arguments.
if len(self.positional_arguments) > len(funcnode.args.args):
if not funcnode.args.vararg:
raise exceptions.InferenceError(name)
positional = self.positional_arguments[:len(funcnode.args.args)]
vararg = self.positional_arguments[len(funcnode.args.args):]
argindex = funcnode.args.find_argname(name)[0]
kwonlyargs = set(arg.name for arg in funcnode.args.kwonlyargs)
kwargs = {
key: value for key, value in self.keyword_arguments.items()
if key not in kwonlyargs
}
# If there are too few positionals compared to
# what the function expects to receive, check to see
# if the missing positional arguments were passed
# as keyword arguments and if so, place them into the
# positional args list.
if len(positional) < len(funcnode.args.args):
for func_arg in funcnode.args.args:
if func_arg.name in kwargs:
arg = kwargs.pop(func_arg.name)
positional.append(arg)
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, bases.Instance):
boundnode = bases.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.positional_arguments[argindex].infer(context)
except IndexError:
pass
if funcnode.args.kwarg == name:
# It wants all the keywords that were passed into
# the call site.
if self.has_invalid_keywords():
raise exceptions.InferenceError
kwarg = nodes.Dict()
kwarg.lineno = funcnode.args.lineno
kwarg.col_offset = funcnode.args.col_offset
kwarg.parent = funcnode.args
items = [(nodes.const_factory(key), value)
for key, value in kwargs.items()]
kwarg.items = items
return iter((kwarg, ))
elif funcnode.args.vararg == name:
# It wants all the args that were passed into
# the call site.
if self.has_invalid_arguments():
raise exceptions.InferenceError
args = nodes.Tuple()
args.lineno = funcnode.args.lineno
args.col_offset = funcnode.args.col_offset
args.parent = funcnode.args
args.elts = vararg
return iter((args, ))
# Check if it's a default parameter.
try:
return funcnode.args.default_value(name).infer(context)
except exceptions.NoDefault:
pass
raise exceptions.InferenceError(name)
astroid-1.4.4/astroid/astpeephole.py 0000666 0000000 0000000 00000005610 12646222644 015661 0 ustar 0000000 0000000 # 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
astroid-1.4.4/astroid/as_string.py 0000666 0000000 0000000 00000050465 12646222644 015351 0 ustar 0000000 0000000 # 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
import six
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_assignattr(self, node):
"""return an astroid.AssAttr node as string"""
return self.visit_attribute(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_assignname(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_repr(self, node):
"""return an astroid.Repr 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_call(self, node):
"""return an astroid.Call node as string"""
expr_str = node.func.accept(self)
args = [arg.accept(self) for arg in node.args]
if node.keywords:
keywords = [kwarg.accept(self) for kwarg in node.keywords]
else:
keywords = []
args.extend(keywords)
return '%s(%s)' % (expr_str, ', '.join(args))
def visit_classdef(self, node):
"""return an astroid.ClassDef 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_attribute(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(self._visit_dict(node))
def _visit_dict(self, node):
for key, value in node.items:
key = key.accept(self)
value = value.accept(self)
if key == '**':
# It can only be a DictUnpack node.
yield key + value
else:
yield '%s: %s' % (key, value)
def visit_dictunpack(self, node):
return '**'
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_expr(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_importfrom(self, node):
"""return an astroid.ImportFrom node as string"""
return 'from %s import %s' % ('.' * (node.level or 0) + node.modname,
_import_string(node.names))
def visit_functiondef(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_annotation = ''
if six.PY3 and node.returns:
return_annotation = '->' + node.returns.as_string()
trailer = return_annotation + ":"
else:
trailer = ":"
def_format = "\n%sdef %s(%s)%s%s\n%s"
return def_format % (decorate, node.name,
node.args.accept(self),
trailer, docs,
self._stmt_list(node.body))
def visit_generatorexp(self, node):
"""return an astroid.GeneratorExp node as string"""
return '(%s %s)' % (node.elt.accept(self),
' '.join([n.accept(self) for n in node.generators]))
def visit_attribute(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"""
if node.arg is None:
return '**%s' % node.value.accept(self)
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,)
def visit_starred(self, node):
"""return Starred node as string"""
return "*" + node.value.accept(self)
# These aren't for real AST nodes, but for inference objects.
def visit_frozenset(self, node):
return node.parent.accept(self)
def visit_super(self, node):
return node.parent.accept(self)
def visit_yes(self, node):
return "Uninferable"
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_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 visit_asyncfunctiondef(self, node):
function = super(AsStringVisitor3k, self).visit_functiondef(node)
return 'async ' + function.strip()
def visit_await(self, node):
return 'await %s' % node.value.accept(self)
def visit_asyncwith(self, node):
return 'async %s' % self.visit_with(node)
def visit_asyncfor(self, node):
return 'async %s' % self.visit_for(node)
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()
astroid-1.4.4/astroid/bases.py 0000666 0000000 0000000 00000053265 12646222644 014456 0 ustar 0000000 0000000 # 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.
"""
import functools
import sys
import warnings
import wrapt
from astroid import context as contextmod
from astroid import decorators as decoratorsmod
from astroid import exceptions
from astroid import util
if sys.version_info >= (3, 0):
BUILTINS = 'builtins'
else:
BUILTINS = '__builtin__'
PROPERTIES = {BUILTINS + '.property', 'abc.abstractproperty'}
# List of possible property names. We use this list in order
# to see if a method is a property or not. This should be
# pretty reliable and fast, the alternative being to check each
# decorator to see if its a real property-like descriptor, which
# can be too complicated.
# Also, these aren't qualified, because each project can
# define them, we shouldn't expect to know every possible
# property-like decorator!
# TODO(cpopa): just implement descriptors already.
POSSIBLE_PROPERTIES = {"cached_property", "cachedproperty",
"lazyproperty", "lazy_property", "reify",
"lazyattribute", "lazy_attribute",
"LazyProperty", "lazy"}
def _is_property(meth):
if PROPERTIES.intersection(meth.decoratornames()):
return True
stripped = {name.split(".")[-1] for name in meth.decoratornames()
if name is not util.YES}
return any(name in stripped for name in POSSIBLE_PROPERTIES)
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
def _infer_stmts(stmts, context, frame=None):
"""Return an iterator on statements inferred by each statement in *stmts*."""
stmt = None
inferred = False
if context is not None:
name = context.lookupname
context = context.clone()
else:
name = None
context = contextmod.InferenceContext()
for stmt in stmts:
if stmt is util.YES:
yield stmt
inferred = True
continue
context.lookupname = stmt._infer_name(frame, name)
try:
for inferred in stmt.infer(context=context):
yield inferred
inferred = True
except exceptions.UnresolvableName:
continue
except exceptions.InferenceError:
yield util.YES
inferred = True
if not inferred:
raise exceptions.InferenceError(str(stmt))
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 exceptions.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 exceptions.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 exceptions.NotFoundError:
pass
return values
def igetattr(self, name, context=None):
"""inferred getattr"""
if not context:
context = contextmod.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 exceptions.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 exceptions.NotFoundError:
raise exceptions.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 _is_property(attr):
for inferred in attr.infer_call_result(self, context):
yield inferred
else:
yield BoundMethod(attr, self)
elif hasattr(attr, 'name') and attr.name == '':
# This is a lambda function defined at class level,
# since its scope is the underlying _proxied class.
# Unfortunately, we can't do an isinstance check here,
# because of the circular dependency between astroid.bases
# and astroid.scoped_nodes.
if attr.statement().scope() == self._proxied:
if attr.args.args and attr.args.args[0].name == 'self':
yield BoundMethod(attr, self)
continue
yield attr
else:
yield attr
def infer_call_result(self, caller, context=None):
"""infer what a class instance is returning when called"""
inferred = False
for node in self._proxied.igetattr('__call__', context):
if node is util.YES or not node.callable():
continue
for res in node.infer_call_result(caller, context):
inferred = True
yield res
if not inferred:
raise exceptions.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 exceptions.NotFoundError:
return False
def pytype(self):
return self._proxied.qname()
def display_type(self):
return 'Instance of'
# TODO(cpopa): this is set in inference.py
# The circular dependency hell goes deeper and deeper.
# pylint: disable=unused-argument
def getitem(self, index, context=None):
pass
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 self._proxied.getattr(name, context)
def igetattr(self, name, context=None):
if name == 'im_func':
return iter((self._proxied,))
return self._proxied.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 util.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=None):
if context is None:
context = contextmod.InferenceContext()
context = context.clone()
context.boundnode = self.bound
return super(BoundMethod, self).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"""
@functools.wraps(func)
def wrapped(node, context=None, _func=func, **kwargs):
"""wrapper function handling context"""
if context is None:
context = contextmod.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 ares not in yielded:
yield res
yielded.add(ares)
return wrapped
@wrapt.decorator
def yes_if_nothing_inferred(func, instance, args, kwargs):
inferred = False
for node in func(*args, **kwargs):
inferred = True
yield node
if not inferred:
yield util.YES
@wrapt.decorator
def raise_if_nothing_inferred(func, instance, args, kwargs):
inferred = False
for node in func(*args, **kwargs):
inferred = True
yield node
if not inferred:
raise exceptions.InferenceError()
# 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 FunctionDef 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 exceptions.UseInferenceDefault:
pass
if not context:
return self._infer(context, **kwargs)
key = (self, context.lookupname,
context.callcontext, context.boundnode)
if key in context.inferred:
return iter(context.inferred[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 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, FunctionDef or
ClassDef)
"""
return self.parent.frame()
def scope(self):
"""return the first node defining a new scope (i.e. Module,
FunctionDef, ClassDef, 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
msg = 'Could not find %s in %s\'s children'
raise exceptions.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 exceptions.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
@decoratorsmod.cachedproperty
def fromlineno(self):
if self.lineno is None:
return self._fixed_source_line()
else:
return self.lineno
@decoratorsmod.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 ImportFrom, 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 exceptions.InferenceError(self.__class__.__name__)
def inferred(self):
'''return list of inferred values for a more simple inference usage'''
return list(self.infer())
def infered(self):
warnings.warn('%s.infered() is deprecated and slated for removal '
'in astroid 2.0, use %s.inferred() instead.'
% (type(self).__name__, type(self).__name__),
PendingDeprecationWarning, stacklevel=2)
return self.inferred()
def instanciate_class(self):
"""instanciate a node if it is a ClassDef 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]
astroid-1.4.4/astroid/brain/ 0000777 0000000 0000000 00000000000 12646224174 014067 5 ustar 0000000 0000000 astroid-1.4.4/astroid/brain/brain_builtin_inference.py 0000666 0000000 0000000 00000025560 12646222644 021310 0 ustar 0000000 0000000 """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 arguments
from astroid import nodes
from astroid import objects
from astroid.builder import AstroidBuilder
from astroid import util
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:
if not result.parent:
# Let the transformation function determine
# the parent for its result. Otherwise,
# we set it to be the node we transformed from.
result.parent = node
result.lineno = node.lineno
result.col_offset = node.col_offset
return iter([result])
MANAGER.register_transform(nodes.Call,
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:
inferred = next(arg.infer(context=context))
except (InferenceError, StopIteration):
raise UseInferenceDefault()
if inferred is util.YES:
raise UseInferenceDefault()
transformed = transform(inferred)
if not transformed or transformed is util.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)
infer_frozenset = partial(
_infer_builtin,
klass=objects.FrozenSet,
iterables=(nodes.List, nodes.Tuple, nodes.Set),
build_elts=frozenset)
def _get_elts(arg, context):
is_iterable = lambda n: isinstance(n,
(nodes.List, nodes.Tuple, nodes.Set))
try:
inferred = next(arg.infer(context))
except (InferenceError, UnresolvableName):
raise UseInferenceDefault()
if isinstance(inferred, nodes.Dict):
items = inferred.items
elif is_iterable(inferred):
items = []
for elt in inferred.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 inferred, we'll fallback to default inference.
"""
call = arguments.CallSite.from_call(node)
if call.has_invalid_arguments() or call.has_invalid_keywords():
raise UseInferenceDefault
args = call.positional_arguments
kwargs = list(call.keyword_arguments.items())
if not args and not kwargs:
# dict()
return nodes.Dict()
elif kwargs and not args:
# dict(a=1, b=2, c=4)
items = [(nodes.Const(key), value) for key, value in kwargs]
elif len(args) == 1 and kwargs:
# dict(some_iterable, b=2, c=4)
elts = _get_elts(args[0], context)
keys = [(nodes.Const(key), value) for key, value in kwargs]
items = elts + keys
elif len(args) == 1:
items = _get_elts(args[0], context)
else:
raise UseInferenceDefault()
empty = nodes.Dict()
empty.items = items
return empty
def _node_class(node):
klass = node.frame()
while klass is not None and not isinstance(klass, nodes.ClassDef):
if klass.parent is None:
klass = None
else:
klass = klass.parent.frame()
return klass
def infer_super(node, context=None):
"""Understand super calls.
There are some restrictions for what can be understood:
* unbounded super (one argument form) is not understood.
* if the super call is not inside a function (classmethod or method),
then the default inference will be used.
* if the super arguments can't be infered, the default inference
will be used.
"""
if len(node.args) == 1:
# Ignore unbounded super.
raise UseInferenceDefault
scope = node.scope()
if not isinstance(scope, nodes.FunctionDef):
# Ignore non-method uses of super.
raise UseInferenceDefault
if scope.type not in ('classmethod', 'method'):
# Not interested in staticmethods.
raise UseInferenceDefault
cls = _node_class(scope)
if not len(node.args):
mro_pointer = cls
# In we are in a classmethod, the interpreter will fill
# automatically the class as the second argument, not an instance.
if scope.type == 'classmethod':
mro_type = cls
else:
mro_type = cls.instantiate_class()
else:
# TODO(cpopa): support flow control (multiple inference values).
try:
mro_pointer = next(node.args[0].infer(context=context))
except InferenceError:
raise UseInferenceDefault
try:
mro_type = next(node.args[1].infer(context=context))
except InferenceError:
raise UseInferenceDefault
if mro_pointer is YES or mro_type is YES:
# No way we could understand this.
raise UseInferenceDefault
super_obj = objects.Super(mro_pointer=mro_pointer,
mro_type=mro_type,
self_class=cls,
scope=scope)
super_obj.parent = node
return iter([super_obj])
# Builtins inference
MANAGER.register_transform(nodes.Call,
inference_tip(infer_super),
lambda n: (isinstance(n.func, nodes.Name) and
n.func.name == 'super'))
register_builtin_transform(infer_tuple, 'tuple')
register_builtin_transform(infer_set, 'set')
register_builtin_transform(infer_list, 'list')
register_builtin_transform(infer_dict, 'dict')
register_builtin_transform(infer_frozenset, 'frozenset')
astroid-1.4.4/astroid/brain/brain_dateutil.py 0000666 0000000 0000000 00000000700 12640766772 017435 0 ustar 0000000 0000000 """Astroid hooks for dateutil"""
import textwrap
from astroid import MANAGER, register_module_extender
from astroid.builder import AstroidBuilder
def dateutil_transform():
return AstroidBuilder(MANAGER).string_build(textwrap.dedent('''
import datetime
def parse(timestr, parserinfo=None, **kwargs):
return datetime.datetime()
'''))
register_module_extender(MANAGER, 'dateutil.parser', dateutil_transform)
astroid-1.4.4/astroid/brain/brain_gi.py 0000666 0000000 0000000 00000013615 12646222644 016221 0 ustar 0000000 0000000 """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
import warnings
from astroid import MANAGER, AstroidBuildingException, nodes
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 (str(obj).startswith(", )
# Only accept function calls with two constant arguments
if len(node.args) != 2:
return False
if not all(isinstance(arg, nodes.Const) for arg in node.args):
return False
func = node.func
if isinstance(func, nodes.Attribute):
if func.attrname != 'require_version':
return False
if isinstance(func.expr, nodes.Name) and func.expr.name == 'gi':
return True
return False
if isinstance(func, nodes.Name):
return func.name == 'require_version'
return False
def _register_require_version(node):
# Load the gi.require_version locally
try:
import gi
gi.require_version(node.args[0].value, node.args[1].value)
except Exception:
pass
return node
MANAGER.register_failed_import_hook(_import_gi_module)
MANAGER.register_transform(nodes.Call, _register_require_version, _looks_like_require_version)
astroid-1.4.4/astroid/brain/brain_mechanize.py 0000666 0000000 0000000 00000000746 12640766772 017577 0 ustar 0000000 0000000 from astroid import MANAGER, register_module_extender
from astroid.builder import AstroidBuilder
def mechanize_transform():
return AstroidBuilder(MANAGER).string_build('''
class Browser(object):
def open(self, url, data=None, timeout=None):
return None
def open_novisit(self, url, data=None, timeout=None):
return None
def open_local_file(self, filename):
return None
''')
register_module_extender(MANAGER, 'mechanize', mechanize_transform)
astroid-1.4.4/astroid/brain/brain_nose.py 0000666 0000000 0000000 00000005316 12646222644 016565 0 ustar 0000000 0000000 # 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)
if method.name == 'assertEqual':
# nose also exports assert_equals.
yield 'assert_equals', 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')
astroid-1.4.4/astroid/brain/brain_numpy.py 0000666 0000000 0000000 00000004242 12646170047 016765 0 ustar 0000000 0000000 # 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 .
"""Astroid hooks for numpy."""
import astroid
# TODO(cpopa): drop when understanding augmented assignments
def numpy_core_transform():
return astroid.parse('''
from numpy.core import numeric
from numpy.core import fromnumeric
from numpy.core import defchararray
from numpy.core import records
from numpy.core import function_base
from numpy.core import machar
from numpy.core import getlimits
from numpy.core import shape_base
__all__ = (['char', 'rec', 'memmap', 'chararray'] + numeric.__all__ +
fromnumeric.__all__ +
records.__all__ +
function_base.__all__ +
machar.__all__ +
getlimits.__all__ +
shape_base.__all__)
''')
def numpy_transform():
return astroid.parse('''
from numpy import core
from numpy import matrixlib as _mat
from numpy import lib
__all__ = ['add_newdocs',
'ModuleDeprecationWarning',
'VisibleDeprecationWarning', 'linalg', 'fft', 'random',
'ctypeslib', 'ma',
'__version__', 'pkgload', 'PackageLoader',
'show_config'] + core.__all__ + _mat.__all__ + lib.__all__
''')
astroid.register_module_extender(astroid.MANAGER, 'numpy.core', numpy_core_transform)
astroid.register_module_extender(astroid.MANAGER, 'numpy', numpy_transform)
astroid-1.4.4/astroid/brain/brain_pytest.py 0000666 0000000 0000000 00000001614 12640766772 017157 0 ustar 0000000 0000000 """Astroid hooks for pytest."""
from __future__ import absolute_import
from astroid import MANAGER, register_module_extender
from astroid.builder import AstroidBuilder
def pytest_transform():
return AstroidBuilder(MANAGER).string_build('''
try:
import _pytest.mark
import _pytest.recwarn
import _pytest.runner
import _pytest.python
except ImportError:
pass
else:
deprecated_call = _pytest.recwarn.deprecated_call
exit = _pytest.runner.exit
fail = _pytest.runner.fail
fixture = _pytest.python.fixture
importorskip = _pytest.runner.importorskip
mark = _pytest.mark.MarkGenerator()
raises = _pytest.python.raises
skip = _pytest.runner.skip
yield_fixture = _pytest.python.yield_fixture
''')
register_module_extender(MANAGER, 'pytest', pytest_transform)
register_module_extender(MANAGER, 'py.test', pytest_transform)
astroid-1.4.4/astroid/brain/brain_qt.py 0000666 0000000 0000000 00000002373 12646222644 016245 0 ustar 0000000 0000000 """Astroid hooks for the PyQT library."""
from astroid import MANAGER, register_module_extender
from astroid.builder import AstroidBuilder
from astroid import nodes
from astroid import parse
def _looks_like_signal(node, signal_name='pyqtSignal'):
if '__class__' in node._instance_attrs:
cls = node._instance_attrs['__class__'][0]
return cls.name == signal_name
return False
def transform_pyqt_signal(node):
module = parse('''
class pyqtSignal(object):
def connect(self, slot, type=None, no_receiver_check=False):
pass
def disconnect(self, slot):
pass
def emit(self, *args):
pass
''')
signal_cls = module['pyqtSignal']
node._instance_attrs['emit'] = signal_cls['emit']
node._instance_attrs['disconnect'] = signal_cls['disconnect']
node._instance_attrs['connect'] = signal_cls['connect']
def pyqt4_qtcore_transform():
return AstroidBuilder(MANAGER).string_build('''
def SIGNAL(signal_name): pass
class QObject(object):
def emit(self, signal): pass
''')
register_module_extender(MANAGER, 'PyQt4.QtCore', pyqt4_qtcore_transform)
MANAGER.register_transform(nodes.FunctionDef, transform_pyqt_signal,
_looks_like_signal) astroid-1.4.4/astroid/brain/brain_six.py 0000666 0000000 0000000 00000023677 12646222644 016436 0 ustar 0000000 0000000 # 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, InferenceError
from astroid import nodes
SIX_ADD_METACLASS = 'six.add_metaclass'
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
def transform_six_add_metaclass(node):
"""Check if the given class node is decorated with *six.add_metaclass*
If so, inject its argument as the metaclass of the underlying class.
"""
if not node.decorators:
return
for decorator in node.decorators.nodes:
if not isinstance(decorator, nodes.Call):
continue
try:
func = next(decorator.func.infer())
except InferenceError:
continue
if func.qname() == SIX_ADD_METACLASS and decorator.args:
metaclass = decorator.args[0]
node._metaclass = metaclass
return node
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)
MANAGER.register_transform(nodes.ClassDef, transform_six_add_metaclass)
astroid-1.4.4/astroid/brain/brain_stdlib.py 0000666 0000000 0000000 00000037104 12646222644 017102 0 ustar 0000000 0000000
"""Astroid hooks for the Python 2 standard library.
Currently help understanding of :
* hashlib.md5 and hashlib.sha1
"""
import functools
import sys
from textwrap import dedent
from astroid import (
MANAGER, UseInferenceDefault, inference_tip, BoundMethod,
InferenceError, register_module_extender)
from astroid import exceptions
from astroid import nodes
from astroid.builder import AstroidBuilder
from astroid import util
PY3K = sys.version_info > (3, 0)
PY33 = sys.version_info >= (3, 3)
PY34 = sys.version_info >= (3, 4)
# 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):
if node is util.YES:
raise UseInferenceDefault
try:
value = next(node.infer(context=context))
if value is util.YES:
raise UseInferenceDefault()
else:
return value
except StopIteration:
raise InferenceError()
# node is a Call 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):
raise UseInferenceDefault()
# we want to return a Class node instance with proper attributes set
class_node = nodes.ClassDef(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
fake_node.attrname = attr
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):
self.iterable = iterable
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 __reversed__(self): return self.iterable[::-1]
def __getitem__(self, index): pass
def __setitem__(self, index, value): pass
def __delitem__(self, index): pass
''')
def pkg_resources_transform():
return AstroidBuilder(MANAGER).string_build('''
def require(*requirements):
return pkg_resources.working_set.require(*requirements)
def run_script(requires, script_name):
return pkg_resources.working_set.run_script(requires, script_name)
def iter_entry_points(group, name=None):
return pkg_resources.working_set.iter_entry_points(group, name)
def resource_exists(package_or_requirement, resource_name):
return get_provider(package_or_requirement).has_resource(resource_name)
def resource_isdir(package_or_requirement, resource_name):
return get_provider(package_or_requirement).resource_isdir(
resource_name)
def resource_filename(package_or_requirement, resource_name):
return get_provider(package_or_requirement).get_resource_filename(
self, resource_name)
def resource_stream(package_or_requirement, resource_name):
return get_provider(package_or_requirement).get_resource_stream(
self, resource_name)
def resource_string(package_or_requirement, resource_name):
return get_provider(package_or_requirement).get_resource_string(
self, resource_name)
def resource_listdir(package_or_requirement, resource_name):
return get_provider(package_or_requirement).resource_listdir(
resource_name)
def extraction_error():
pass
def get_cache_path(archive_name, names=()):
extract_path = self.extraction_path or get_default_cache()
target_path = os.path.join(extract_path, archive_name+'-tmp', *names)
return target_path
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'))
communicate_signature = 'def communicate(self, input=None, timeout=None)'
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')
communicate_signature = 'def communicate(self, input=None)'
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)'
if PY3K:
ctx_manager = '''
def __enter__(self): return self
def __exit__(self, *args): pass
'''
else:
ctx_manager = ''
code = dedent('''
class Popen(object):
returncode = pid = 0
stdin = stdout = stderr = file()
%(init)s
%(communicate_signature)s:
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
%(ctx_manager)s
''' % {'init': init,
'communicate': communicate,
'communicate_signature': communicate_signature,
'wait_signature': wait_signature,
'ctx_manager': ctx_manager})
return AstroidBuilder(MANAGER).string_build(code)
# namedtuple support ###########################################################
def _looks_like(node, name):
func = node.func
if isinstance(func, nodes.Attribute):
return func.attrname == name
if isinstance(func, nodes.Name):
return func.name == name
return False
_looks_like_namedtuple = functools.partial(_looks_like, name='namedtuple')
_looks_like_enum = functools.partial(_looks_like, name='Enum')
def infer_named_tuple(node, context=None):
"""Specific inference function for namedtuple Call 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):
return self
''' % {'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 Call node. """
enum_meta = nodes.ClassDef("EnumMeta", 'docstring')
class_node = infer_func_form(node, enum_meta,
context=context, enum=True)[0]
return iter([class_node])
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.AssignName)
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(%(types)s):
@property
def value(self):
# Not the best return.
return None
@property
def name(self):
return %(name)r
''' % {'name': target.name, 'types': ', '.join(node.basenames)})
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.instantiate_class())
node._locals[local] = new_targets
break
return node
def multiprocessing_transform():
module = AstroidBuilder(MANAGER).string_build(dedent('''
from multiprocessing.managers import SyncManager
def Manager():
return SyncManager()
'''))
if not PY34:
return module
# On Python 3.4, multiprocessing uses a getattr lookup inside contexts,
# in order to get the attributes they need. Since it's extremely
# dynamic, we use this approach to fake it.
node = AstroidBuilder(MANAGER).string_build(dedent('''
from multiprocessing.context import DefaultContext, BaseContext
default = DefaultContext()
base = BaseContext()
'''))
try:
context = next(node['default'].infer())
base = next(node['base'].infer())
except InferenceError:
return module
for node in (context, base):
for key, value in node._locals.items():
if key.startswith("_"):
continue
value = value[0]
if isinstance(value, nodes.FunctionDef):
# We need to rebound this, since otherwise
# it will have an extra argument (self).
value = BoundMethod(value, node)
module[key] = value
return module
def multiprocessing_managers_transform():
return AstroidBuilder(MANAGER).string_build(dedent('''
import array
import threading
import multiprocessing.pool as pool
import six
class Namespace(object):
pass
class Value(object):
def __init__(self, typecode, value, lock=True):
self._typecode = typecode
self._value = value
def get(self):
return self._value
def set(self, value):
self._value = value
def __repr__(self):
return '%s(%r, %r)'%(type(self).__name__, self._typecode, self._value)
value = property(get, set)
def Array(typecode, sequence, lock=True):
return array.array(typecode, sequence)
class SyncManager(object):
Queue = JoinableQueue = six.moves.queue.Queue
Event = threading.Event
RLock = threading.RLock
BoundedSemaphore = threading.BoundedSemaphore
Condition = threading.Condition
Barrier = threading.Barrier
Pool = pool.Pool
list = list
dict = dict
Value = Value
Array = Array
Namespace = Namespace
__enter__ = lambda self: self
__exit__ = lambda *args: args
def start(self, initializer=None, initargs=None):
pass
def shutdown(self):
pass
'''))
MANAGER.register_transform(nodes.Call, inference_tip(infer_named_tuple),
_looks_like_namedtuple)
MANAGER.register_transform(nodes.Call, inference_tip(infer_enum),
_looks_like_enum)
MANAGER.register_transform(nodes.ClassDef, 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)
register_module_extender(MANAGER, 'multiprocessing.managers',
multiprocessing_managers_transform)
register_module_extender(MANAGER, 'multiprocessing', multiprocessing_transform)
astroid-1.4.4/astroid/builder.py 0000666 0000000 0000000 00000024355 12646222644 015005 0 ustar 0000000 0000000 # 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
import _ast
import os
import sys
import textwrap
from astroid import bases
from astroid import exceptions
from astroid import manager
from astroid import modutils
from astroid import raw_building
from astroid import rebuilder
from astroid import util
def _parse(string):
return compile(string, "", 'exec', _ast.PyCF_ONLY_AST)
if sys.version_info >= (3, 0):
# pylint: disable=no-name-in-module; We don't understand flows yet.
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 encoding
# detect_encoding returns utf-8 if no encoding specified
msg = 'Wrong (%s) or no encoding specified' % encoding
raise exceptions.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
MANAGER = manager.AstroidManager()
class AstroidBuilder(raw_building.InspectBuilder):
"""Class for building an astroid tree from source code or from a live module.
The param *manager* specifies the manager class which should be used.
If no manager is given, then the default one will be used. The
param *apply_transforms* determines if the transforms should be
applied after the tree was built from source or from a live object,
by default being True.
"""
def __init__(self, manager=None, apply_transforms=True):
super(AstroidBuilder, self).__init__()
self._manager = manager or MANAGER
self._apply_transforms = apply_transforms
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 = os.path.splitext(modutils._path_from_filename(path))
if ext in ('.py', '.pyc', '.pyo') and os.path.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)
if self._apply_transforms:
# We have to handle transformation by ourselves since the
# rebuilder isn't called for builtin nodes
node = self._manager.visit_transforms(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 exceptions.AstroidBuildingException(msg)
except SyntaxError as exc: # py3k encoding specification error
raise exceptions.AstroidBuildingException(exc)
except LookupError as exc: # unknown encoding
raise exceptions.AstroidBuildingException(exc)
with stream:
# get module name if necessary
if modname is None:
try:
modname = '.'.join(modutils.modpath_from_file(path))
except ImportError:
modname = os.path.splitext(os.path.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."""
module = self._data_build(data, modname, path)
module.source_code = 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._import_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)
# Visit the transforms
if self._apply_transforms:
module = self._manager.visit_transforms(module)
return module
def _data_build(self, data, modname, path):
"""Build tree node from data and add some informations"""
try:
node = _parse(data + '\n')
except (TypeError, ValueError, SyntaxError) as exc:
raise exceptions.AstroidBuildingException(exc)
if path is not None:
node_file = os.path.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
builder = rebuilder.TreeRebuilder(self._manager)
module = builder.visit_module(node, modname, node_file, package)
module._import_from_nodes = builder._import_from_nodes
module._delayed_assattr = builder._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 exceptions.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
This adds name to locals and handle members definition.
"""
try:
frame = node.frame()
for inferred in node.expr.infer():
if inferred is util.YES:
continue
try:
if inferred.__class__ is bases.Instance:
inferred = inferred._proxied
iattrs = inferred._instance_attrs
elif isinstance(inferred, bases.Instance):
# Const, Tuple, ... we may be wrong, may be not, but
# anyway we don't want to pollute builtin's namespace
continue
elif inferred.is_function:
iattrs = inferred._instance_attrs
else:
iattrs = inferred._locals
except AttributeError:
# XXX log error
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 exceptions.InferenceError:
pass
def parse(code, module_name='', path=None, apply_transforms=True):
"""Parses a source string in order to obtain an astroid AST from it
:param str code: The code for the module.
:param str module_name: The name for the module, if any
:param str path: The path for the module
:param bool apply_transforms:
Apply the transforms for the give code. Use it if you
don't want the default transforms to be applied.
"""
code = textwrap.dedent(code)
builder = AstroidBuilder(manager=MANAGER,
apply_transforms=apply_transforms)
return builder.string_build(code, modname=module_name, path=path)
astroid-1.4.4/astroid/context.py 0000666 0000000 0000000 00000004653 12646222644 015042 0 ustar 0000000 0000000 # 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 .
"""Various context related utilities, including inference and call contexts."""
import contextlib
class InferenceContext(object):
__slots__ = ('path', 'lookupname', 'callcontext', 'boundnode', 'inferred')
def __init__(self, path=None, inferred=None):
self.path = path or set()
self.lookupname = None
self.callcontext = None
self.boundnode = None
self.inferred = inferred 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, inferred=self.inferred)
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.inferred[key] = tuple(results)
return
@contextlib.contextmanager
def restore_path(self):
path = set(self.path)
yield
self.path = path
class CallContext(object):
"""Holds information for a call site."""
__slots__ = ('args', 'keywords')
def __init__(self, args, keywords=None):
self.args = args
if keywords:
keywords = [(arg.arg, arg.value) for arg in keywords]
else:
keywords = []
self.keywords = keywords
def copy_context(context):
if context is not None:
return context.clone()
else:
return InferenceContext()
astroid-1.4.4/astroid/decorators.py 0000666 0000000 0000000 00000004676 12646222644 015530 0 ustar 0000000 0000000 # 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 .
#
# The code in this file was originally part of logilab-common, licensed under
# the same license.
""" A few useful function/method decorators."""
import wrapt
@wrapt.decorator
def cached(func, instance, args, kwargs):
"""Simple decorator to cache result of method calls without args."""
cache = getattr(instance, '__cache', None)
if cache is None:
instance.__cache = cache = {}
try:
return cache[func]
except KeyError:
cache[func] = result = func(*args, **kwargs)
return result
class cachedproperty(object):
""" Provides a cached property equivalent to the stacking of
@cached and @property, but more efficient.
After first usage, the becomes part of the object's
__dict__. Doing:
del obj. empties the cache.
Idea taken from the pyramid_ framework and the mercurial_ project.
.. _pyramid: http://pypi.python.org/pypi/pyramid
.. _mercurial: http://pypi.python.org/pypi/Mercurial
"""
__slots__ = ('wrapped',)
def __init__(self, wrapped):
try:
wrapped.__name__
except AttributeError:
raise TypeError('%s must have a __name__ attribute' %
wrapped)
self.wrapped = wrapped
@property
def __doc__(self):
doc = getattr(self.wrapped, '__doc__', None)
return ('%s'
% ('\n%s' % doc if doc else ''))
def __get__(self, inst, objtype=None):
if inst is None:
return self
val = self.wrapped(inst)
setattr(inst, self.wrapped.__name__, val)
return val
astroid-1.4.4/astroid/exceptions.py 0000666 0000000 0000000 00000004456 12646222644 015540 0 ustar 0000000 0000000 # 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 MroError(ResolveError):
"""Error raised when there is a problem with method resolution of a class."""
class DuplicateBasesError(MroError):
"""Error raised when there are duplicate bases in the same class bases."""
class InconsistentMroError(MroError):
"""Error raised when a class's MRO is inconsistent."""
class SuperError(ResolveError):
"""Error raised when there is a problem with a super call."""
class SuperArgumentTypeError(SuperError):
"""Error raised when the super arguments are invalid."""
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
"""
astroid-1.4.4/astroid/inference.py 0000666 0000000 0000000 00000027510 12646222644 015311 0 ustar 0000000 0000000 # 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
"""
from __future__ import print_function
from astroid import bases
from astroid import context as contextmod
from astroid import exceptions
from astroid import manager
from astroid import nodes
from astroid import protocols
from astroid import util
MANAGER = manager.AstroidManager()
# .infer method ###############################################################
def infer_end(self, context=None):
"""inference's end for node such as Module, ClassDef, FunctionDef,
Const...
"""
yield self
nodes.Module._infer = infer_end
nodes.ClassDef._infer = infer_end
nodes.FunctionDef._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.FunctionDef):
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 exceptions.UnresolvableName(self.name)
context = context.clone()
context.lookupname = self.name
return bases._infer_stmts(stmts, context, frame)
nodes.Name._infer = bases.path_wrapper(infer_name)
nodes.AssignName.infer_lhs = infer_name # won't work with a path wrapper
@bases.path_wrapper
@bases.raise_if_nothing_inferred
def infer_call(self, context=None):
"""infer a Call node by trying to guess what the function returns"""
callcontext = context.clone()
callcontext.callcontext = contextmod.CallContext(args=self.args,
keywords=self.keywords)
callcontext.boundnode = None
for callee in self.func.infer(context):
if callee is util.YES:
yield callee
continue
try:
if hasattr(callee, 'infer_call_result'):
for inferred in callee.infer_call_result(self, callcontext):
yield inferred
except exceptions.InferenceError:
## XXX log error ?
continue
nodes.Call._infer = infer_call
@bases.path_wrapper
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 exceptions.InferenceError()
if asname:
yield self.do_import_module(self.real_name(name))
else:
yield self.do_import_module(name)
nodes.Import._infer = infer_import
def infer_name_module(self, name):
context = contextmod.InferenceContext()
context.lookupname = name
return self.infer(context, asname=False)
nodes.Import.infer_name_module = infer_name_module
@bases.path_wrapper
def infer_import_from(self, context=None, asname=True):
"""infer a ImportFrom node: return the imported module/object"""
name = context.lookupname
if name is None:
raise exceptions.InferenceError()
if asname:
name = self.real_name(name)
module = self.do_import_module()
try:
context = contextmod.copy_context(context)
context.lookupname = name
stmts = module.getattr(name, ignore_locals=module is self.root())
return bases._infer_stmts(stmts, context)
except exceptions.NotFoundError:
raise exceptions.InferenceError(name)
nodes.ImportFrom._infer = infer_import_from
@bases.raise_if_nothing_inferred
def infer_attribute(self, context=None):
"""infer an Attribute node by using getattr on the associated object"""
for owner in self.expr.infer(context):
if owner is util.YES:
yield owner
continue
try:
context.boundnode = owner
for obj in owner.igetattr(self.attrname, context):
yield obj
context.boundnode = None
except (exceptions.NotFoundError, exceptions.InferenceError):
context.boundnode = None
except AttributeError:
# XXX method / function
context.boundnode = None
nodes.Attribute._infer = bases.path_wrapper(infer_attribute)
nodes.AssignAttr.infer_lhs = infer_attribute # # won't work with a path wrapper
@bases.path_wrapper
def infer_global(self, context=None):
if context.lookupname is None:
raise exceptions.InferenceError()
try:
return bases._infer_stmts(self.root().getattr(context.lookupname),
context)
except exceptions.NotFoundError:
raise exceptions.InferenceError()
nodes.Global._infer = infer_global
@bases.raise_if_nothing_inferred
def infer_subscript(self, context=None):
"""Inference for subscripts
We're understanding if the index is a Const
or a slice, passing the result of inference
to the value's `getitem` method, which should
handle each supported index type accordingly.
"""
value = next(self.value.infer(context))
if value is util.YES:
yield util.YES
return
index = next(self.slice.infer(context))
if index is util.YES:
yield util.YES
return
if isinstance(index, nodes.Const):
try:
assigned = value.getitem(index.value, context)
except AttributeError:
raise exceptions.InferenceError()
except (IndexError, TypeError):
yield util.YES
return
# Prevent inferring if the infered subscript
# is the same as the original subscripted object.
if self is assigned or assigned is util.YES:
yield util.YES
return
for infered in assigned.infer(context):
yield infered
else:
raise exceptions.InferenceError()
nodes.Subscript._infer = bases.path_wrapper(infer_subscript)
nodes.Subscript.infer_lhs = infer_subscript
@bases.raise_if_nothing_inferred
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 = protocols.UNARY_OP_METHOD[self.op]
if meth is None:
yield util.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 util.YES
nodes.UnaryOp._infer = bases.path_wrapper(infer_unaryop)
def _infer_binop(operator, operand1, operand2, context, failures=None):
if operand1 is util.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(protocols.BIN_OP_METHOD[operator])
yield operand1
except:
if failures is None:
yield util.YES
else:
failures.append(operand1)
@bases.yes_if_nothing_inferred
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 = bases.path_wrapper(infer_binop)
def infer_arguments(self, context=None):
name = context.lookupname
if name is None:
raise exceptions.InferenceError()
return protocols._arguments_infer_argname(self, name, context)
nodes.Arguments._infer = infer_arguments
@bases.path_wrapper
def infer_assign(self, context=None):
"""infer a AssignName/AssignAttr: 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 bases._infer_stmts(stmts, context)
nodes.AssignName._infer = infer_assign
nodes.AssignAttr._infer = infer_assign
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 = bases.path_wrapper(infer_augassign)
# no infer method on DelName and DelAttr (expected InferenceError)
@bases.path_wrapper
def infer_empty_node(self, context=None):
if not self.has_underlying_object():
yield util.YES
else:
try:
for inferred in MANAGER.infer_ast_from_something(self.object,
context=context):
yield inferred
except exceptions.AstroidError:
yield util.YES
nodes.EmptyNode._infer = infer_empty_node
def infer_index(self, context=None):
return self.value.infer(context)
nodes.Index._infer = infer_index
# TODO: move directly into bases.Instance when the dependency hell
# will be solved.
def instance_getitem(self, index, context=None):
# Rewrap index to Const for this case
index = nodes.Const(index)
if context:
new_context = context.clone()
else:
context = new_context = contextmod.InferenceContext()
# Create a new callcontext for providing index as an argument.
new_context.callcontext = contextmod.CallContext(args=[index])
new_context.boundnode = self
method = next(self.igetattr('__getitem__', context=context))
if not isinstance(method, bases.BoundMethod):
raise exceptions.InferenceError
try:
return next(method.infer_call_result(self, new_context))
except StopIteration:
raise exceptions.InferenceError
bases.Instance.getitem = instance_getitem
astroid-1.4.4/astroid/manager.py 0000666 0000000 0000000 00000025560 12646222644 014770 0 ustar 0000000 0000000 # 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
import imp
import os
import zipimport
from astroid import exceptions
from astroid import modutils
from astroid import transforms
def safe_repr(obj):
try:
return repr(obj)
except Exception: # pylint: disable=broad-except
return '???'
class AstroidManager(object):
"""the astroid manager, responsible to build astroid from files
or modules.
Use the Borg pattern.
"""
name = 'astroid loader'
brain = {}
def __init__(self):
self.__dict__ = AstroidManager.brain
if not self.__dict__:
# NOTE: cache entries are added by the [re]builder
self.astroid_cache = {}
self._mod_file_cache = {}
self._failed_import_hooks = []
self.always_load_extensions = False
self.optimize_ast = False
self.extension_package_whitelist = set()
self._transform = transforms.TransformVisitor()
# Export these APIs for convenience
self.register_transform = self._transform.register_transform
self.unregister_transform = self._transform.unregister_transform
def visit_transforms(self, node):
"""Visit the transforms and apply them to the given *node*."""
return self._transform.visit(node)
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].source_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 exceptions.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(os.path.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 exceptions.AstroidBuildingException(msg)
return self.ast_from_module(module, modname)
elif mp_type == imp.PY_COMPILED:
msg = "Unable to load compiled module %s" % (modname,)
raise exceptions.AstroidBuildingException(msg)
if filepath is None:
msg = "Unable to load module %s" % (modname,)
raise exceptions.AstroidBuildingException(msg)
return self.ast_from_file(filepath, modname, fallback=False)
except exceptions.AstroidBuildingException as e:
for hook in self._failed_import_hooks:
try:
return hook(modname)
except exceptions.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 Exception: # pylint: disable=broad-except
continue
return None
def file_from_module_name(self, modname, contextfile):
# pylint: disable=redefined-variable-type
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 = exceptions.AstroidBuildingException(msg)
self._mod_file_cache[(modname, contextfile)] = value
if isinstance(value, exceptions.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:
msg = 'Unable to get module for class %s' % safe_repr(klass)
raise exceptions.AstroidBuildingException(msg)
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:
msg = 'Unable to get module for %s' % safe_repr(klass)
raise exceptions.AstroidBuildingException(msg)
except Exception as ex:
msg = ('Unexpected error while retrieving module for %s: %s'
% (safe_repr(klass), ex))
raise exceptions.AstroidBuildingException(msg)
try:
name = klass.__name__
except AttributeError:
msg = 'Unable to get name for %s' % safe_repr(klass)
raise exceptions.AstroidBuildingException(msg)
except Exception as ex:
exc = ('Unexpected error while retrieving name for %s: %s'
% (safe_repr(klass), ex))
raise exceptions.AstroidBuildingException(exc)
# take care, on living object __module__ is regularly wrong :(
modastroid = self.ast_from_module_name(modname)
if klass is obj:
for inferred in modastroid.igetattr(name, context):
yield inferred
else:
for inferred in modastroid.igetattr(name, context):
yield inferred.instantiate_class()
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 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)
astroid-1.4.4/astroid/mixins.py 0000666 0000000 0000000 00000012604 12646222644 014660 0 ustar 0000000 0000000 # 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.
"""
import warnings
from astroid import decorators
from astroid import exceptions
class BlockRangeMixIn(object):
"""override block range """
@decorators.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 assign_type(self):
return self
def ass_type(self):
warnings.warn('%s.ass_type() is deprecated and slated for removal '
'in astroid 2.0, use %s.assign_type() instead.'
% (type(self).__name__, type(self).__name__),
PendingDeprecationWarning, stacklevel=2)
return self.assign_type()
class AssignTypeMixin(object):
def assign_type(self):
return self
def ass_type(self):
warnings.warn('%s.ass_type() is deprecated and slated for removal '
'in astroid 2.0, use %s.assign_type() instead.'
% (type(self).__name__, type(self).__name__),
PendingDeprecationWarning, stacklevel=2)
return self.assign_type()
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 assign_type(self):
return self.parent.assign_type()
def ass_type(self):
warnings.warn('%s.ass_type() is deprecated and slated for removal '
'in astroid 2.0, use %s.assign_type() instead.'
% (type(self).__name__, type(self).__name__),
PendingDeprecationWarning, stacklevel=2)
return self.assign_type()
class ImportFromMixin(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,
relative_only=level and level >= 1)
except exceptions.AstroidBuildingException as ex:
if isinstance(ex.args[0], SyntaxError):
raise exceptions.InferenceError(str(ex))
raise exceptions.InferenceError(modname)
except SyntaxError as ex:
raise exceptions.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 exceptions.NotFoundError(asname)
astroid-1.4.4/astroid/modutils.py 0000666 0000000 0000000 00000061634 12646222644 015220 0 ustar 0000000 0000000 # 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
import imp
import os
import platform
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
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',)
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)])
# 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()
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
if platform.python_implementation() == 'PyPy':
_root = os.path.join(sys.prefix, 'lib_pypy')
STD_LIB_DIRS.add(_root)
try:
# real_prefix is defined when running inside virtualenv.
STD_LIB_DIRS.add(os.path.join(sys.real_prefix, 'lib_pypy'))
except AttributeError:
pass
del _root
if os.name == 'posix':
# Need the real prefix is we're under a virtualenv, otherwise
# the usual one will do.
try:
prefix = sys.real_prefix
except AttributeError:
prefix = sys.prefix
def _posix_path(path):
base_python = 'python%d.%d' % sys.version_info[:2]
return os.path.join(prefix, path, base_python)
STD_LIB_DIRS.add(_posix_path('lib'))
if sys.maxsize > 2**32:
# This tries to fix a problem with /usr/lib64 builds,
# where systems are running both 32-bit and 64-bit code
# on the same machine, which reflects into the places where
# standard library could be found. More details can be found
# here http://bugs.python.org/issue1294959.
# An easy reproducing case would be
# https://github.com/PyCQA/pylint/issues/712#issuecomment-163178753
STD_LIB_DIRS.add(_posix_path('lib64'))
EXT_LIB_DIR = get_python_lib()
IS_JYTHON = platform.python_implementation() == 'Jython'
BUILTIN_MODULES = dict.fromkeys(sys.builtin_module_names, True)
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))
def _path_from_filename(filename, is_jython=IS_JYTHON):
if not is_jython:
if sys.version_info > (3, 0):
return filename
else:
if filename.endswith(".pyc"):
return filename[:-1]
return filename
head, has_pyclass, _ = filename.partition("$py.class")
if has_pyclass:
return head + ".py"
return filename
def _handle_blacklist(blacklist, dirnames, filenames):
"""remove files/directories in the black list
dirnames/filenames are usually from os.walk
"""
for norecurs in blacklist:
if norecurs in dirnames:
dirnames.remove(norecurs)
elif norecurs in filenames:
filenames.remove(norecurs)
_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=True):
"""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__', '')
prevmodule = module
if not _file and _is_namespace(curname):
continue
if not _file and len(modpath) != len(parts):
raise ImportError('no module in %s' % '.'.join(parts[len(modpath):]))
path = [os.path.dirname(_file)]
return module
def load_module_from_file(filepath, path=None, use_sys=True, 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"""
modpath = []
for part in mod_path:
modpath.append(part)
path = os.path.join(path, part)
if not _is_namespace('.'.join(modpath)) and 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
"""
filename = _path_from_filename(filename)
filename = os.path.abspath(filename)
base = os.path.splitext(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('astroid.as_string.dump')
'astroid.as_string'
: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: iterable
list of files or directories to ignore.
: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
"""
filename = os.path.abspath(_path_from_filename(filename))
base, orig_ext = os.path.splitext(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:
# we assume there are no namespaces in stdlib
return not _is_namespace(modname)
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 list(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))
try:
import pkg_resources
except ImportError:
pkg_resources = None
def _is_namespace(modname):
return (pkg_resources is not None
and modname in pkg_resources._namespace_packages)
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 _is_namespace(modpath[0]) and modpath[0] in sys.modules:
# 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__
if not modpath:
return imp.C_BUILTIN, None
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:
extend_path = b'pkgutil' in data and b'extend_path' in data
declare_namespace = (
b"pkg_resources" in data
and b"declare_namespace(__name__)" in data)
if extend_path or declare_namespace:
# 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
astroid-1.4.4/astroid/nodes.py 0000666 0000000 0000000 00000006260 12646170047 014461 0 ustar 0000000 0000000 # 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, FunctionDef or ClassDef)
.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 ImportFrom and Import :
.real_name(name),
"""
# pylint: disable=unused-import,redefined-builtin
from astroid.node_classes import (
Arguments, AssignAttr, Assert, Assign,
AssignName, AugAssign, Repr, BinOp, BoolOp, Break, Call, Compare,
Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete,
Dict, Expr, Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, For,
ImportFrom, Attribute, 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,
AsyncFor, Await, AsyncWith,
# Backwards-compatibility aliases
Backquote, Discard, AssName, AssAttr, Getattr, CallFunc, From,
# Node not present in the builtin ast module.
DictUnpack,
)
from astroid.scoped_nodes import (
Module, GeneratorExp, Lambda, DictComp,
ListComp, SetComp, FunctionDef, ClassDef,
AsyncFunctionDef,
# Backwards-compatibility aliases
Class, Function, GenExpr,
)
ALL_NODE_CLASSES = (
AsyncFunctionDef, AsyncFor, AsyncWith, Await,
Arguments, AssignAttr, Assert, Assign, AssignName, AugAssign,
Repr, BinOp, BoolOp, Break,
Call, ClassDef, Compare, Comprehension, Const, Continue,
Decorators, DelAttr, DelName, Delete,
Dict, DictComp, DictUnpack, Expr,
Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice,
For, ImportFrom, FunctionDef,
Attribute, GeneratorExp, 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,
)
astroid-1.4.4/astroid/node_classes.py 0000666 0000000 0000000 00000100275 12646222644 016015 0 ustar 0000000 0000000 # 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 abc
import warnings
import lazy_object_proxy
import six
from astroid import bases
from astroid import context as contextmod
from astroid import decorators
from astroid import exceptions
from astroid import mixins
from astroid import util
BUILTINS = six.moves.builtins.__name__
@bases.raise_if_nothing_inferred
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:
if elt is util.YES:
yield elt
continue
for inferred_elt in unpack_infer(elt, context):
yield inferred_elt
return
# if inferred is a final node, return it and stop
inferred = next(stmt.infer(context))
if inferred is stmt:
yield inferred
return
# else, infer recursivly, except YES object that should be returned as is
for inferred in stmt.infer(context):
if inferred is util.YES:
yield inferred
else:
for inf_inf in unpack_infer(inferred, 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
@six.add_metaclass(abc.ABCMeta)
class _BaseContainer(mixins.ParentAssignTypeMixin,
bases.NodeNG,
bases.Instance):
"""Base class for Set, FrozenSet, Tuple and List."""
_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 itered(self):
return self.elts
def bool_value(self):
return bool(self.elts)
@abc.abstractmethod
def pytype(self):
pass
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):
"""inferred lookup
return an iterator on inferred values of the statements returned by
the lookup method
"""
frame, stmts = self.lookup(name)
context = contextmod.InferenceContext()
return bases._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()
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, 'assign_type'), (node, node.scope(),
node.scope().locals)
assign_type = node.assign_type()
if node.has_base(self):
break
_stmts, done = assign_type._get_filtered_stmts(self, node, _stmts, mystmt)
if done:
break
optional_assign = assign_type.optional_assign
if optional_assign and assign_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].assign_type().parent_of(assign_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, AssignName):
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 AssignName(LookupMixIn, mixins.ParentAssignTypeMixin, bases.NodeNG):
"""class representing an AssName node"""
class DelName(LookupMixIn, mixins.ParentAssignTypeMixin, bases.NodeNG):
"""class representing a DelName node"""
class Name(LookupMixIn, bases.NodeNG):
"""class representing a Name node"""
class Arguments(mixins.AssignTypeMixin, bases.NodeNG):
"""class representing an Arguments node"""
if six.PY3:
# 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
@decorators.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,
getattr(self, 'annotations', None))
)
if self.vararg:
result.append('*%s' % self.vararg)
if self.kwonlyargs:
if not self.vararg:
result.append('*')
result.append(_format_args(self.kwonlyargs, self.kw_defaults))
if self.kwarg:
result.append('**%s' % self.kwarg)
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 exceptions.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, annotations=None):
values = []
if args is None:
return ''
if annotations is None:
annotations = []
if defaults is not None:
default_offset = len(args) - len(defaults)
packed = six.moves.zip_longest(args, annotations)
for i, (arg, annotation) in enumerate(packed):
if isinstance(arg, Tuple):
values.append('(%s)' % _format_args(arg.elts))
else:
argname = arg.name
if annotation is not None:
argname += ':' + annotation.as_string()
values.append(argname)
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 AssignAttr(mixins.ParentAssignTypeMixin, bases.NodeNG):
"""class representing an AssignAttr node"""
_astroid_fields = ('expr',)
expr = None
class Assert(bases.Statement):
"""class representing an Assert node"""
_astroid_fields = ('test', 'fail',)
test = None
fail = None
class Assign(bases.Statement, mixins.AssignTypeMixin):
"""class representing an Assign node"""
_astroid_fields = ('targets', 'value',)
targets = None
value = None
class AugAssign(bases.Statement, mixins.AssignTypeMixin):
"""class representing an AugAssign node"""
_astroid_fields = ('target', 'value',)
target = None
value = None
class Repr(bases.NodeNG):
"""class representing a Backquote node"""
_astroid_fields = ('value',)
value = None
class BinOp(bases.NodeNG):
"""class representing a BinOp node"""
_astroid_fields = ('left', 'right',)
left = None
right = None
class BoolOp(bases.NodeNG):
"""class representing a BoolOp node"""
_astroid_fields = ('values',)
values = None
class Break(bases.Statement):
"""class representing a Break node"""
class Call(bases.NodeNG):
"""class representing a Call node"""
_astroid_fields = ('func', 'args', 'keywords')
func = None
args = None
keywords = None
@property
def starargs(self):
args = self.args or []
return [arg for arg in args if isinstance(arg, Starred)]
@property
def kwargs(self):
keywords = self.keywords or []
return [keyword for keyword in keywords if keyword.arg is None]
class Compare(bases.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(bases.NodeNG):
"""class representing a Comprehension node"""
_astroid_fields = ('target', 'iter', 'ifs')
target = None
iter = None
ifs = None
optional_assign = True
def assign_type(self):
return self
def ass_type(self):
warnings.warn('%s.ass_type() is deprecated and slated for removal'
'in astroid 2.0, use %s.assign_type() instead.'
% (type(self).__name__, type(self).__name__),
PendingDeprecationWarning, stacklevel=2)
return self.assign_type()
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(bases.NodeNG, bases.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])
if isinstance(self.value, bytes) and six.PY3:
# Bytes aren't instances of six.string_types
# on Python 3. Also, indexing them should return
# integers.
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(bases.Statement):
"""class representing a Continue node"""
class Decorators(bases.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(mixins.ParentAssignTypeMixin, bases.NodeNG):
"""class representing a DelAttr node"""
_astroid_fields = ('expr',)
expr = None
class Delete(mixins.AssignTypeMixin, bases.Statement):
"""class representing a Delete node"""
_astroid_fields = ('targets',)
targets = None
class Dict(bases.NodeNG, bases.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 list(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:
# TODO(cpopa): no support for overriding yet, {1:2, **{1: 3}}.
if isinstance(key, DictUnpack):
try:
return value.getitem(lookup_key, context)
except IndexError:
continue
for inferredkey in key.infer(context):
if inferredkey is util.YES:
continue
if isinstance(inferredkey, Const) \
and inferredkey.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 Expr(bases.Statement):
"""class representing a Expr node"""
_astroid_fields = ('value',)
value = None
class Ellipsis(bases.NodeNG): # pylint: disable=redefined-builtin
"""class representing an Ellipsis node"""
class EmptyNode(bases.NodeNG):
"""class representing an EmptyNode node"""
class ExceptHandler(mixins.AssignTypeMixin, bases.Statement):
"""class representing an ExceptHandler node"""
_astroid_fields = ('type', 'name', 'body',)
type = None
name = None
body = None
@decorators.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(bases.Statement):
"""class representing an Exec node"""
_astroid_fields = ('expr', 'globals', 'locals',)
expr = None
globals = None
locals = None
class ExtSlice(bases.NodeNG):
"""class representing an ExtSlice node"""
_astroid_fields = ('dims',)
dims = None
class For(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, bases.Statement):
"""class representing a For node"""
_astroid_fields = ('target', 'iter', 'body', 'orelse',)
target = None
iter = None
body = None
orelse = None
optional_assign = True
@decorators.cachedproperty
def blockstart_tolineno(self):
return self.iter.tolineno
class AsyncFor(For):
"""Asynchronous For built with `async` keyword."""
class Await(bases.NodeNG):
"""Await node for the `await` keyword."""
_astroid_fields = ('value', )
value = None
def postinit(self, value=None):
self.value = value
class ImportFrom(mixins.ImportFromMixin, bases.Statement):
"""class representing a From node"""
def __init__(self, fromname, names, level=0):
self.modname = fromname
self.names = names
self.level = level
class Attribute(bases.NodeNG):
"""class representing a Attribute node"""
_astroid_fields = ('expr',)
expr = None
class Global(bases.Statement):
"""class representing a Global node"""
def __init__(self, names):
self.names = names
def _infer_name(self, frame, name):
return name
class If(mixins.BlockRangeMixIn, bases.Statement):
"""class representing an If node"""
_astroid_fields = ('test', 'body', 'orelse')
test = None
body = None
orelse = None
@decorators.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(bases.NodeNG):
"""class representing an IfExp node"""
_astroid_fields = ('test', 'body', 'orelse')
test = None
body = None
orelse = None
class Import(mixins.ImportFromMixin, bases.Statement):
"""class representing an Import node"""
class Index(bases.NodeNG):
"""class representing an Index node"""
_astroid_fields = ('value',)
value = None
class Keyword(bases.NodeNG):
"""class representing a Keyword node"""
_astroid_fields = ('value',)
value = None
class List(_BaseContainer):
"""class representing a List node"""
def pytype(self):
return '%s.list' % BUILTINS
def getitem(self, index, context=None):
return self.elts[index]
class Nonlocal(bases.Statement):
"""class representing a Nonlocal node"""
def __init__(self, names):
self.names = names
def _infer_name(self, frame, name):
return name
class Pass(bases.Statement):
"""class representing a Pass node"""
class Print(bases.Statement):
"""class representing a Print node"""
_astroid_fields = ('dest', 'values',)
dest = None
values = None
class Raise(bases.Statement):
"""class representing a Raise node"""
exc = None
if six.PY2:
_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(bases.Statement):
"""class representing a Return node"""
_astroid_fields = ('value',)
value = None
class Set(_BaseContainer):
"""class representing a Set node"""
def pytype(self):
return '%s.set' % BUILTINS
class Slice(bases.NodeNG):
"""class representing a Slice node"""
_astroid_fields = ('lower', 'upper', 'step')
lower = None
upper = None
step = None
class Starred(mixins.ParentAssignTypeMixin, bases.NodeNG):
"""class representing a Starred node"""
_astroid_fields = ('value',)
value = None
class Subscript(bases.NodeNG):
"""class representing a Subscript node"""
_astroid_fields = ('value', 'slice')
value = None
slice = None
class TryExcept(mixins.BlockRangeMixIn, bases.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(mixins.BlockRangeMixIn, bases.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(_BaseContainer):
"""class representing a Tuple node"""
def pytype(self):
return '%s.tuple' % BUILTINS
def getitem(self, index, context=None):
return self.elts[index]
class UnaryOp(bases.NodeNG):
"""class representing an UnaryOp node"""
_astroid_fields = ('operand',)
operand = None
class While(mixins.BlockRangeMixIn, bases.Statement):
"""class representing a While node"""
_astroid_fields = ('test', 'body', 'orelse',)
test = None
body = None
orelse = None
@decorators.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(mixins.BlockRangeMixIn, mixins.AssignTypeMixin, bases.Statement):
"""class representing a With node"""
_astroid_fields = ('items', 'body')
items = None
body = None
@decorators.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 AsyncWith(With):
"""Asynchronous `with` built with the `async` keyword."""
class Yield(bases.NodeNG):
"""class representing a Yield node"""
_astroid_fields = ('value',)
value = None
class YieldFrom(Yield):
""" Class representing a YieldFrom node. """
class DictUnpack(bases.NodeNG):
"""Represents the unpacking of dicts into dicts using PEP 448."""
# constants ##############################################################
CONST_CLS = {
list: List,
tuple: Tuple,
dict: Dict,
set: Set,
type(None): Const,
type(NotImplemented): Const,
}
def _update_const_classes():
"""update constant classes, so the keys of CONST_CLS can be reused"""
klasses = (bool, int, float, complex, str)
if six.PY2:
klasses += (unicode, long)
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, bases.NodeNG)
try:
return CONST_CLS[value.__class__](value)
except (KeyError, AttributeError):
node = EmptyNode()
node.object = value
return node
# Backward-compatibility aliases
def instancecheck(cls, other):
wrapped = cls.__wrapped__
other_cls = other.__class__
is_instance_of = wrapped is other_cls or issubclass(other_cls, wrapped)
warnings.warn("%r is deprecated and slated for removal in astroid "
"2.0, use %r instead" % (cls.__class__.__name__,
wrapped.__name__),
PendingDeprecationWarning, stacklevel=2)
return is_instance_of
def proxy_alias(alias_name, node_type):
proxy = type(alias_name, (lazy_object_proxy.Proxy,),
{'__class__': object.__dict__['__class__'],
'__instancecheck__': instancecheck})
return proxy(lambda: node_type)
Backquote = proxy_alias('Backquote', Repr)
Discard = proxy_alias('Discard', Expr)
AssName = proxy_alias('AssName', AssignName)
AssAttr = proxy_alias('AssAttr', AssignAttr)
Getattr = proxy_alias('Getattr', Attribute)
CallFunc = proxy_alias('CallFunc', Call)
From = proxy_alias('From', ImportFrom)
astroid-1.4.4/astroid/objects.py 0000666 0000000 0000000 00000014403 12646222644 015001 0 ustar 0000000 0000000 # 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 .
"""
Inference objects are a way to represent composite AST nodes,
which are used only as inference results, so they can't be found in the
code tree. For instance, inferring the following frozenset use, leads to an
inferred FrozenSet:
CallFunc(func=Name('frozenset'), args=Tuple(...))
"""
import six
from astroid import MANAGER
from astroid.bases import (
BUILTINS, NodeNG, Instance, _infer_stmts,
BoundMethod, _is_property
)
from astroid.decorators import cachedproperty
from astroid.exceptions import (
SuperError, SuperArgumentTypeError,
NotFoundError, MroError
)
from astroid.node_classes import const_factory
from astroid.scoped_nodes import ClassDef, FunctionDef
from astroid.mixins import ParentAssignTypeMixin
class FrozenSet(NodeNG, Instance, ParentAssignTypeMixin):
"""class representing a FrozenSet composite node"""
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.frozenset' % BUILTINS
def itered(self):
return self.elts
def _infer(self, context=None):
yield self
@cachedproperty
def _proxied(self):
builtins = MANAGER.astroid_cache[BUILTINS]
return builtins.getattr('frozenset')[0]
class Super(NodeNG):
"""Proxy class over a super call.
This class offers almost the same behaviour as Python's super,
which is MRO lookups for retrieving attributes from the parents.
The *mro_pointer* is the place in the MRO from where we should
start looking, not counting it. *mro_type* is the object which
provides the MRO, it can be both a type or an instance.
*self_class* is the class where the super call is, while
*scope* is the function where the super call is.
"""
def __init__(self, mro_pointer, mro_type, self_class, scope):
self.type = mro_type
self.mro_pointer = mro_pointer
self._class_based = False
self._self_class = self_class
self._scope = scope
self._model = {
'__thisclass__': self.mro_pointer,
'__self_class__': self._self_class,
'__self__': self.type,
'__class__': self._proxied,
}
def _infer(self, context=None):
yield self
def super_mro(self):
"""Get the MRO which will be used to lookup attributes in this super."""
if not isinstance(self.mro_pointer, ClassDef):
raise SuperArgumentTypeError("The first super argument must be type.")
if isinstance(self.type, ClassDef):
# `super(type, type)`, most likely in a class method.
self._class_based = True
mro_type = self.type
else:
mro_type = getattr(self.type, '_proxied', None)
if not isinstance(mro_type, (Instance, ClassDef)):
raise SuperArgumentTypeError("super(type, obj): obj must be an "
"instance or subtype of type")
if not mro_type.newstyle:
raise SuperError("Unable to call super on old-style classes.")
mro = mro_type.mro()
if self.mro_pointer not in mro:
raise SuperArgumentTypeError("super(type, obj): obj must be an "
"instance or subtype of type")
index = mro.index(self.mro_pointer)
return mro[index + 1:]
@cachedproperty
def _proxied(self):
builtins = MANAGER.astroid_cache[BUILTINS]
return builtins.getattr('super')[0]
def pytype(self):
return '%s.super' % BUILTINS
def display_type(self):
return 'Super of'
@property
def name(self):
"""Get the name of the MRO pointer."""
return self.mro_pointer.name
def igetattr(self, name, context=None):
"""Retrieve the inferred values of the given attribute name."""
local_name = self._model.get(name)
if local_name:
yield local_name
return
try:
mro = self.super_mro()
except (MroError, SuperError) as exc:
# Don't let invalid MROs or invalid super calls
# to leak out as is from this function.
six.raise_from(NotFoundError, exc)
found = False
for cls in mro:
if name not in cls._locals:
continue
found = True
for infered in _infer_stmts([cls[name]], context, frame=self):
if not isinstance(infered, FunctionDef):
yield infered
continue
# We can obtain different descriptors from a super depending
# on what we are accessing and where the super call is.
if infered.type == 'classmethod':
yield BoundMethod(infered, cls)
elif self._scope.type == 'classmethod' and infered.type == 'method':
yield infered
elif self._class_based or infered.type == 'staticmethod':
yield infered
elif _is_property(infered):
# TODO: support other descriptors as well.
for value in infered.infer_call_result(self, context):
yield value
else:
yield BoundMethod(infered, cls)
if not found:
raise NotFoundError(name)
def getattr(self, name, context=None):
return list(self.igetattr(name, context=context))
astroid-1.4.4/astroid/protocols.py 0000666 0000000 0000000 00000040731 12646222644 015377 0 ustar 0000000 0000000 # 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.
"""
import collections
import operator
import sys
from astroid import arguments
from astroid import bases
from astroid import context as contextmod
from astroid import exceptions
from astroid import node_classes
from astroid import nodes
from astroid import util
BIN_OP_METHOD = {'+': '__add__',
'-': '__sub__',
'/': '__div__',
'//': '__floordiv__',
'*': '__mul__',
'**': '__pow__',
'%': '__mod__',
'&': '__and__',
'|': '__or__',
'^': '__xor__',
'<<': '__lshift__',
'>>': '__rshift__',
'@': '__matmul__'
}
UNARY_OP_METHOD = {'+': '__pos__',
'-': '__neg__',
'~': '__invert__',
'not': None, # XXX not '__nonzero__'
}
# unary operations ############################################################
def tl_infer_unary_op(self, operator):
if operator == 'not':
return node_classes.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 node_classes.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 node_classes.const_factory(not self.value)
# XXX log potentially raised TypeError
elif operator == '+':
return node_classes.const_factory(+self.value)
else: # operator == '-':
return node_classes.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,
}
if sys.version_info >= (3, 5):
# MatMult is available since Python 3.5+.
BIN_OP_IMPL['@'] = operator.matmul
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 node_classes.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 util.YES:
yield other
else:
try:
for val in other.infer_binary_op(operator, self, context):
yield val
except AttributeError:
yield util.YES
nodes.Const.infer_binary_op = bases.yes_if_nothing_inferred(const_infer_binary_op)
def _multiply_seq_by_int(self, other, context):
node = self.__class__()
elts = []
for elt in self.elts:
infered = util.safe_infer(elt, context)
if infered is None:
infered = util.YES
elts.append(infered)
node.elts = elts * other.value
return node
def _filter_uninferable_nodes(elts, context):
for elt in elts:
if elt is util.YES:
yield elt
else:
for inferred in elt.infer(context):
yield inferred
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 = list(_filter_uninferable_nodes(self.elts, context))
elts += list(_filter_uninferable_nodes(other.elts, context))
node.elts = elts
yield node
elif isinstance(other, nodes.Const) and operator == '*':
if not isinstance(other.value, int):
yield util.YES
continue
yield _multiply_seq_by_int(self, other, context)
elif isinstance(other, bases.Instance) and not isinstance(other, nodes.Const):
yield util.YES
# XXX else log TypeError
nodes.Tuple.infer_binary_op = bases.yes_if_nothing_inferred(tl_infer_binary_op)
nodes.List.infer_binary_op = bases.yes_if_nothing_inferred(tl_infer_binary_op)
def dict_infer_binary_op(self, operator, other, context):
for other in other.infer(context):
if isinstance(other, bases.Instance) and isinstance(other._proxied, nodes.ClassDef):
yield util.YES
# XXX else log TypeError
nodes.Dict.infer_binary_op = bases.yes_if_nothing_inferred(dict_infer_binary_op)
def instance_infer_binary_op(self, operator, other, context):
try:
methods = self.getattr(BIN_OP_METHOD[operator])
except (exceptions.NotFoundError, KeyError):
# Unknown operator
yield util.YES
else:
for method in methods:
if not isinstance(method, nodes.FunctionDef):
continue
for result in method.infer_call_result(self, context):
if result is not util.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
bases.Instance.infer_binary_op = bases.yes_if_nothing_inferred(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 util.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 util.YES:
break
else:
# we are not yet on the last part of the path
# search on each possibly inferred value
try:
for inferred in _resolve_looppart(assigned.infer(context),
asspath, context):
yield inferred
except exceptions.InferenceError:
break
@bases.raise_if_nothing_inferred
def for_assigned_stmts(self, node=None, 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 inferred in _resolve_looppart(self.iter.infer(context),
asspath, context):
yield inferred
nodes.For.assigned_stmts = for_assigned_stmts
nodes.Comprehension.assigned_stmts = for_assigned_stmts
def sequence_assigned_stmts(self, node=None, context=None, asspath=None):
if asspath is None:
asspath = []
try:
index = self.elts.index(node)
except ValueError:
util.reraise(exceptions.InferenceError(
'Tried to retrieve a node {node!r} which does not exist',
node=self, assign_path=asspath, context=context))
asspath.insert(0, index)
return self.parent.assigned_stmts(node=self, context=context, asspath=asspath)
nodes.Tuple.assigned_stmts = sequence_assigned_stmts
nodes.List.assigned_stmts = sequence_assigned_stmts
def assend_assigned_stmts(self, node=None, context=None, asspath=None):
return self.parent.assigned_stmts(node=self, context=context)
nodes.AssignName.assigned_stmts = assend_assigned_stmts
nodes.AssignAttr.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 util.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 bases.Instance(self.parent.parent.frame())
return
if functype == 'classmethod':
yield self.parent.parent.frame()
return
if context and context.callcontext:
call_site = arguments.CallSite(context.callcontext)
for value in call_site.infer_argument(self.parent, name, context):
yield value
return
# TODO: just provide the type here, no need to have an empty Dict.
if name == self.vararg:
vararg = node_classes.const_factory(())
vararg.parent = self
yield vararg
return
if name == self.kwarg:
kwarg = node_classes.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 = contextmod.copy_context(context)
for inferred in self.default_value(name).infer(context):
yield inferred
yield util.YES
except exceptions.NoDefault:
yield util.YES
def arguments_assigned_stmts(self, node=None, context=None, asspath=None):
if context.callcontext:
# reset call context/name
callcontext = context.callcontext
context = contextmod.copy_context(context)
context.callcontext = None
args = arguments.CallSite(callcontext)
return args.infer_argument(self.parent, node.name, context)
return _arguments_infer_argname(self, node.name, context)
nodes.Arguments.assigned_stmts = arguments_assigned_stmts
@bases.raise_if_nothing_inferred
def assign_assigned_stmts(self, node=None, context=None, asspath=None):
if not asspath:
yield self.value
return
for inferred in _resolve_asspart(self.value.infer(context), asspath, context):
yield inferred
nodes.Assign.assigned_stmts = assign_assigned_stmts
nodes.AugAssign.assigned_stmts = 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 util.YES:
return
else:
# we are not yet on the last part of the path search on each
# possibly inferred value
try:
for inferred in _resolve_asspart(assigned.infer(context),
asspath, context):
yield inferred
except exceptions.InferenceError:
return
@bases.raise_if_nothing_inferred
def excepthandler_assigned_stmts(self, node=None, context=None, asspath=None):
for assigned in node_classes.unpack_infer(self.type):
if isinstance(assigned, nodes.ClassDef):
assigned = bases.Instance(assigned)
yield assigned
nodes.ExceptHandler.assigned_stmts = bases.raise_if_nothing_inferred(excepthandler_assigned_stmts)
@bases.raise_if_nothing_inferred
def with_assigned_stmts(self, node=None, 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 = with_assigned_stmts
@bases.yes_if_nothing_inferred
def starred_assigned_stmts(self, node=None, context=None, asspath=None):
stmt = self.statement()
if not isinstance(stmt, (nodes.Assign, nodes.For)):
raise exceptions.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 exceptions.InferenceError()
if context is None:
context = contextmod.InferenceContext()
try:
rhs = next(value.infer(context))
except exceptions.InferenceError:
yield util.YES
return
if rhs is util.YES or not hasattr(rhs, 'elts'):
# Not interested in inferred values without elts.
yield util.YES
return
elts = collections.deque(rhs.elts[:])
if len(lhs.elts) > len(rhs.elts):
# a, *b, c = (1, 2)
raise exceptions.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
packed = nodes.List()
packed.elts = elts
packed.parent = self
yield packed
break
nodes.Starred.assigned_stmts = starred_assigned_stmts
astroid-1.4.4/astroid/raw_building.py 0000666 0000000 0000000 00000035044 12646222644 016022 0 ustar 0000000 0000000 # 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)
"""
import sys
import os
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
_JYTHON = os.name == 'java'
_BUILTINS = vars(six.moves.builtins)
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)
def _add_dunder_class(func, member):
"""Add a __class__ member to the given func node, if we can determine it."""
python_cls = member.__class__
cls_name = getattr(python_cls, '__name__', None)
if not cls_name:
return
bases = [ancestor.__name__ for ancestor in python_cls.__bases__]
ast_klass = build_class(cls_name, bases, python_cls.__doc__)
func._instance_attrs['__class__'] = [ast_klass]
_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)
_add_dunder_class(func, member)
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.source_file = 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__')
or (name in _BUILTINS and _JYTHON)):
# 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
real_name = {
'gtk': 'gtk_gtk',
'_io': 'io',
}.get(modname, modname)
if real_name != 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 six.moves 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
elif cls is type(NotImplemented):
proxy = build_class('NotImplementedType')
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)
astroid-1.4.4/astroid/rebuilder.py 0000666 0000000 0000000 00000121570 12646222644 015331 0 ustar 0000000 0000000 # 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
import _ast
from _ast import (
# 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
from astroid import astpeephole
_BIN_OP_CLASSES = {Add: '+',
BitAnd: '&',
BitOr: '|',
BitXor: '^',
Div: '/',
FloorDiv: '//',
Mod: '%',
Mult: '*',
Pow: '**',
Sub: '-',
LShift: '<<',
RShift: '>>',
}
if sys.version_info >= (3, 5):
from _ast import MatMult
_BIN_OP_CLASSES[MatMult] = '@'
_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',
'comprehension': 'Comprehension',
"ListCompFor": 'Comprehension',
"GenExprFor": 'Comprehension',
'excepthandler': 'ExceptHandler',
'keyword': 'Keyword',
}
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], _ast.Expr) and isinstance(node.body[0].value, _ast.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, None)
return newnode
def _visit_or_none(node, attr, visitor, parent, assign_ctx, visit='visit',
**kws):
"""If the given node has an attribute, visits the attribute, and
otherwise returns None.
"""
value = getattr(node, attr, None)
if value:
return getattr(visitor, visit)(value, parent, assign_ctx, **kws)
else:
return None
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._import_from_nodes = []
self._delayed_assattr = []
self._visit_meths = {}
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.source_file = modpath
return newnode
def visit(self, node, parent, assign_ctx=None):
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 visit_method(node, parent, assign_ctx)
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, assign_ctx=None):
"""visit a Arguments node by returning a fresh instance of it"""
newnode = new.Arguments()
newnode.parent = parent
newnode.args = [self.visit(child, newnode, "Assign")
for child in node.args]
newnode.defaults = [self.visit(child, newnode, assign_ctx)
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, assign_ctx)
vararg = vararg.arg
elif PY3K and node.varargannotation:
newnode.varargannotation = self.visit(node.varargannotation,
newnode, assign_ctx)
if kwarg:
if PY34:
if kwarg.annotation:
newnode.kwargannotation = self.visit(kwarg.annotation,
newnode, assign_ctx)
kwarg = kwarg.arg
elif PY3K:
if node.kwargannotation:
newnode.kwargannotation = self.visit(node.kwargannotation,
newnode, assign_ctx)
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_assignattr(self, node, parent, assign_ctx=None):
"""visit a AssAttr node by returning a fresh instance of it"""
newnode = new.AssignAttr()
_lineno_parent(node, newnode, parent)
newnode.expr = self.visit(node.expr, newnode, assign_ctx)
self._delayed_assattr.append(newnode)
return newnode
def visit_assert(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
if node.msg is not None:
newnode.fail = self.visit(node.msg, newnode, assign_ctx)
return newnode
def visit_assign(self, node, parent, assign_ctx=None):
"""visit a Assign node by returning a fresh instance of it"""
newnode = new.Assign()
_lineno_parent(node, newnode, parent)
newnode.targets = [self.visit(child, newnode, "Assign")
for child in node.targets]
newnode.value = self.visit(node.value, newnode, None)
return newnode
def visit_assignname(self, node, parent, assign_ctx=None, node_name=None):
'''visit a node and return a AssName node'''
newnode = new.AssignName()
_set_infos(node, newnode, parent)
newnode.name = node_name
self._save_assignment(newnode)
return newnode
def visit_augassign(self, node, parent, assign_ctx=None):
"""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__] + "="
newnode.target = self.visit(node.target, newnode, "Assign")
newnode.value = self.visit(node.value, newnode, None)
return newnode
def visit_repr(self, node, parent, assign_ctx=None):
"""visit a Backquote node by returning a fresh instance of it"""
newnode = new.Repr()
_lineno_parent(node, newnode, parent)
newnode.value = self.visit(node.value, newnode, assign_ctx)
return newnode
def visit_binop(self, node, parent, assign_ctx=None):
"""visit a BinOp node by returning a fresh instance of it"""
if isinstance(node.left, _ast.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")
optimized = self._peepholer.optimize_binop(node)
if optimized:
_lineno_parent(node, optimized, parent)
return optimized
newnode = new.BinOp()
_lineno_parent(node, newnode, parent)
newnode.left = self.visit(node.left, newnode, assign_ctx)
newnode.right = self.visit(node.right, newnode, assign_ctx)
newnode.op = _BIN_OP_CLASSES[node.op.__class__]
return newnode
def visit_boolop(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
for child in node.values]
newnode.op = _BOOL_OP_CLASSES[node.op.__class__]
return newnode
def visit_break(self, node, parent, assign_ctx=None):
"""visit a Break node by returning a fresh instance of it"""
newnode = new.Break()
_set_infos(node, newnode, parent)
return newnode
def visit_call(self, node, parent, assign_ctx=None):
"""visit a CallFunc node by returning a fresh instance of it"""
newnode = new.Call()
_lineno_parent(node, newnode, parent)
newnode.func = self.visit(node.func, newnode, assign_ctx)
args = [self.visit(child, newnode, assign_ctx)
for child in node.args]
starargs = _visit_or_none(node, 'starargs', self, newnode,
assign_ctx)
kwargs = _visit_or_none(node, 'kwargs', self, newnode,
assign_ctx)
keywords = None
if node.keywords:
keywords = [self.visit(child, newnode, assign_ctx)
for child in node.keywords]
if starargs:
new_starargs = new.Starred()
new_starargs.col_offset = starargs.col_offset
new_starargs.lineno = starargs.lineno
new_starargs.parent = starargs.parent
new_starargs.value = starargs
args.append(new_starargs)
if kwargs:
new_kwargs = new.Keyword()
new_kwargs.arg = None
new_kwargs.col_offset = kwargs.col_offset
new_kwargs.lineno = kwargs.lineno
new_kwargs.parent = kwargs.parent
new_kwargs.value = kwargs
if keywords:
keywords.append(new_kwargs)
else:
keywords = [new_kwargs]
newnode.args = args
newnode.keywords = keywords
return newnode
def visit_classdef(self, node, parent, assign_ctx=None):
"""visit a Class node to become astroid"""
newnode = new.ClassDef(node.name, None)
_lineno_parent(node, newnode, parent)
_init_set_doc(node, newnode)
newnode.bases = [self.visit(child, newnode, assign_ctx)
for child in node.bases]
newnode.body = [self.visit(child, newnode, assign_ctx)
for child in node.body]
if node.decorator_list:
newnode.decorators = self.visit_decorators(node, newnode, assign_ctx)
newnode.parent.frame().set_local(newnode.name, newnode)
return newnode
def visit_const(self, node, parent, assign_ctx=None):
"""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, assign_ctx=None):
"""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, assign_ctx=None):
"""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, assign_ctx)
newnode.ops = [(_CMP_OP_CLASSES[op.__class__], self.visit(expr, newnode, assign_ctx))
for (op, expr) in zip(node.ops, node.comparators)]
return newnode
def visit_comprehension(self, node, parent, assign_ctx=None):
"""visit a Comprehension node by returning a fresh instance of it"""
newnode = new.Comprehension()
newnode.parent = parent
newnode.target = self.visit(node.target, newnode, 'Assign')
newnode.iter = self.visit(node.iter, newnode, None)
newnode.ifs = [self.visit(child, newnode, None)
for child in node.ifs]
return newnode
def visit_decorators(self, node, parent, assign_ctx=None):
"""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)
decorators = node.decorator_list
newnode.nodes = [self.visit(child, newnode, assign_ctx)
for child in decorators]
return newnode
def visit_delete(self, node, parent, assign_ctx=None):
"""visit a Delete node by returning a fresh instance of it"""
newnode = new.Delete()
_lineno_parent(node, newnode, parent)
newnode.targets = [self.visit(child, newnode, 'Del')
for child in node.targets]
return newnode
def _visit_dict_items(self, node, parent, newnode, assign_ctx):
for key, value in zip(node.keys, node.values):
rebuilt_value = self.visit(value, newnode, assign_ctx)
if not key:
# Python 3.5 and extended unpacking
rebuilt_key = new.DictUnpack()
rebuilt_key.lineno = rebuilt_value.lineno
rebuilt_key.col_offset = rebuilt_value.col_offset
rebuilt_key.parent = rebuilt_value.parent
else:
rebuilt_key = self.visit(key, newnode, assign_ctx)
yield rebuilt_key, rebuilt_value
def visit_dict(self, node, parent, assign_ctx=None):
"""visit a Dict node by returning a fresh instance of it"""
newnode = new.Dict()
_lineno_parent(node, newnode, parent)
newnode.items = list(self._visit_dict_items(node, parent, newnode, assign_ctx))
return newnode
def visit_dictcomp(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
newnode.value = self.visit(node.value, newnode, assign_ctx)
newnode.generators = [self.visit(child, newnode, assign_ctx)
for child in node.generators]
return newnode
def visit_expr(self, node, parent, assign_ctx=None):
"""visit a Discard node by returning a fresh instance of it"""
newnode = new.Expr()
_lineno_parent(node, newnode, parent)
newnode.value = self.visit(node.value, newnode, assign_ctx)
return newnode
def visit_ellipsis(self, node, parent, assign_ctx=None):
"""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, assign_ctx=None):
"""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, assign_ctx=None):
"""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, assign_ctx)
if node.name is not None:
# /!\ node.name can be a tuple
newnode.name = self.visit(node.name, newnode, 'Assign')
newnode.body = [self.visit(child, newnode, None)
for child in node.body]
return newnode
def visit_exec(self, node, parent, assign_ctx=None):
"""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,
assign_ctx)
if node.locals is not None:
newnode.locals = self.visit(node.locals, newnode,
assign_ctx)
return newnode
def visit_extslice(self, node, parent, assign_ctx=None):
"""visit an ExtSlice node by returning a fresh instance of it"""
newnode = new.ExtSlice()
newnode.parent = parent
newnode.dims = [self.visit(dim, newnode, assign_ctx)
for dim in node.dims]
return newnode
def _visit_for(self, cls, node, parent, assign_ctx=None):
"""visit a For node by returning a fresh instance of it"""
newnode = cls()
_lineno_parent(node, newnode, parent)
newnode.target = self.visit(node.target, newnode, "Assign")
newnode.iter = self.visit(node.iter, newnode, None)
newnode.body = [self.visit(child, newnode, None)
for child in node.body]
newnode.orelse = [self.visit(child, newnode, None)
for child in node.orelse]
return newnode
def visit_for(self, node, parent, assign_ctx=None):
return self._visit_for(new.For, node, parent,
assign_ctx=assign_ctx)
def visit_importfrom(self, node, parent, assign_ctx=None):
"""visit a From node by returning a fresh instance of it"""
names = [(alias.name, alias.asname) for alias in node.names]
newnode = new.ImportFrom(node.module or '', names, node.level or None)
_set_infos(node, newnode, parent)
# store From names to add them to locals after building
self._import_from_nodes.append(newnode)
return newnode
def _visit_functiondef(self, cls, node, parent, assign_ctx=None):
"""visit an FunctionDef node to become astroid"""
self._global_names.append({})
newnode = cls(node.name, None)
_lineno_parent(node, newnode, parent)
_init_set_doc(node, newnode)
newnode.args = self.visit(node.args, newnode, assign_ctx)
newnode.body = [self.visit(child, newnode, assign_ctx)
for child in node.body]
decorators = node.decorator_list
if decorators:
newnode.decorators = self.visit_decorators(
node, newnode, assign_ctx)
if PY3K and node.returns:
newnode.returns = self.visit(node.returns, newnode,
assign_ctx)
self._global_names.pop()
frame = newnode.parent.frame()
frame.set_local(newnode.name, newnode)
return newnode
def visit_functiondef(self, node, parent, assign_ctx=None):
return self._visit_functiondef(new.FunctionDef, node, parent,
assign_ctx=assign_ctx)
def visit_generatorexp(self, node, parent, assign_ctx=None):
"""visit a GenExpr node by returning a fresh instance of it"""
newnode = new.GeneratorExp()
_lineno_parent(node, newnode, parent)
newnode.elt = self.visit(node.elt, newnode, assign_ctx)
newnode.generators = [self.visit(child, newnode, assign_ctx)
for child in node.generators]
return newnode
def visit_attribute(self, node, parent, assign_ctx=None):
"""visit a Getattr node by returning a fresh instance of it"""
# pylint: disable=redefined-variable-type
if assign_ctx == "Del":
# FIXME : maybe we should reintroduce and visit_delattr ?
# for instance, deactivating asscontext
newnode = new.DelAttr()
elif assign_ctx == "Assign":
# FIXME : maybe we should call visit_assattr ?
newnode = new.AssignAttr()
self._delayed_assattr.append(newnode)
else:
newnode = new.Attribute()
_lineno_parent(node, newnode, parent)
newnode.expr = self.visit(node.value, newnode, None)
newnode.attrname = node.attr
return newnode
def visit_global(self, node, parent, assign_ctx=None):
"""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, assign_ctx=None):
"""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, assign_ctx)
newnode.body = [self.visit(child, newnode, assign_ctx)
for child in node.body]
newnode.orelse = [self.visit(child, newnode, assign_ctx)
for child in node.orelse]
return newnode
def visit_ifexp(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
newnode.body = self.visit(node.body, newnode, assign_ctx)
newnode.orelse = self.visit(node.orelse, newnode, assign_ctx)
return newnode
def visit_import(self, node, parent, assign_ctx=None):
"""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, assign_ctx=None):
"""visit a Index node by returning a fresh instance of it"""
newnode = new.Index()
newnode.parent = parent
newnode.value = self.visit(node.value, newnode, assign_ctx)
return newnode
def visit_keyword(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
return newnode
def visit_lambda(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
newnode.body = self.visit(node.body, newnode, assign_ctx)
return newnode
def visit_list(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
for child in node.elts]
return newnode
def visit_listcomp(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
newnode.generators = [self.visit(child, newnode, assign_ctx)
for child in node.generators]
return newnode
def visit_name(self, node, parent, assign_ctx=None):
"""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
# pylint: disable=redefined-variable-type
if assign_ctx == "Del":
newnode = new.DelName()
elif assign_ctx is not None: # 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 assign_ctx in ('Del', 'Assign'): # 'Aug' ??
self._save_assignment(newnode)
return newnode
def visit_bytes(self, node, parent, assign_ctx=None):
"""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, assign_ctx=None):
"""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, assign_ctx=None):
"""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, assign_ctx=None):
"""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, assign_ctx=None):
"""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, assign_ctx)
newnode.values = [self.visit(child, newnode, assign_ctx)
for child in node.values]
return newnode
def visit_raise(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
if node.inst is not None:
newnode.inst = self.visit(node.inst, newnode, assign_ctx)
if node.tback is not None:
newnode.tback = self.visit(node.tback, newnode, assign_ctx)
return newnode
def visit_return(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
return newnode
def visit_set(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
for child in node.elts]
return newnode
def visit_setcomp(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
newnode.generators = [self.visit(child, newnode, assign_ctx)
for child in node.generators]
return newnode
def visit_slice(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
if node.upper is not None:
newnode.upper = self.visit(node.upper, newnode, assign_ctx)
if node.step is not None:
newnode.step = self.visit(node.step, newnode, assign_ctx)
return newnode
def visit_subscript(self, node, parent, assign_ctx=None):
"""visit a Subscript node by returning a fresh instance of it"""
newnode = new.Subscript()
_lineno_parent(node, newnode, parent)
newnode.value = self.visit(node.value, newnode, None)
newnode.slice = self.visit(node.slice, newnode, None)
return newnode
def visit_tryexcept(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
for child in node.body]
newnode.handlers = [self.visit(child, newnode, assign_ctx)
for child in node.handlers]
newnode.orelse = [self.visit(child, newnode, assign_ctx)
for child in node.orelse]
return newnode
def visit_tryfinally(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
for child in node.body]
newnode.finalbody = [self.visit(n, newnode, assign_ctx)
for n in node.finalbody]
return newnode
def visit_tuple(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
for child in node.elts]
return newnode
def visit_unaryop(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
newnode.op = _UNARY_OP_CLASSES[node.op.__class__]
return newnode
def visit_while(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
newnode.body = [self.visit(child, newnode, assign_ctx)
for child in node.body]
newnode.orelse = [self.visit(child, newnode, assign_ctx)
for child in node.orelse]
return newnode
def visit_with(self, node, parent, assign_ctx=None):
newnode = new.With()
_lineno_parent(node, newnode, parent)
expr = self.visit(node.context_expr, newnode, assign_ctx)
if node.optional_vars is not None:
vars = self.visit(node.optional_vars, newnode, 'Assign')
else:
vars = None
self.asscontext = None
newnode.items = [(expr, vars)]
newnode.body = [self.visit(child, newnode, assign_ctx)
for child in node.body]
return newnode
def visit_yield(self, node, parent, assign_ctx=None):
"""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, assign_ctx=None):
"""visit a arg node by returning a fresh AssName instance"""
# TODO(cpopa): introduce an Arg node instead of using AssignName.
return self.visit_assignname(node, parent, assign_ctx, node.arg)
def visit_nameconstant(self, node, parent, assign_ctx=None):
# 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, assign_ctx=None):
newnode = super(TreeRebuilder3k, self).visit_arguments(node, parent, assign_ctx)
newnode.kwonlyargs = [self.visit(child, newnode, 'Assign')
for child in node.kwonlyargs]
newnode.kw_defaults = [self.visit(child, newnode, None)
if child else None for child in node.kw_defaults]
newnode.annotations = [
self.visit(arg.annotation, newnode, None) if arg.annotation else None
for arg in node.args]
return newnode
def visit_excepthandler(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
if node.name is not None:
newnode.name = self.visit_assignname(node, newnode, 'Assign', node.name)
newnode.body = [self.visit(child, newnode, None)
for child in node.body]
return newnode
def visit_nonlocal(self, node, parent, assign_ctx=None):
"""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, assign_ctx=None):
"""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, assign_ctx)
if node.cause is not None:
newnode.cause = self.visit(node.cause, newnode, assign_ctx)
return newnode
def visit_starred(self, node, parent, assign_ctx=None):
"""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, assign_ctx)
return newnode
def visit_try(self, node, parent, assign_ctx=None):
# python 3.3 introduce a new Try node replacing TryFinally/TryExcept nodes
# pylint: disable=redefined-variable-type
if node.finalbody:
newnode = new.TryFinally()
_lineno_parent(node, newnode, parent)
newnode.finalbody = [self.visit(n, newnode, assign_ctx)
for n in node.finalbody]
if node.handlers:
excnode = new.TryExcept()
_lineno_parent(node, excnode, newnode)
excnode.body = [self.visit(child, excnode, assign_ctx)
for child in node.body]
excnode.handlers = [self.visit(child, excnode, assign_ctx)
for child in node.handlers]
excnode.orelse = [self.visit(child, excnode, assign_ctx)
for child in node.orelse]
newnode.body = [excnode]
else:
newnode.body = [self.visit(child, newnode, assign_ctx)
for child in node.body]
elif node.handlers:
newnode = new.TryExcept()
_lineno_parent(node, newnode, parent)
newnode.body = [self.visit(child, newnode, assign_ctx)
for child in node.body]
newnode.handlers = [self.visit(child, newnode, assign_ctx)
for child in node.handlers]
newnode.orelse = [self.visit(child, newnode, assign_ctx)
for child in node.orelse]
return newnode
def _visit_with(self, cls, node, parent, assign_ctx=None):
if 'items' not in node._fields:
# python < 3.3
return super(TreeRebuilder3k, self).visit_with(node, parent,
assign_ctx)
newnode = cls()
_lineno_parent(node, newnode, parent)
def visit_child(child):
expr = self.visit(child.context_expr, newnode)
if child.optional_vars:
var = self.visit(child.optional_vars, newnode,
'Assign')
else:
var = None
return expr, var
newnode.items = [visit_child(child)
for child in node.items]
newnode.body = [self.visit(child, newnode, None)
for child in node.body]
return newnode
def visit_with(self, node, parent, assign_ctx=None):
return self._visit_with(new.With, node, parent, assign_ctx=assign_ctx)
def visit_yieldfrom(self, node, parent, assign_ctx=None):
return _create_yield_node(node, parent, self, new.YieldFrom)
def visit_classdef(self, node, parent, assign_ctx=None):
newnode = super(TreeRebuilder3k, self).visit_classdef(node, parent, assign_ctx)
newnode._newstyle = True
for keyword in node.keywords:
if keyword.arg == 'metaclass':
newnode._metaclass = self.visit(keyword, newnode, assign_ctx).value
break
return newnode
# Async structs added in Python 3.5
def visit_asyncfunctiondef(self, node, parent, assign_ctx=None):
return self._visit_functiondef(new.AsyncFunctionDef, node, parent,
assign_ctx=assign_ctx)
def visit_asyncfor(self, node, parent, assign_ctx=None):
return self._visit_for(new.AsyncFor, node, parent,
assign_ctx=assign_ctx)
def visit_await(self, node, parent, assign_ctx=None):
newnode = new.Await()
newnode.lineno = node.lineno
newnode.col_offset = node.col_offset
newnode.parent = parent
newnode.value = self.visit(node.value, newnode, None)
return newnode
def visit_asyncwith(self, node, parent, assign_ctx=None):
return self._visit_with(new.AsyncWith, node, parent,
assign_ctx=assign_ctx)
if sys.version_info >= (3, 0):
TreeRebuilder = TreeRebuilder3k
astroid-1.4.4/astroid/scoped_nodes.py 0000666 0000000 0000000 00000171245 12646222644 016025 0 ustar 0000000 0000000 # 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, ClassDef, FunctionDef (and
Lambda, GeneratorExp, DictComp and SetComp to some extent).
"""
import io
import itertools
import warnings
import six
import wrapt
from astroid import bases
from astroid import context as contextmod
from astroid import exceptions
from astroid import manager
from astroid import mixins
from astroid import node_classes
from astroid import decorators as decorators_mod
from astroid import util
BUILTINS = six.moves.builtins.__name__
ITER_METHODS = ('__iter__', '__getitem__')
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 exceptions.InconsistentMroError(
"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 exceptions.DuplicateBasesError('Duplicates found in the mro.')
def remove_nodes(cls):
@wrapt.decorator
def decorator(func, instance, args, kwargs):
nodes = [n for n in func(*args, **kwargs) if not isinstance(n, cls)]
if not nodes:
raise exceptions.NotFoundError()
return nodes
return decorator
def function_to_method(n, klass):
if isinstance(n, FunctionDef):
if n.type == 'classmethod':
return bases.BoundMethod(n, klass)
if n.type != 'staticmethod':
return bases.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 [node_classes.const_factory(self.name)] + locals.get(name, [])
if name == '__doc__':
return [node_classes.const_factory(self.doc)] + locals.get(name, [])
if name == '__dict__':
return [node_classes.Dict()] + locals.get(name, [])
raise exceptions.NotFoundError(name)
MANAGER = 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(six.moves.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: 'FunctionDef' in _scope_lookup
class LocalsDictNodeNG(node_classes.LookupMixIn, bases.NodeNG):
""" this class provides locals handling common to Module, FunctionDef
and ClassDef 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
@property
def locals(self):
util.attribute_to_function_warning('locals', 2.0, 'get_locals')
return self._locals
@locals.setter
def locals(self, _locals):
util.attribute_to_function_warning('locals', 2.0, 'get_locals')
self._locals = _locals
@locals.deleter
def locals(self):
util.attribute_to_function_warning('locals', 2.0, 'get_locals')
del self._locals
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, FunctionDef or ClassDef)
"""
return self
def scope(self):
"""return the first node defining a new scope (i.e. Module,
FunctionDef, ClassDef, Lambda but also GeneratorExp, 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 `FunctionDef` or `ClassDef`
"""
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 `FunctionDef` or `ClassDef`
"""
return list(zip(self.keys(), self.values()))
def __contains__(self, name):
return name in self._locals
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
source_file = None
# Alternatively, if built from a string/bytes, this can be set
source_code = 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()
# Future deprecation warnings
@property
def file(self):
util.rename_warning('file', 2.0, 'source_file')
return self.source_file
@file.setter
def file(self, source_file):
util.rename_warning('file', 2.0, 'source_file')
self.source_file = source_file
@file.deleter
def file(self):
util.rename_warning('file', 2.0, 'source_file')
del self.source_file
@property
def path(self):
util.rename_warning('path', 2.0, 'source_file')
return self.source_file
@path.setter
def path(self, source_file):
util.rename_warning('path', 2.0, 'source_file')
self.source_file = source_file
@path.deleter
def path(self):
util.rename_warning('path', 2.0, 'source_file')
del self.source_file
@property
def file_bytes(self):
util.rename_warning('file_bytes', 2.0, 'source_code')
return self.source_code
@file_bytes.setter
def file_bytes(self, source_code):
util.rename_warning('file_bytes', 2.0, 'source_code')
self.source_code = source_code
@file_bytes.deleter
def file_bytes(self):
util.rename_warning('file_bytes', 2.0, 'source_code')
del self.source_code
@property
def globals(self):
util.attribute_to_function_warning('globals', 2.0, 'get_locals')
return self._locals
@globals.setter
def globals(self, _globals):
util.attribute_to_function_warning('globals', 2.0, 'get_locals')
self._locals = _globals
@globals.deleter
def globals(self):
util.attribute_to_function_warning('globals', 2.0, 'get_locals')
del self._locals
@property
def future_imports(self):
util.attribute_to_function_warning('future_imports', 2.0, 'future_imports')
return self._future_imports
@future_imports.setter
def future_imports(self, _future_imports):
util.attribute_to_function_warning('future_imports', 2.0, 'future_imports')
self._future_imports = _future_imports
@future_imports.deleter
def future_imports(self):
util.attribute_to_function_warning('future_imports', 2.0, 'future_imports')
del self._future_imports
def _get_stream(self):
if self.source_code is not None:
return io.BytesIO(self.source_code)
if self.source_file is not None:
stream = open(self.source_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 name not in self._locals:
try:
return self, self.getattr(name)
except exceptions.NotFoundError:
return self, ()
return self._scope_lookup(node, name, offset)
def pytype(self):
return '%s.module' % BUILTINS
def display_type(self):
return 'Module'
@remove_nodes(node_classes.DelName)
def getattr(self, name, context=None, ignore_locals=False):
if name in self.special_attributes:
if name == '__file__':
return [node_classes.const_factory(self.source_file)] + self._locals.get(name, [])
if name == '__path__' and self.package:
return [node_classes.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 exceptions.AstroidBuildingException:
raise exceptions.NotFoundError(name)
except SyntaxError:
raise exceptions.NotFoundError(name)
raise exceptions.NotFoundError(name)
def igetattr(self, name, context=None):
"""inferred getattr"""
# set lookup name since this is necessary to infer on import nodes for
# instance
context = contextmod.copy_context(context)
context.lookupname = name
try:
return bases._infer_stmts(self.getattr(name, context),
context, frame=self)
except exceptions.NotFoundError:
raise exceptions.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.source_file is not None and self.source_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 six.PY2:
@decorators_mod.cachedproperty
def _absolute_import_activated(self):
for stmt in self._locals.get('absolute_import', ()):
if isinstance(stmt, node_classes.ImportFrom) 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 exceptions.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.
"""
# 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 exceptions.InferenceError:
return default
except AttributeError:
# not an assignment node
# XXX infer?
return default
# Try our best to detect the exported name.
inferred = []
try:
explicit = next(explicit.infer())
except exceptions.InferenceError:
return default
if not isinstance(explicit, (node_classes.Tuple, node_classes.List)):
return default
str_const = lambda node: (isinstance(node, node_classes.Const) and
isinstance(node.value, six.string_types))
for node in explicit.elts:
if str_const(node):
inferred.append(node.value)
else:
try:
inferred_node = next(node.infer())
except exceptions.InferenceError:
continue
if str_const(inferred_node):
inferred.append(inferred_node.value)
return inferred
def bool_value(self):
return True
class ComprehensionScope(LocalsDictNodeNG):
def frame(self):
return self.parent.frame()
scope_lookup = LocalsDictNodeNG._scope_lookup
class GeneratorExp(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(bases.NodeNG):
"""class representing a ListComp node"""
_astroid_fields = ('elt', 'generators')
elt = None
generators = None
if six.PY3:
class ListComp(_ListComp, ComprehensionScope):
"""class representing a ListComp node"""
def __init__(self):
self._locals = {}
else:
class ListComp(_ListComp):
"""class representing a ListComp node"""
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, FunctionDef):
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, exceptions.InferenceError):
return
if isinstance(result, bases.Instance):
result = result._proxied
if isinstance(result, ClassDef):
if result.is_subtype_of('%s.classmethod' % BUILTINS):
return 'classmethod'
if result.is_subtype_of('%s.staticmethod' % BUILTINS):
return 'staticmethod'
class Lambda(mixins.FilterStmtsMixin, LocalsDictNodeNG):
_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 FunctionDef(bases.Statement, Lambda):
if six.PY3:
_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
decorators = None
def __init__(self, name, doc):
self._locals = {}
self.args = []
self.body = []
self.name = name
self.doc = doc
self._instance_attrs = {}
@property
def instance_attrs(self):
util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes')
return self._instance_attrs
@instance_attrs.setter
def instance_attrs(self, _instance_attrs):
util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes')
self._instance_attrs = _instance_attrs
@instance_attrs.deleter
def instance_attrs(self):
util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes')
del self._instance_attrs
@decorators_mod.cachedproperty
def extra_decorators(self):
"""Get the extra decorators that this function can haves
Additional decorators are considered when they are used as
assignments, as in `method = staticmethod(method)`.
The property will return all the callables that are used for
decoration.
"""
frame = self.parent.frame()
if not isinstance(frame, ClassDef):
return []
decorators = []
for assign in frame.nodes_of_class(node_classes.Assign):
if (isinstance(assign.value, node_classes.Call)
and isinstance(assign.value.func, node_classes.Name)):
for assign_node in assign.targets:
if not isinstance(assign_node, node_classes.AssignName):
# Support only `name = callable(name)`
continue
if assign_node.name != self.name:
# Interested only in the assignment nodes that
# decorates the current method.
continue
try:
meth = frame[self.name]
except KeyError:
continue
else:
# Must be a function and in the same frame as the
# original method.
if (isinstance(meth, FunctionDef)
and assign_node.frame() == frame):
decorators.append(assign.value)
return decorators
@decorators_mod.cachedproperty
def type(self):
"""Get the function type for this node.
Possible values are: method, function, staticmethod, classmethod.
"""
builtin_descriptors = {'classmethod', 'staticmethod'}
for decorator in self.extra_decorators:
if decorator.func.name in builtin_descriptors:
return decorator.func.name
frame = self.parent.frame()
type_name = 'function'
if isinstance(frame, ClassDef):
if self.name == '__new__':
return 'classmethod'
else:
type_name = 'method'
if self.decorators:
for node in self.decorators.nodes:
if isinstance(node, node_classes.Name):
if node.name in builtin_descriptors:
return node.name
if isinstance(node, node_classes.Call):
# Handle the following case:
# @some_decorator(arg1, arg2)
# def func(...)
#
try:
current = next(node.func.infer())
except exceptions.InferenceError:
continue
_type = _infer_decorator_callchain(current)
if _type is not None:
return _type
try:
for inferred in node.infer():
# Check to see if this returns a static or a class method.
_type = _infer_decorator_callchain(inferred)
if _type is not None:
return _type
if not isinstance(inferred, ClassDef):
continue
for ancestor in inferred.ancestors():
if not isinstance(ancestor, ClassDef):
continue
if ancestor.is_subtype_of('%s.classmethod' % BUILTINS):
return 'classmethod'
elif ancestor.is_subtype_of('%s.staticmethod' % BUILTINS):
return 'staticmethod'
except exceptions.InferenceError:
pass
return type_name
@decorators_mod.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
@decorators_mod.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 [node_classes.const_factory(self.root().qname())]
if name in self._instance_attrs:
return self._instance_attrs[name]
return std_special_attributes(self, name, False)
def igetattr(self, name, context=None):
"""Inferred getattr, which returns an iterator of inferred statements."""
try:
return bases._infer_stmts(self.getattr(name, context),
context, frame=self)
except exceptions.NotFoundError:
raise exceptions.InferenceError(name)
def is_method(self):
"""return true if the function node should be considered as a method"""
# check we are defined in a ClassDef, because this is usually expected
# (e.g. pylint...) when is_method() return True
return self.type != 'function' and isinstance(self.parent.frame(), ClassDef)
@decorators_mod.cached
def decoratornames(self):
"""return a list of decorator qualified names"""
result = set()
decoratornodes = []
if self.decorators is not None:
# pylint: disable=unsupported-binary-operation; damn flow control.
decoratornodes += self.decorators.nodes
decoratornodes += self.extra_decorators
for decnode in decoratornodes:
for infnode in decnode.infer():
result.add(infnode.qname())
return result
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:
inferred = next(node.infer())
except exceptions.InferenceError:
continue
if inferred and inferred.qname() in ('abc.abstractproperty',
'abc.abstractmethod'):
return True
for child_node in self.body:
if isinstance(child_node, node_classes.Raise):
if child_node.raises_not_implemented():
return True
return pass_is_abstract and isinstance(child_node, node_classes.Pass)
# 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"""
yield_nodes = (node_classes.Yield, node_classes.YieldFrom)
return next(self.nodes_of_class(yield_nodes,
skip_klass=(FunctionDef, Lambda)), False)
def infer_call_result(self, caller, context=None):
"""infer what a function is returning when called"""
if self.is_generator():
result = bases.Generator()
result.parent = self
yield result
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, ClassDef):
c = ClassDef('temporary_class', None)
c.hide = True
c.parent = self
class_bases = [next(b.infer(context)) for b in caller.args[1:]]
c.bases = [base for base in class_bases if base != util.YES]
c._metaclass = metaclass
yield c
return
returns = self.nodes_of_class(node_classes.Return, skip_klass=FunctionDef)
for returnnode in returns:
if returnnode.value is None:
yield node_classes.Const(None)
else:
try:
for inferred in returnnode.value.infer(context):
yield inferred
except exceptions.InferenceError:
yield util.YES
class AsyncFunctionDef(FunctionDef):
"""Asynchronous function created with the `async` keyword."""
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, node_classes.Tuple):
_rec_get_names(arg.elts, names)
else:
names.append(arg.name)
return names
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():
baseobj_name = baseobj.qname()
if baseobj_name in seen:
continue
else:
seen.add(baseobj_name)
if isinstance(baseobj, bases.Instance):
# not abstract
return False
if baseobj is util.YES:
continue
if baseobj is klass:
continue
if not isinstance(baseobj, ClassDef):
continue
if baseobj._type == 'metaclass':
return True
if _is_metaclass(baseobj, seen):
return True
except exceptions.InferenceError:
continue
return False
def _class_type(klass, ancestors=None):
"""return a ClassDef node type to differ metaclass 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('Exception'):
klass._type = 'exception'
else:
if ancestors is None:
ancestors = set()
klass_name = klass.qname()
if klass_name in ancestors:
# XXX we are in loop ancestors, and have found no type
klass._type = 'class'
return 'class'
ancestors.add(klass_name)
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
class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG, bases.Statement):
# 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__'))
_type = None
_metaclass_hack = False
hide = False
type = property(_class_type,
doc="class'type, possible values are 'class' | "
"'metaclass' | 'exception'")
def __init__(self, name, doc):
self._instance_attrs = {}
self._locals = {}
self.bases = []
self.body = []
self.name = name
self.doc = doc
@property
def instance_attrs(self):
util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes')
return self._instance_attrs
@instance_attrs.setter
def instance_attrs(self, _instance_attrs):
util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes')
self._instance_attrs = _instance_attrs
@instance_attrs.deleter
def instance_attrs(self):
util.attribute_to_function_warning('instance_attrs', 2.0, 'get_attributes')
del self._instance_attrs
def _newstyle_impl(self, context=None):
if context is None:
context = contextmod.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, ClassDef):
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")
@decorators_mod.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_type_call(self, caller, context):
name_node = next(caller.args[0].infer(context))
if (isinstance(name_node, node_classes.Const) and
isinstance(name_node.value, six.string_types)):
name = name_node.value
else:
return util.YES
result = ClassDef(name, None)
# Get the bases of the class.
class_bases = next(caller.args[1].infer(context))
if isinstance(class_bases, (node_classes.Tuple, node_classes.List)):
result.bases = class_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.
return util.YES
# Get the members of the class
try:
members = next(caller.args[2].infer(context))
except exceptions.InferenceError:
members = None
if members and isinstance(members, node_classes.Dict):
for attr, value in members.items:
if (isinstance(attr, node_classes.Const) and
isinstance(attr.value, six.string_types)):
result._locals[attr.value] = [value]
result.parent = caller.parent
return result
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):
result = self._infer_type_call(caller, context)
yield result
else:
yield bases.Instance(self)
def scope_lookup(self, node, name, offset=0):
# pylint: disable=redefined-variable-type
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)
@property
def basenames(self):
"""Get the list of parent class names, as they appear in the class definition."""
return [bnode.as_string() for bnode in self.bases]
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 = contextmod.InferenceContext()
if six.PY3:
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, ClassDef):
if isinstance(baseobj, bases.Instance):
baseobj = baseobj._proxied
else:
continue
if not baseobj.hide:
if baseobj in yielded:
continue
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
yielded.add(grandpa)
yield grandpa
except exceptions.InferenceError:
continue
def local_attr_ancestors(self, name, context=None):
"""return an iterator on astroid representation of parent classes
which have defined in their locals
"""
if self.newstyle and all(n.newstyle for n in self.ancestors(context)):
# Look up in the mro if we can. This will result in the
# attribute being looked up just as Python does it.
try:
ancestors = self.mro(context)[1:]
except exceptions.MroError:
# Fallback to use ancestors, we can't determine
# a sane MRO.
ancestors = self.ancestors(context=context)
else:
ancestors = self.ancestors(context=context)
for astroid in ancestors:
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
@remove_nodes(node_classes.DelAttr)
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:
for class_node in self.local_attr_ancestors(name, context):
return class_node._locals[name]
raise exceptions.NotFoundError(name)
@remove_nodes(node_classes.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 exceptions.NotFoundError(name)
return values
def instantiate_class(self):
"""return Instance of ClassDef node, else return self"""
return bases.Instance(self)
def instanciate_class(self):
"""return Instance of ClassDef node, else return self"""
util.rename_warning('instanciate_class()', 2.0, 'instantiate_class()')
return self.instantiate_class()
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 [node_classes.const_factory(self.root().qname())] + values
if name == '__bases__':
node = node_classes.Tuple()
elts = list(self._inferred_bases(context))
node.elts = elts
return [node] + values
if name == '__mro__' and self.newstyle:
mro = self.mro()
node = node_classes.Tuple()
node.elts = mro
return [node]
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 exceptions.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 = contextmod.copy_context(context)
context.lookupname = name
try:
for inferred in bases._infer_stmts(self.getattr(name, context),
context, frame=self):
# yield YES object instead of descriptors when necessary
if (not isinstance(inferred, node_classes.Const)
and isinstance(inferred, bases.Instance)):
try:
inferred._proxied.getattr('__get__', context)
except exceptions.NotFoundError:
yield inferred
else:
yield util.YES
else:
yield function_to_method(inferred, self)
except exceptions.NotFoundError:
if not name.startswith('__') and self.has_dynamic_getattr(context):
# class handle some dynamic attributes, return a YES object
yield util.YES
else:
raise exceptions.InferenceError(name)
def has_dynamic_getattr(self, context=None):
"""
Check if the current instance has a custom __getattr__
or a custom __getattribute__.
If any such method is found and it is not from
builtins, nor from an extension module, then the function
will return True.
"""
def _valid_getattr(node):
root = node.root()
return root.name != BUILTINS and getattr(root, 'pure_python', None)
try:
return _valid_getattr(self.getattr('__getattr__', context)[0])
except exceptions.NotFoundError:
#if self.newstyle: XXX cause an infinite recursion error
try:
getattribute = self.getattr('__getattribute__', context)[0]
return _valid_getattr(getattribute)
except exceptions.NotFoundError:
pass
return False
def methods(self):
"""return an iterator on all methods defined in the class and
its ancestors
"""
done = {}
for astroid in itertools.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, FunctionDef):
yield member
def implicit_metaclass(self):
"""Get the implicit metaclass of the current class
For newstyle classes, this will return an instance of builtins.type.
For oldstyle classes, it will simply return None, since there's
no implicit metaclass there.
"""
if self.newstyle:
return builtin_lookup('type')[1][0]
_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, ClassDef) and baseobj.hide:
self._metaclass = baseobj._metaclass
self._metaclass_hack = True
break
except exceptions.InferenceError:
pass
if self._metaclass:
# Expects this from Py3k TreeRebuilder
try:
return next(node for node in self._metaclass.infer()
if node is not util.YES)
except (exceptions.InferenceError, StopIteration):
return None
if six.PY3:
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:
inferred = next(assignment.infer())
except exceptions.InferenceError:
return
if inferred is util.YES: # don't expose this
return None
return inferred
def _find_metaclass(self, seen=None):
if seen is None:
seen = set()
seen.add(self)
klass = self._explicit_metaclass()
if klass is None:
for parent in self.ancestors():
if parent not in seen:
klass = parent._find_metaclass(seen)
if klass is not None:
break
return klass
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.
"""
return self._find_metaclass()
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 exceptions.NotFoundError:
continue
else:
continue
if isinstance(slots, node_classes.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, node_classes.Dict):
values = [item[0] for item in slots.items]
else:
values = slots.itered()
if values is util.YES:
continue
if not values:
# Stop the iteration, because the class
# has an empty list of slots.
raise StopIteration(values)
for elt in values:
try:
for inferred in elt.infer():
if inferred is util.YES:
continue
if (not isinstance(inferred, node_classes.Const) or
not isinstance(inferred.value,
six.string_types)):
continue
if not inferred.value:
continue
yield inferred
except exceptions.InferenceError:
continue
def _slots(self):
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 as exc:
# The class doesn't have a __slots__ definition or empty slots.
if exc.args and exc.args[0] not in ('', None):
return exc.args[0]
return None
# pylint: disable=unsupported-binary-operation; false positive
return [first] + list(slots)
# Cached, because inferring them all the time is expensive
@decorators_mod.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.
"""
def grouped_slots():
# Not interested in object, since it can't have slots.
for cls in self.mro()[:-1]:
try:
cls_slots = cls._slots()
except NotImplementedError:
continue
if cls_slots is not None:
for slot in cls_slots:
yield slot
else:
yield None
if not self.newstyle:
raise NotImplementedError(
"The concept of slots is undefined for old-style classes.")
slots = list(grouped_slots())
if not all(slot is not None for slot in slots):
return None
return sorted(slots, key=lambda item: item.value)
def _inferred_bases(self, 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 = contextmod.InferenceContext()
if six.PY3:
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 exceptions.InferenceError:
continue
if isinstance(baseobj, bases.Instance):
baseobj = baseobj._proxied
if not isinstance(baseobj, ClassDef):
continue
if not baseobj.hide:
yield baseobj
else:
for base in baseobj.bases:
yield base
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))
bases_mro = []
for base in bases:
try:
mro = base.mro(context=context)
bases_mro.append(mro)
except NotImplementedError:
# Some classes have in their ancestors both newstyle and
# old style classes. For these we can't retrieve the .mro,
# although in Python it's possible, since the class we are
# currently working is in fact new style.
# So, we fallback to ancestors here.
ancestors = list(base.ancestors(context=context))
bases_mro.append(ancestors)
unmerged_mro = ([[self]] + bases_mro + [bases])
_verify_duplicates_mro(unmerged_mro)
return _c3_merge(unmerged_mro)
def get_locals(node):
'''Stub function for forwards compatibility.'''
return node._locals
def get_attributes(node):
'''Stub function for forwards compatibility.'''
return node._instance_attrs
# Backwards-compatibility aliases
Class = node_classes.proxy_alias('Class', ClassDef)
Function = node_classes.proxy_alias('Function', FunctionDef)
GenExpr = node_classes.proxy_alias('GenExpr', GeneratorExp)
astroid-1.4.4/astroid/tests/ 0000777 0000000 0000000 00000000000 12646224174 014136 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/resources.py 0000666 0000000 0000000 00000004504 12646170047 016524 0 ustar 0000000 0000000 # 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
astroid-1.4.4/astroid/tests/testdata/ 0000777 0000000 0000000 00000000000 12646224174 015747 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/ 0000777 0000000 0000000 00000000000 12646224174 017352 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/ 0000777 0000000 0000000 00000000000 12646224174 020263 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/absimp/ 0000777 0000000 0000000 00000000000 12646224174 021536 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/absimp/sidepackage/ 0000777 0000000 0000000 00000000000 12646224174 023776 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py 0000666 0000000 0000000 00000000052 12632317503 026076 0 ustar 0000000 0000000 """a side package with nothing in it
"""
astroid-1.4.4/astroid/tests/testdata/python2/data/absimp/string.py 0000666 0000000 0000000 00000000123 12632317503 023404 0 ustar 0000000 0000000 from __future__ import absolute_import, print_function
import string
print(string)
astroid-1.4.4/astroid/tests/testdata/python2/data/absimp/__init__.py 0000666 0000000 0000000 00000000131 12632317503 023634 0 ustar 0000000 0000000 """a package with absolute import activated
"""
from __future__ import absolute_import
astroid-1.4.4/astroid/tests/testdata/python2/data/absimport.py 0000666 0000000 0000000 00000000116 12632317503 022625 0 ustar 0000000 0000000 from __future__ import absolute_import
import email
from email import message
astroid-1.4.4/astroid/tests/testdata/python2/data/all.py 0000666 0000000 0000000 00000000152 12632317503 021375 0 ustar 0000000 0000000
name = 'a'
_bla = 2
other = 'o'
class Aaa: pass
def func(): print 'yo'
__all__ = 'Aaa', '_bla', 'name'
astroid-1.4.4/astroid/tests/testdata/python2/data/appl/ 0000777 0000000 0000000 00000000000 12646224174 021217 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/appl/myConnection.py 0000666 0000000 0000000 00000000457 12640766772 024255 0 ustar 0000000 0000000 from __future__ import print_function
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...')
astroid-1.4.4/astroid/tests/testdata/python2/data/appl/__init__.py 0000666 0000000 0000000 00000000015 12632317503 023316 0 ustar 0000000 0000000 """
Init
"""
astroid-1.4.4/astroid/tests/testdata/python2/data/clientmodule_test.py 0000666 0000000 0000000 00000001440 12646222644 024357 0 ustar 0000000 0000000 """ 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()
astroid-1.4.4/astroid/tests/testdata/python2/data/descriptor_crash.py 0000666 0000000 0000000 00000000331 12632317503 024162 0 ustar 0000000 0000000
import urllib
class Page(object):
_urlOpen = staticmethod(urllib.urlopen)
def getPage(self, url):
handle = self._urlOpen(url)
data = handle.read()
handle.close()
return data
astroid-1.4.4/astroid/tests/testdata/python2/data/email.py 0000666 0000000 0000000 00000000106 12632317503 021713 0 ustar 0000000 0000000 """fake email module to test absolute import doesn't grab this one"""
astroid-1.4.4/astroid/tests/testdata/python2/data/find_test/ 0000777 0000000 0000000 00000000000 12646224174 022242 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/find_test/module.py 0000666 0000000 0000000 00000000000 12632317503 024061 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/find_test/module2.py 0000666 0000000 0000000 00000000000 12632317503 024143 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/find_test/noendingnewline.py 0000666 0000000 0000000 00000000000 12632317503 025757 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/find_test/nonregr.py 0000666 0000000 0000000 00000000000 12632317503 024246 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/find_test/__init__.py 0000666 0000000 0000000 00000000000 12632317503 024333 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/format.py 0000666 0000000 0000000 00000000645 12632317503 022124 0 ustar 0000000 0000000 """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();
astroid-1.4.4/astroid/tests/testdata/python2/data/joined_strings.py 0000666 0000000 0000000 00000214750 12646170047 023666 0 ustar 0000000 0000000 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') astroid-1.4.4/astroid/tests/testdata/python2/data/lmfp/ 0000777 0000000 0000000 00000000000 12646224174 021221 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/lmfp/foo.py 0000666 0000000 0000000 00000000252 12632317503 022347 0 ustar 0000000 0000000 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)
astroid-1.4.4/astroid/tests/testdata/python2/data/lmfp/__init__.py 0000666 0000000 0000000 00000000063 12632317503 023323 0 ustar 0000000 0000000 # force a "direct" python import
from . import foo
astroid-1.4.4/astroid/tests/testdata/python2/data/module.py 0000666 0000000 0000000 00000003414 12646170047 022123 0 ustar 0000000 0000000 """test module for astroid
"""
__revision__ = '$Id: module.py,v 1.2 2005-11-02 11:56:54 syt Exp $'
from astroid.node_classes import Name as NameNode
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:
return local
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:
return b
else:
if a in autre:
return a
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)"""
pass
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
astroid-1.4.4/astroid/tests/testdata/python2/data/module1abs/ 0000777 0000000 0000000 00000000000 12646224174 022317 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/module1abs/core.py 0000666 0000000 0000000 00000000013 12632317503 023605 0 ustar 0000000 0000000 import sys
astroid-1.4.4/astroid/tests/testdata/python2/data/module1abs/__init__.py 0000666 0000000 0000000 00000000161 12632317503 024420 0 ustar 0000000 0000000 from __future__ import absolute_import, print_function
from . import core
from .core import *
print(sys.version)
astroid-1.4.4/astroid/tests/testdata/python2/data/module2.py 0000666 0000000 0000000 00000003650 12632317503 022202 0 ustar 0000000 0000000 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
astroid-1.4.4/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg 0000666 0000000 0000000 00000002306 12632317503 023426 0 ustar 0000000 0000000 PK Ay:5\Bã‚ ¢ mypypa/__init__.pycÛü‰—+êÆIÏd(`b .æ)Q@’‘!Xƒ $Æ$ôý4@ªJ¸D||YjQqf~^|¼H;‚(ÖI¥™9)úI)™Å%z9™y¥º™ffú©ééú¹••‰úññ™y™%ññz•Å@6¹ù)¥9©v ŠAæ PK Ay:ê\sj mypypa/__init__.py‹/K-*ÎÌÏ‹W°UP7Ð3Tç PK Ay:K–Œ“[ Ž EGG-INFO/SOURCES.txt+N-)-Ð+¨äÒÓÏÌË,‰ñ|+*õRÓÓu3óÒòõ¼Ýu=ýÜü1$‚ýCƒœ]ƒõJ*J0äRRRóRRó’+ãs2󲋱**É/ˆÏI-KÍÉ PK Ay:#z| EGG-INFO/top_level.txtË,¨,Hä PK Ay:“×2 EGG-INFO/dependency_links.txtã PK Ay:“×2 EGG-INFO/zip-safeã PK Ay:ÂSA4~ · EGG-INFO/PKG-INFOóM-ILI,IÔ
K-*ÎÌϳR0Ô3àòKÌMµRð¨Hä‚Ëèä‚Kss‹*RòòòK22óÒ¹<òsSuÓšBý¼ýüÃý¸KK2ò‹Ðùº©¹‰™9QŸÌäÔ¼b$m.©ÅÉE™%`a‚9‰%iùE¹ PK Ay:5\Bã‚ ¢ ¤ mypypa/__init__.pycPK Ay:ê\sj ¤³ mypypa/__init__.pyPK Ay:K–Œ“[ Ž ¤ù EGG-INFO/SOURCES.txtPK Ay:#z| ¤† EGG-INFO/top_level.txtPK Ay:“×2 ¤Ã EGG-INFO/dependency_links.txtPK Ay:“×2 ¤ EGG-INFO/zip-safePK Ay:ÂSA4~ · ¤3 EGG-INFO/PKG-INFOPK Ð à astroid-1.4.4/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip 0000666 0000000 0000000 00000002306 12632317503 023466 0 ustar 0000000 0000000 PK Ay:5\Bã‚ ¢ mypypa/__init__.pycÛü‰—+êÆIÏd(`b .æ)Q@’‘!Xƒ $Æ$ôý4@ªJ¸D||YjQqf~^|¼H;‚(ÖI¥™9)úI)™Å%z9™y¥º™ffú©ééú¹••‰úññ™y™%ññz•Å@6¹ù)¥9©v ŠAæ PK Ay:ê\sj mypypa/__init__.py‹/K-*ÎÌÏ‹W°UP7Ð3Tç PK Ay:K–Œ“[ Ž EGG-INFO/SOURCES.txt+N-)-Ð+¨äÒÓÏÌË,‰ñ|+*õRÓÓu3óÒòõ¼Ýu=ýÜü1$‚ýCƒœ]ƒõJ*J0äRRRóRRó’+ãs2󲋱**É/ˆÏI-KÍÉ PK Ay:#z| EGG-INFO/top_level.txtË,¨,Hä PK Ay:“×2 EGG-INFO/dependency_links.txtã PK Ay:“×2 EGG-INFO/zip-safeã PK Ay:ÂSA4~ · EGG-INFO/PKG-INFOóM-ILI,IÔ
K-*ÎÌϳR0Ô3àòKÌMµRð¨Hä‚Ëèä‚Kss‹*RòòòK22óÒ¹<òsSuÓšBý¼ýüÃý¸KK2ò‹Ðùº©¹‰™9QŸÌäÔ¼b$m.©ÅÉE™%`a‚9‰%iùE¹ PK Ay:5\Bã‚ ¢ ¤ mypypa/__init__.pycPK Ay:ê\sj ¤³ mypypa/__init__.pyPK Ay:K–Œ“[ Ž ¤ù EGG-INFO/SOURCES.txtPK Ay:#z| ¤† EGG-INFO/top_level.txtPK Ay:“×2 ¤Ã EGG-INFO/dependency_links.txtPK Ay:“×2 ¤ EGG-INFO/zip-safePK Ay:ÂSA4~ · ¤3 EGG-INFO/PKG-INFOPK Ð à astroid-1.4.4/astroid/tests/testdata/python2/data/noendingnewline.py 0000666 0000000 0000000 00000000767 12632317503 024024 0 ustar 0000000 0000000 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()
astroid-1.4.4/astroid/tests/testdata/python2/data/nonregr.py 0000666 0000000 0000000 00000002176 12632317503 022307 0 ustar 0000000 0000000 from __future__ import generators, print_function
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
astroid-1.4.4/astroid/tests/testdata/python2/data/notall.py 0000666 0000000 0000000 00000000112 12646222644 022120 0 ustar 0000000 0000000 name = 'a'
_bla = 2
other = 'o'
class Aaa: pass
def func(): print('yo')
astroid-1.4.4/astroid/tests/testdata/python2/data/package/ 0000777 0000000 0000000 00000000000 12646224174 021656 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/package/absimport.py 0000666 0000000 0000000 00000000254 12632317503 024223 0 ustar 0000000 0000000 from __future__ import absolute_import, print_function
import import_package_subpackage_module # fail
print(import_package_subpackage_module)
from . import hello as hola
astroid-1.4.4/astroid/tests/testdata/python2/data/package/hello.py 0000666 0000000 0000000 00000000024 12632317503 023321 0 ustar 0000000 0000000 """hello module"""
astroid-1.4.4/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py 0000666 0000000 0000000 00000004302 12632317503 030740 0 ustar 0000000 0000000 # 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
astroid-1.4.4/astroid/tests/testdata/python2/data/package/subpackage/ 0000777 0000000 0000000 00000000000 12646224174 023763 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/package/subpackage/module.py 0000666 0000000 0000000 00000000040 12632317503 025606 0 ustar 0000000 0000000 """package.subpackage.module"""
astroid-1.4.4/astroid/tests/testdata/python2/data/package/subpackage/__init__.py 0000666 0000000 0000000 00000000031 12632317503 026060 0 ustar 0000000 0000000 """package.subpackage"""
astroid-1.4.4/astroid/tests/testdata/python2/data/package/__init__.py 0000666 0000000 0000000 00000000071 12632317503 023757 0 ustar 0000000 0000000 """package's __init__ file"""
from . import subpackage
astroid-1.4.4/astroid/tests/testdata/python2/data/recursion.py 0000666 0000000 0000000 00000000064 12632317503 022640 0 ustar 0000000 0000000 """ For issue #25 """
class Base(object):
pass astroid-1.4.4/astroid/tests/testdata/python2/data/SSL1/ 0000777 0000000 0000000 00000000000 12646224174 021005 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/SSL1/Connection1.py 0000666 0000000 0000000 00000000527 12632317503 023535 0 ustar 0000000 0000000 """M2Crypto.SSL.Connection
Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved."""
from __future__ import print_function
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')
astroid-1.4.4/astroid/tests/testdata/python2/data/SSL1/__init__.py 0000666 0000000 0000000 00000000043 12632317503 023105 0 ustar 0000000 0000000 from Connection1 import Connection
astroid-1.4.4/astroid/tests/testdata/python2/data/suppliermodule_test.py 0000666 0000000 0000000 00000000354 12646222644 024747 0 ustar 0000000 0000000 """ 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
astroid-1.4.4/astroid/tests/testdata/python2/data/unicode_package/ 0000777 0000000 0000000 00000000000 12646224174 023364 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/unicode_package/core/ 0000777 0000000 0000000 00000000000 12646224174 024314 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/unicode_package/core/__init__.py 0000666 0000000 0000000 00000000000 12632317503 026405 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python2/data/unicode_package/__init__.py 0000666 0000000 0000000 00000000021 12632317503 025460 0 ustar 0000000 0000000 x = "șțîâ" astroid-1.4.4/astroid/tests/testdata/python2/data/__init__.py 0000666 0000000 0000000 00000000104 12632317503 022361 0 ustar 0000000 0000000 __revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $"
astroid-1.4.4/astroid/tests/testdata/python3/ 0000777 0000000 0000000 00000000000 12646224174 017353 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/ 0000777 0000000 0000000 00000000000 12646224174 020264 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/absimp/ 0000777 0000000 0000000 00000000000 12646224174 021537 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/absimp/sidepackage/ 0000777 0000000 0000000 00000000000 12646224174 023777 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py 0000666 0000000 0000000 00000000052 12632317503 026077 0 ustar 0000000 0000000 """a side package with nothing in it
"""
astroid-1.4.4/astroid/tests/testdata/python3/data/absimp/string.py 0000666 0000000 0000000 00000000123 12632317503 023405 0 ustar 0000000 0000000 from __future__ import absolute_import, print_function
import string
print(string)
astroid-1.4.4/astroid/tests/testdata/python3/data/absimp/__init__.py 0000666 0000000 0000000 00000000131 12632317503 023635 0 ustar 0000000 0000000 """a package with absolute import activated
"""
from __future__ import absolute_import
astroid-1.4.4/astroid/tests/testdata/python3/data/absimport.py 0000666 0000000 0000000 00000000050 12632317503 022623 0 ustar 0000000 0000000
import email
from email import message
astroid-1.4.4/astroid/tests/testdata/python3/data/all.py 0000666 0000000 0000000 00000000153 12632317503 021377 0 ustar 0000000 0000000
name = 'a'
_bla = 2
other = 'o'
class Aaa: pass
def func(): print('yo')
__all__ = 'Aaa', '_bla', 'name'
astroid-1.4.4/astroid/tests/testdata/python3/data/appl/ 0000777 0000000 0000000 00000000000 12646224174 021220 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/appl/myConnection.py 0000666 0000000 0000000 00000000405 12632317503 024230 0 ustar 0000000 0000000 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...')
astroid-1.4.4/astroid/tests/testdata/python3/data/appl/__init__.py 0000666 0000000 0000000 00000000015 12632317503 023317 0 ustar 0000000 0000000 """
Init
"""
astroid-1.4.4/astroid/tests/testdata/python3/data/clientmodule_test.py 0000666 0000000 0000000 00000001440 12646222644 024360 0 ustar 0000000 0000000 """ 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()
astroid-1.4.4/astroid/tests/testdata/python3/data/descriptor_crash.py 0000666 0000000 0000000 00000000331 12632317503 024163 0 ustar 0000000 0000000
import urllib
class Page(object):
_urlOpen = staticmethod(urllib.urlopen)
def getPage(self, url):
handle = self._urlOpen(url)
data = handle.read()
handle.close()
return data
astroid-1.4.4/astroid/tests/testdata/python3/data/email.py 0000666 0000000 0000000 00000000106 12632317503 021714 0 ustar 0000000 0000000 """fake email module to test absolute import doesn't grab this one"""
astroid-1.4.4/astroid/tests/testdata/python3/data/find_test/ 0000777 0000000 0000000 00000000000 12646224174 022243 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/find_test/module.py 0000666 0000000 0000000 00000000000 12632317503 024062 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/find_test/module2.py 0000666 0000000 0000000 00000000000 12632317503 024144 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/find_test/noendingnewline.py 0000666 0000000 0000000 00000000000 12632317503 025760 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/find_test/nonregr.py 0000666 0000000 0000000 00000000000 12632317503 024247 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/find_test/__init__.py 0000666 0000000 0000000 00000000000 12632317503 024334 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/format.py 0000666 0000000 0000000 00000000645 12632317503 022125 0 ustar 0000000 0000000 """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();
astroid-1.4.4/astroid/tests/testdata/python3/data/joined_strings.py 0000666 0000000 0000000 00000214750 12646170047 023667 0 ustar 0000000 0000000 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') astroid-1.4.4/astroid/tests/testdata/python3/data/lmfp/ 0000777 0000000 0000000 00000000000 12646224174 021222 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/lmfp/foo.py 0000666 0000000 0000000 00000000252 12632317503 022350 0 ustar 0000000 0000000 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)
astroid-1.4.4/astroid/tests/testdata/python3/data/lmfp/__init__.py 0000666 0000000 0000000 00000000063 12632317503 023324 0 ustar 0000000 0000000 # force a "direct" python import
from . import foo
astroid-1.4.4/astroid/tests/testdata/python3/data/module.py 0000666 0000000 0000000 00000003407 12646170047 022126 0 ustar 0000000 0000000 """test module for astroid
"""
__revision__ = '$Id: module.py,v 1.2 2005-11-02 11:56:54 syt Exp $'
from astroid.node_classes import Name as NameNode
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:
return
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:
return
else:
if a in autre:
return '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)"""
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
astroid-1.4.4/astroid/tests/testdata/python3/data/module1abs/ 0000777 0000000 0000000 00000000000 12646224174 022320 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/module1abs/core.py 0000666 0000000 0000000 00000000013 12632317503 023606 0 ustar 0000000 0000000 import sys
astroid-1.4.4/astroid/tests/testdata/python3/data/module1abs/__init__.py 0000666 0000000 0000000 00000000073 12632317503 024423 0 ustar 0000000 0000000
from . import core
from .core import *
print(sys.version)
astroid-1.4.4/astroid/tests/testdata/python3/data/module2.py 0000666 0000000 0000000 00000003672 12646222644 022215 0 ustar 0000000 0000000 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
astroid-1.4.4/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg 0000666 0000000 0000000 00000002306 12632317503 023427 0 ustar 0000000 0000000 PK Ay:5\Bã‚ ¢ mypypa/__init__.pycÛü‰—+êÆIÏd(`b .æ)Q@’‘!Xƒ $Æ$ôý4@ªJ¸D||YjQqf~^|¼H;‚(ÖI¥™9)úI)™Å%z9™y¥º™ffú©ééú¹••‰úññ™y™%ññz•Å@6¹ù)¥9©v ŠAæ PK Ay:ê\sj mypypa/__init__.py‹/K-*ÎÌÏ‹W°UP7Ð3Tç PK Ay:K–Œ“[ Ž EGG-INFO/SOURCES.txt+N-)-Ð+¨äÒÓÏÌË,‰ñ|+*õRÓÓu3óÒòõ¼Ýu=ýÜü1$‚ýCƒœ]ƒõJ*J0äRRRóRRó’+ãs2󲋱**É/ˆÏI-KÍÉ PK Ay:#z| EGG-INFO/top_level.txtË,¨,Hä PK Ay:“×2 EGG-INFO/dependency_links.txtã PK Ay:“×2 EGG-INFO/zip-safeã PK Ay:ÂSA4~ · EGG-INFO/PKG-INFOóM-ILI,IÔ
K-*ÎÌϳR0Ô3àòKÌMµRð¨Hä‚Ëèä‚Kss‹*RòòòK22óÒ¹<òsSuÓšBý¼ýüÃý¸KK2ò‹Ðùº©¹‰™9QŸÌäÔ¼b$m.©ÅÉE™%`a‚9‰%iùE¹ PK Ay:5\Bã‚ ¢ ¤ mypypa/__init__.pycPK Ay:ê\sj ¤³ mypypa/__init__.pyPK Ay:K–Œ“[ Ž ¤ù EGG-INFO/SOURCES.txtPK Ay:#z| ¤† EGG-INFO/top_level.txtPK Ay:“×2 ¤Ã EGG-INFO/dependency_links.txtPK Ay:“×2 ¤ EGG-INFO/zip-safePK Ay:ÂSA4~ · ¤3 EGG-INFO/PKG-INFOPK Ð à astroid-1.4.4/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip 0000666 0000000 0000000 00000002306 12632317503 023467 0 ustar 0000000 0000000 PK Ay:5\Bã‚ ¢ mypypa/__init__.pycÛü‰—+êÆIÏd(`b .æ)Q@’‘!Xƒ $Æ$ôý4@ªJ¸D||YjQqf~^|¼H;‚(ÖI¥™9)úI)™Å%z9™y¥º™ffú©ééú¹••‰úññ™y™%ññz•Å@6¹ù)¥9©v ŠAæ PK Ay:ê\sj mypypa/__init__.py‹/K-*ÎÌÏ‹W°UP7Ð3Tç PK Ay:K–Œ“[ Ž EGG-INFO/SOURCES.txt+N-)-Ð+¨äÒÓÏÌË,‰ñ|+*õRÓÓu3óÒòõ¼Ýu=ýÜü1$‚ýCƒœ]ƒõJ*J0äRRRóRRó’+ãs2󲋱**É/ˆÏI-KÍÉ PK Ay:#z| EGG-INFO/top_level.txtË,¨,Hä PK Ay:“×2 EGG-INFO/dependency_links.txtã PK Ay:“×2 EGG-INFO/zip-safeã PK Ay:ÂSA4~ · EGG-INFO/PKG-INFOóM-ILI,IÔ
K-*ÎÌϳR0Ô3àòKÌMµRð¨Hä‚Ëèä‚Kss‹*RòòòK22óÒ¹<òsSuÓšBý¼ýüÃý¸KK2ò‹Ðùº©¹‰™9QŸÌäÔ¼b$m.©ÅÉE™%`a‚9‰%iùE¹ PK Ay:5\Bã‚ ¢ ¤ mypypa/__init__.pycPK Ay:ê\sj ¤³ mypypa/__init__.pyPK Ay:K–Œ“[ Ž ¤ù EGG-INFO/SOURCES.txtPK Ay:#z| ¤† EGG-INFO/top_level.txtPK Ay:“×2 ¤Ã EGG-INFO/dependency_links.txtPK Ay:“×2 ¤ EGG-INFO/zip-safePK Ay:ÂSA4~ · ¤3 EGG-INFO/PKG-INFOPK Ð à astroid-1.4.4/astroid/tests/testdata/python3/data/noendingnewline.py 0000666 0000000 0000000 00000000772 12632317503 024021 0 ustar 0000000 0000000 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()
astroid-1.4.4/astroid/tests/testdata/python3/data/nonregr.py 0000666 0000000 0000000 00000002115 12632317503 022301 0 ustar 0000000 0000000
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
astroid-1.4.4/astroid/tests/testdata/python3/data/notall.py 0000666 0000000 0000000 00000000113 12632317503 022114 0 ustar 0000000 0000000
name = 'a'
_bla = 2
other = 'o'
class Aaa: pass
def func(): print('yo')
astroid-1.4.4/astroid/tests/testdata/python3/data/package/ 0000777 0000000 0000000 00000000000 12646224174 021657 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/package/absimport.py 0000666 0000000 0000000 00000000254 12632317503 024224 0 ustar 0000000 0000000 from __future__ import absolute_import, print_function
import import_package_subpackage_module # fail
print(import_package_subpackage_module)
from . import hello as hola
astroid-1.4.4/astroid/tests/testdata/python3/data/package/hello.py 0000666 0000000 0000000 00000000024 12632317503 023322 0 ustar 0000000 0000000 """hello module"""
astroid-1.4.4/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py 0000666 0000000 0000000 00000004302 12632317503 030741 0 ustar 0000000 0000000 # 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
astroid-1.4.4/astroid/tests/testdata/python3/data/package/subpackage/ 0000777 0000000 0000000 00000000000 12646224174 023764 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/package/subpackage/module.py 0000666 0000000 0000000 00000000040 12632317503 025607 0 ustar 0000000 0000000 """package.subpackage.module"""
astroid-1.4.4/astroid/tests/testdata/python3/data/package/subpackage/__init__.py 0000666 0000000 0000000 00000000031 12632317503 026061 0 ustar 0000000 0000000 """package.subpackage"""
astroid-1.4.4/astroid/tests/testdata/python3/data/package/__init__.py 0000666 0000000 0000000 00000000071 12632317503 023760 0 ustar 0000000 0000000 """package's __init__ file"""
from . import subpackage
astroid-1.4.4/astroid/tests/testdata/python3/data/recursion.py 0000666 0000000 0000000 00000000064 12632317503 022641 0 ustar 0000000 0000000 """ For issue #25 """
class Base(object):
pass astroid-1.4.4/astroid/tests/testdata/python3/data/SSL1/ 0000777 0000000 0000000 00000000000 12646224174 021006 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/SSL1/Connection1.py 0000666 0000000 0000000 00000000462 12632317503 023534 0 ustar 0000000 0000000 """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')
astroid-1.4.4/astroid/tests/testdata/python3/data/SSL1/__init__.py 0000666 0000000 0000000 00000000044 12632317503 023107 0 ustar 0000000 0000000 from .Connection1 import Connection
astroid-1.4.4/astroid/tests/testdata/python3/data/suppliermodule_test.py 0000666 0000000 0000000 00000000354 12646222644 024750 0 ustar 0000000 0000000 """ 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
astroid-1.4.4/astroid/tests/testdata/python3/data/unicode_package/ 0000777 0000000 0000000 00000000000 12646224174 023365 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/unicode_package/core/ 0000777 0000000 0000000 00000000000 12646224174 024315 5 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/unicode_package/core/__init__.py 0000666 0000000 0000000 00000000000 12632317503 026406 0 ustar 0000000 0000000 astroid-1.4.4/astroid/tests/testdata/python3/data/unicode_package/__init__.py 0000666 0000000 0000000 00000000021 12632317503 025461 0 ustar 0000000 0000000 x = "șțîâ" astroid-1.4.4/astroid/tests/testdata/python3/data/__init__.py 0000666 0000000 0000000 00000000104 12632317503 022362 0 ustar 0000000 0000000 __revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $"
astroid-1.4.4/astroid/tests/unittest_brain.py 0000666 0000000 0000000 00000043205 12646222644 017546 0 ustar 0000000 0000000 # 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
import six
from astroid import MANAGER
from astroid import bases
from astroid import builder
from astroid import nodes
from astroid import test_utils
from astroid import util
import astroid
try:
import nose # pylint: disable=unused-import
HAS_NOSE = True
except ImportError:
HAS_NOSE = False
try:
import multiprocessing # pylint: disable=unused-import
HAS_MULTIPROCESSING = True
except ImportError:
HAS_MULTIPROCESSING = False
try:
import enum # pylint: disable=unused-import
HAS_ENUM = True
except ImportError:
HAS_ENUM = False
try:
import dateutil # pylint: disable=unused-import
HAS_DATEUTIL = True
except ImportError:
HAS_DATEUTIL = False
try:
import numpy # pylint: disable=unused-import
HAS_NUMPY = True
except ImportError:
HAS_NUMPY = False
try:
import pytest # pylint: disable=unused-import
HAS_PYTEST = True
except ImportError:
HAS_PYTEST = 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(util.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')
self.assertEqual(len(instance.getattr('geturl')), 1)
self.assertEqual(instance.name, 'ParseResult')
def test_namedtuple_instance_attrs(self):
result = test_utils.extract_node('''
from collections import namedtuple
namedtuple('a', 'a b c')(1, 2, 3) #@
''')
inferred = next(result.infer())
for name, attr in inferred._instance_attrs.items():
self.assertEqual(attr[0].attrname, name)
def test_namedtuple_uninferable_fields(self):
node = test_utils.extract_node('''
x = [A] * 2
from collections import namedtuple
l = namedtuple('a', x)
l(1)
''')
inferred = next(node.infer())
self.assertIs(util.YES, inferred)
class ModuleExtenderTest(unittest.TestCase):
def testExtensionModules(self):
transformer = MANAGER._transform
for extender, _ in transformer.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_equals
from nose.tools import assert_true
assert_equal = assert_equal #@
assert_true = assert_true #@
assert_equals = assert_equals #@
""")
assert_equal = next(methods[0].value.infer())
assert_true = next(methods[1].value.infer())
assert_equals = next(methods[2].value.infer())
self.assertIsInstance(assert_equal, astroid.BoundMethod)
self.assertIsInstance(assert_true, astroid.BoundMethod)
self.assertIsInstance(assert_equals, astroid.BoundMethod)
self.assertEqual(assert_equal.qname(),
'unittest.case.TestCase.assertEqual')
self.assertEqual(assert_true.qname(),
'unittest.case.TestCase.assertTrue')
self.assertEqual(assert_equals.qname(),
'unittest.case.TestCase.assertEqual')
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.FunctionDef)
self.assertEqual(urljoin.qname(), 'urllib.parse.urljoin')
self.assertIsInstance(urlencode, nodes.FunctionDef)
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.ClassDef)
content_too_short = next(urllib_error.igetattr('ContentTooShortError'))
self.assertIsInstance(content_too_short, nodes.ClassDef)
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.FunctionDef)
self.assertEqual(urlopen.qname(), 'urllib.request.urlopen')
self.assertIsInstance(urlretrieve, nodes.FunctionDef)
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.ClassDef)
if six.PY3:
qname = 'http.client.HTTPSConnection'
else:
qname = 'httplib.HTTPSConnection'
self.assertEqual(inferred.qname(), qname)
@unittest.skipUnless(HAS_MULTIPROCESSING,
'multiprocesing is required for this test, but '
'on some platforms it is missing '
'(Jython for instance)')
class MultiprocessingBrainTest(unittest.TestCase):
def test_multiprocessing_module_attributes(self):
# Test that module attributes are working,
# especially on Python 3.4+, where they are obtained
# from a context.
module = test_utils.extract_node("""
import multiprocessing
""")
module = module.do_import_module('multiprocessing')
cpu_count = next(module.igetattr('cpu_count'))
if sys.version_info < (3, 4):
self.assertIsInstance(cpu_count, nodes.FunctionDef)
else:
self.assertIsInstance(cpu_count, astroid.BoundMethod)
def test_module_name(self):
module = test_utils.extract_node("""
import multiprocessing
multiprocessing.SyncManager()
""")
inferred_sync_mgr = next(module.infer())
module = inferred_sync_mgr.root()
self.assertEqual(module.name, 'multiprocessing.managers')
def test_multiprocessing_manager(self):
# Test that we have the proper attributes
# for a multiprocessing.managers.SyncManager
module = builder.parse("""
import multiprocessing
manager = multiprocessing.Manager()
queue = manager.Queue()
joinable_queue = manager.JoinableQueue()
event = manager.Event()
rlock = manager.RLock()
bounded_semaphore = manager.BoundedSemaphore()
condition = manager.Condition()
barrier = manager.Barrier()
pool = manager.Pool()
list = manager.list()
dict = manager.dict()
value = manager.Value()
array = manager.Array()
namespace = manager.Namespace()
""")
queue = next(module['queue'].infer())
self.assertEqual(queue.qname(),
"{}.Queue".format(six.moves.queue.__name__))
joinable_queue = next(module['joinable_queue'].infer())
self.assertEqual(joinable_queue.qname(),
"{}.Queue".format(six.moves.queue.__name__))
event = next(module['event'].infer())
event_name = "threading.{}".format("Event" if six.PY3 else "_Event")
self.assertEqual(event.qname(), event_name)
rlock = next(module['rlock'].infer())
rlock_name = "threading._RLock"
self.assertEqual(rlock.qname(), rlock_name)
bounded_semaphore = next(module['bounded_semaphore'].infer())
semaphore_name = "threading.{}".format(
"BoundedSemaphore" if six.PY3 else "_BoundedSemaphore")
self.assertEqual(bounded_semaphore.qname(), semaphore_name)
pool = next(module['pool'].infer())
pool_name = "multiprocessing.pool.Pool"
self.assertEqual(pool.qname(), pool_name)
for attr in ('list', 'dict'):
obj = next(module[attr].infer())
self.assertEqual(obj.qname(),
"{}.{}".format(bases.BUILTINS, attr))
array = next(module['array'].infer())
self.assertEqual(array.qname(), "array.array")
manager = next(module['manager'].infer())
# Verify that we have these attributes
self.assertTrue(manager.getattr('start'))
self.assertTrue(manager.getattr('shutdown'))
@unittest.skipUnless(HAS_ENUM,
'The enum module was only added in Python 3.4. Support for '
'older Python versions may be available through the enum34 '
'compatibility module.')
class EnumBrainTest(unittest.TestCase):
def test_simple_enum(self):
module = builder.parse("""
import enum
class MyEnum(enum.Enum):
one = "one"
two = "two"
def mymethod(self, x):
return 5
""")
enum = next(module['MyEnum'].infer())
one = enum['one']
self.assertEqual(one.pytype(), '.MyEnum.one')
property_type = '{}.property'.format(bases.BUILTINS)
for propname in ('name', 'value'):
prop = next(iter(one.getattr(propname)))
self.assertIn(property_type, prop.decoratornames())
meth = one.getattr('mymethod')[0]
self.assertIsInstance(meth, astroid.FunctionDef)
def test_looks_like_enum_false_positive(self):
# Test that a class named Enumeration is not considered a builtin enum.
module = builder.parse('''
class Enumeration(object):
def __init__(self, name, enum_list):
pass
test = 42
''')
enum = module['Enumeration']
test = next(enum.igetattr('test'))
self.assertEqual(test.value, 42)
def test_enum_multiple_base_classes(self):
module = builder.parse("""
import enum
class Mixin:
pass
class MyEnum(Mixin, enum.Enum):
one = 1
""")
enum = next(module['MyEnum'].infer())
one = enum['one']
clazz = one.getattr('__class__')[0]
self.assertTrue(clazz.is_subtype_of('.Mixin'),
'Enum instance should share base classes with generating class')
def test_int_enum(self):
module = builder.parse("""
import enum
class MyEnum(enum.IntEnum):
one = 1
""")
enum = next(module['MyEnum'].infer())
one = enum['one']
clazz = one.getattr('__class__')[0]
int_type = '{}.{}'.format(bases.BUILTINS, 'int')
self.assertTrue(clazz.is_subtype_of(int_type),
'IntEnum based enums should be a subtype of int')
def test_enum_func_form_is_class_not_instance(self):
cls, instance = test_utils.extract_node('''
from enum import Enum
f = Enum('Audience', ['a', 'b', 'c'])
f #@
f() #@
''')
inferred_cls = next(cls.infer())
self.assertIsInstance(inferred_cls, nodes.ClassDef)
inferred_instance = next(instance.infer())
self.assertIsInstance(inferred_instance, bases.Instance)
@unittest.skipUnless(HAS_DATEUTIL, "This test requires the dateutil library.")
class DateutilBrainTest(unittest.TestCase):
def test_parser(self):
module = builder.parse("""
from dateutil.parser import parse
d = parse('2000-01-01')
""")
d_type = next(module['d'].infer())
self.assertEqual(d_type.qname(), "datetime.datetime")
@unittest.skipUnless(HAS_NUMPY, "This test requires the numpy library.")
class NumpyBrainTest(unittest.TestCase):
def test_numpy(self):
node = test_utils.extract_node('''
import numpy
numpy.ones #@
''')
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.FunctionDef)
@unittest.skipUnless(HAS_PYTEST, "This test requires the pytest library.")
class PytestBrainTest(unittest.TestCase):
def test_pytest(self):
ast_node = test_utils.extract_node('''
import pytest
pytest #@
''')
module = next(ast_node.infer())
self.assertIn('deprecated_call', module)
self.assertIn('exit', module)
self.assertIn('fail', module)
self.assertIn('fixture', module)
self.assertIn('mark', module)
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_builder.py 0000666 0000000 0000000 00000070332 12646222644 020102 0 ustar 0000000 0000000 # 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
import six
from astroid import builder
from astroid import exceptions
from astroid import manager
from astroid import nodes
from astroid import test_utils
from astroid import util
from astroid.tests import resources
MANAGER = manager.AstroidManager()
BUILTINS = six.moves.builtins.__name__
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.Expr)
self.assertEqual(discard.fromlineno, 4)
self.assertEqual(discard.tolineno, 5)
callfunc = discard.value
self.assertIsInstance(callfunc, nodes.Call)
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.Expr)
self.assertEqual(discard.fromlineno, 10)
self.assertEqual(discard.tolineno, 13)
callfunc = discard.value
self.assertIsInstance(callfunc, nodes.Call)
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.FunctionDef)
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.parse('''
@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.ClassDef)
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.parse(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 = builder.parse('''
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 = builder.parse('''
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 = builder.parse('''
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 = builder.parse('''
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(exceptions.AstroidBuildingException):
self.builder.string_build('\x00')
def test_data_build_invalid_x_escape(self):
with self.assertRaises(exceptions.AstroidBuildingException):
self.builder.string_build('"\\x1"')
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(exceptions.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 six.PY2:
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.FunctionDef)
# 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.FunctionDef)
# 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 six.PY3:
self.assertIsInstance(builtin_ast['Exception'], nodes.ClassDef)
self.assertIsInstance(builtin_ast['NotImplementedError'], nodes.ClassDef)
else:
self.assertIsInstance(builtin_ast['Exception'], nodes.ImportFrom)
self.assertIsInstance(builtin_ast['NotImplementedError'], nodes.ImportFrom)
def test_inspect_build1(self):
time_ast = MANAGER.ast_from_module_name('time')
self.assertTrue(time_ast)
self.assertEqual(time_ast['time'].args.defaults, [])
if os.name == 'java':
test_inspect_build1 = unittest.expectedFailure(test_inspect_build1)
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)
inferred = list(builtin_ast.igetattr('object'))
self.assertEqual(len(inferred), 1)
inferred = inferred[0]
self.assertEqual(inferred.name, 'object')
inferred.as_string() # no crash test
inferred = list(builtin_ast.igetattr('type'))
self.assertEqual(len(inferred), 1)
inferred = inferred[0]
self.assertEqual(inferred.name, 'type')
inferred.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.FunctionDef)
stmt = func.body[0]
self.assertIsInstance(stmt, nodes.Expr)
self.assertIsInstance(stmt.value, nodes.Yield)
self.assertIsInstance(func.body[1].body[0], nodes.Expr)
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 = builder.parse(data, __name__)
if six.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 = builder.parse(data, __name__)
self.assertEqual(len(astroid.getattr('CSTE')), 2)
self.assertIsInstance(astroid.getattr('CSTE')[0], nodes.AssignName)
self.assertEqual(astroid.getattr('CSTE')[0].fromlineno, 2)
self.assertEqual(astroid.getattr('CSTE')[1].fromlineno, 6)
with self.assertRaises(exceptions.NotFoundError):
astroid.getattr('CSTE2')
with self.assertRaises(exceptions.InferenceError):
next(astroid['global_no_effect'].ilookup('CSTE2'))
@unittest.skipIf(os.name == 'java',
'This test is skipped on Jython, because the '
'socket object is patched later on with the '
'methods we are looking for. Since we do not '
'understand setattr in for loops yet, we skip this')
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'):
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 = builder.parse(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()],
[util.YES.__class__])
def test_no_future_imports(self):
mod = builder.parse("import sys")
self.assertEqual(set(), mod._future_imports)
def test_future_imports(self):
mod = builder.parse("from __future__ import print_function")
self.assertEqual(set(['print_function']), mod._future_imports)
def test_two_future_imports(self):
mod = builder.parse("""
from __future__ import print_function
from __future__ import absolute_import
""")
self.assertEqual(set(['print_function', 'absolute_import']), mod._future_imports)
def test_inferred_build(self):
code = '''
class A: pass
A.type = "class"
def A_assign_type(self):
print (self)
A.assign_type = A_assign_type
'''
astroid = builder.parse(code)
lclass = list(astroid.igetattr('A'))
self.assertEqual(len(lclass), 1)
lclass = lclass[0]
self.assertIn('assign_type', lclass._locals)
self.assertIn('type', lclass._locals)
def test_augassign_attr(self):
builder.parse("""
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_inferred_dont_pollute(self):
code = '''
def func(a=None):
a.custom_attr = 0
def func2(a={}):
a.custom_attr = 0
'''
builder.parse(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 = builder.parse(code)
self.assertIn('b', astroid._locals)
code = '''
def visit_if(self, node):
node.test, body = node.tests[0]
'''
astroid = builder.parse(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 = builder.parse(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_not_implemented(self):
node = test_utils.extract_node('''
NotImplemented #@
''')
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, NotImplemented)
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.source_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', 'NameNode', 'YO', 'YOUPI',
'__revision__', 'global_access', 'modutils', 'four_args',
'os', 'redirect']
should.sort()
self.assertEqual(keys, sorted(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 six.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()
try:
import data.module
except ImportError:
# Make pylint happy.
self.skipTest('Unable to load data.module')
else:
self.module = abuilder.module_build(data.module, 'data.module')
@unittest.skipIf(six.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()
astroid-1.4.4/astroid/tests/unittest_inference.py 0000666 0000000 0000000 00000221732 12646222644 020414 0 ustar 0000000 0000000 # 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 warnings
import six
from astroid import InferenceError, builder, nodes
from astroid.builder import parse
from astroid.inference import infer_end as inference_infer_end
from astroid.bases import Instance, BoundMethod, UnboundMethod,\
path_wrapper, BUILTINS
from astroid import arguments
from astroid import objects
from astroid import test_utils
from astroid import util
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):
inferred = next(node.infer())
self.assertIsInstance(inferred, node_type)
self.assertEqual(sorted(elt.value for elt in inferred.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):
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, expected)
def assertInferDict(self, node, expected):
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Dict)
elts = set([(key.value, value.value)
for (key, value) in inferred.items])
self.assertEqual(sorted(elts), sorted(expected.items()))
assertInferTuple = partialmethod(_assertInferElts, nodes.Tuple)
assertInferList = partialmethod(_assertInferElts, nodes.List)
assertInferSet = partialmethod(_assertInferElts, nodes.Set)
assertInferFrozenSet = partialmethod(_assertInferElts, objects.FrozenSet)
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 = parse(CODE, __name__)
def test_infer_abstract_property_return_values(self):
module = parse('''
import abc
class A(object):
@abc.abstractproperty
def test(self):
return 42
a = A()
x = a.test
''')
inferred = next(module['x'].infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, 42)
def test_module_inference(self):
inferred = self.ast.infer()
obj = next(inferred)
self.assertEqual(obj.name, __name__)
self.assertEqual(obj.root().name, __name__)
self.assertRaises(StopIteration, partial(next, inferred))
def test_class_inference(self):
inferred = self.ast['C'].infer()
obj = next(inferred)
self.assertEqual(obj.name, 'C')
self.assertEqual(obj.root().name, __name__)
self.assertRaises(StopIteration, partial(next, inferred))
def test_function_inference(self):
inferred = self.ast['C']['meth1'].infer()
obj = next(inferred)
self.assertEqual(obj.name, 'meth1')
self.assertEqual(obj.root().name, __name__)
self.assertRaises(StopIteration, partial(next, inferred))
def test_builtin_name_inference(self):
inferred = self.ast['C']['meth1']['var'].infer()
var = next(inferred)
self.assertEqual(var.name, 'object')
self.assertEqual(var.root().name, BUILTINS)
self.assertRaises(StopIteration, partial(next, inferred))
def test_tupleassign_name_inference(self):
inferred = self.ast['a'].infer()
exc = next(inferred)
self.assertIsInstance(exc, Instance)
self.assertEqual(exc.name, 'Exception')
self.assertEqual(exc.root().name, EXC_MODULE)
self.assertRaises(StopIteration, partial(next, inferred))
inferred = self.ast['b'].infer()
const = next(inferred)
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, 1)
self.assertRaises(StopIteration, partial(next, inferred))
inferred = self.ast['c'].infer()
const = next(inferred)
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, "bonjour")
self.assertRaises(StopIteration, partial(next, inferred))
def test_listassign_name_inference(self):
inferred = self.ast['d'].infer()
exc = next(inferred)
self.assertIsInstance(exc, Instance)
self.assertEqual(exc.name, 'Exception')
self.assertEqual(exc.root().name, EXC_MODULE)
self.assertRaises(StopIteration, partial(next, inferred))
inferred = self.ast['e'].infer()
const = next(inferred)
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, 1.0)
self.assertRaises(StopIteration, partial(next, inferred))
inferred = self.ast['f'].infer()
const = next(inferred)
self.assertIsInstance(const, nodes.Tuple)
self.assertRaises(StopIteration, partial(next, inferred))
def test_advanced_tupleassign_name_inference1(self):
inferred = self.ast['g'].infer()
const = next(inferred)
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, "bonjour")
self.assertRaises(StopIteration, partial(next, inferred))
inferred = self.ast['h'].infer()
var = next(inferred)
self.assertEqual(var.name, 'object')
self.assertEqual(var.root().name, BUILTINS)
self.assertRaises(StopIteration, partial(next, inferred))
def test_advanced_tupleassign_name_inference2(self):
inferred = self.ast['i'].infer()
const = next(inferred)
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, u"glup")
self.assertRaises(StopIteration, partial(next, inferred))
inferred = self.ast['j'].infer()
const = next(inferred)
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, "bonjour")
self.assertRaises(StopIteration, partial(next, inferred))
inferred = self.ast['k'].infer()
var = next(inferred)
self.assertEqual(var.name, 'object')
self.assertEqual(var.root().name, BUILTINS)
self.assertRaises(StopIteration, partial(next, inferred))
def test_swap_assign_inference(self):
inferred = self.ast._locals['a'][1].infer()
const = next(inferred)
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, 1)
self.assertRaises(StopIteration, partial(next, inferred))
inferred = self.ast._locals['b'][1].infer()
exc = next(inferred)
self.assertIsInstance(exc, Instance)
self.assertEqual(exc.name, 'Exception')
self.assertEqual(exc.root().name, EXC_MODULE)
self.assertRaises(StopIteration, partial(next, inferred))
def test_getattr_inference1(self):
inferred = self.ast['ex'].infer()
exc = next(inferred)
self.assertIsInstance(exc, Instance)
self.assertEqual(exc.name, 'Exception')
self.assertEqual(exc.root().name, EXC_MODULE)
self.assertRaises(StopIteration, partial(next, inferred))
def test_getattr_inference2(self):
inferred = get_node_of_class(self.ast['C']['meth2'], nodes.Attribute).infer()
meth1 = next(inferred)
self.assertEqual(meth1.name, 'meth1')
self.assertEqual(meth1.root().name, __name__)
self.assertRaises(StopIteration, partial(next, inferred))
def test_getattr_inference3(self):
inferred = self.ast['C']['meth3']['b'].infer()
const = next(inferred)
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, 4)
self.assertRaises(StopIteration, partial(next, inferred))
def test_getattr_inference4(self):
inferred = self.ast['C']['meth3']['c'].infer()
const = next(inferred)
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, "hop")
self.assertRaises(StopIteration, partial(next, inferred))
def test_callfunc_inference(self):
inferred = self.ast['v'].infer()
meth1 = next(inferred)
self.assertIsInstance(meth1, Instance)
self.assertEqual(meth1.name, 'object')
self.assertEqual(meth1.root().name, BUILTINS)
self.assertRaises(StopIteration, partial(next, inferred))
def test_unbound_method_inference(self):
inferred = self.ast['m_unbound'].infer()
meth1 = next(inferred)
self.assertIsInstance(meth1, UnboundMethod)
self.assertEqual(meth1.name, 'meth1')
self.assertEqual(meth1.parent.frame().name, 'C')
self.assertRaises(StopIteration, partial(next, inferred))
def test_bound_method_inference(self):
inferred = self.ast['m_bound'].infer()
meth1 = next(inferred)
self.assertIsInstance(meth1, BoundMethod)
self.assertEqual(meth1.name, 'meth1')
self.assertEqual(meth1.parent.frame().name, 'C')
self.assertRaises(StopIteration, partial(next, inferred))
def test_args_default_inference1(self):
optarg = test_utils.get_name_node(self.ast['C']['meth1'], 'optarg')
inferred = optarg.infer()
obj1 = next(inferred)
self.assertIsInstance(obj1, nodes.Const)
self.assertEqual(obj1.value, 0)
obj1 = next(inferred)
self.assertIs(obj1, util.YES, obj1)
self.assertRaises(StopIteration, partial(next, inferred))
def test_args_default_inference2(self):
inferred = self.ast['C']['meth3'].ilookup('d')
obj1 = next(inferred)
self.assertIsInstance(obj1, nodes.Const)
self.assertEqual(obj1.value, 4)
obj1 = next(inferred)
self.assertIs(obj1, util.YES, obj1)
self.assertRaises(StopIteration, partial(next, inferred))
def test_inference_restrictions(self):
inferred = test_utils.get_name_node(self.ast['C']['meth1'], 'arg1').infer()
obj1 = next(inferred)
self.assertIs(obj1, util.YES, obj1)
self.assertRaises(StopIteration, partial(next, inferred))
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 = parse(code, __name__)
a = ast['a']
a_inferred = a.inferred()
self.assertEqual(a_inferred[0].value, 1)
self.assertEqual(len(a_inferred), 1)
def test_infered_warning(self):
code = '''
def f(f=1):
return f
a = f()
'''
ast = parse(code, __name__)
a = ast['a']
warnings.simplefilter('always')
with warnings.catch_warnings(record=True) as w:
a.infered()
self.assertIsInstance(w[0].message, PendingDeprecationWarning)
def test_exc_ancestors(self):
code = '''
def f():
raise __(NotImplementedError)
'''
error = test_utils.extract_node(code, __name__)
nie = error.inferred()[0]
self.assertIsInstance(nie, nodes.ClassDef)
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 = parse(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 = parse(code, __name__)
n = ast['b']
n_infer = n.infer()
inferred = next(n_infer)
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.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()
inferred = next(n_infer)
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, 2)
self.assertRaises(StopIteration, partial(next, n_infer))
def test_builtin_types(self):
code = '''
l = [1]
t = (2,)
d = {}
s = ''
s2 = '_'
'''
ast = parse(code, __name__)
n = ast['l']
inferred = next(n.infer())
self.assertIsInstance(inferred, nodes.List)
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.getitem(0).value, 1)
self.assertIsInstance(inferred._proxied, nodes.ClassDef)
self.assertEqual(inferred._proxied.name, 'list')
self.assertIn('append', inferred._proxied._locals)
n = ast['t']
inferred = next(n.infer())
self.assertIsInstance(inferred, nodes.Tuple)
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.getitem(0).value, 2)
self.assertIsInstance(inferred._proxied, nodes.ClassDef)
self.assertEqual(inferred._proxied.name, 'tuple')
n = ast['d']
inferred = next(n.infer())
self.assertIsInstance(inferred, nodes.Dict)
self.assertIsInstance(inferred, Instance)
self.assertIsInstance(inferred._proxied, nodes.ClassDef)
self.assertEqual(inferred._proxied.name, 'dict')
self.assertIn('get', inferred._proxied._locals)
n = ast['s']
inferred = next(n.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.name, 'str')
self.assertIn('lower', inferred._proxied._locals)
n = ast['s2']
inferred = next(n.infer())
self.assertEqual(inferred.getitem(0).value, '_')
code = 's = {1}'
ast = parse(code, __name__)
n = ast['s']
inferred = next(n.infer())
self.assertIsInstance(inferred, nodes.Set)
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.name, 'set')
self.assertIn('remove', inferred._proxied._locals)
@test_utils.require_version(maxver='3.0')
def test_unicode_type(self):
code = '''u = u""'''
ast = parse(code, __name__)
n = ast['u']
inferred = next(n.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.name, 'unicode')
self.assertIn('lower', inferred._proxied._locals)
@unittest.expectedFailure
def test_descriptor_are_callable(self):
code = '''
class A:
statm = staticmethod(open)
clsm = classmethod('whatever')
'''
ast = parse(code, __name__)
statm = next(ast['A'].igetattr('statm'))
self.assertTrue(statm.callable())
clsm = next(ast['A'].igetattr('clsm'))
self.assertFalse(clsm.callable())
def test_bt_ancestor_crash(self):
code = '''
class Warning(Warning):
pass
'''
ast = parse(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 = parse(code, __name__)
xxx = ast['xxx']
self.assertSetEqual({n.__class__ for n in xxx.inferred()},
{nodes.Const, util.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 = parse(code, __name__)
arg = test_utils.get_name_node(ast['ErudiEntitySchema']['__init__'], 'e_type')
self.assertEqual([n.__class__ for n in arg.infer()],
[util.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()],
[util.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 = parse(code, __name__)
self.assertEqual(len(list(ast['process_line'].infer_call_result(None))), 3)
self.assertEqual(len(list(ast['tupletest'].infer())), 3)
values = ['FunctionDef(first_word)', 'FunctionDef(last_word)', 'Const(NoneType)']
self.assertEqual([str(inferred)
for inferred 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 = parse(code, __name__)
values = [i.value for i in test_utils.get_name_node(ast, 'something', -1).infer()]
self.assertEqual(values, [1.0, 1.0j])
def test_simple_subscript(self):
code = '''
class A(object):
def __getitem__(self, index):
return index + 42
[1, 2, 3][0] #@
(1, 2, 3)[1] #@
(1, 2, 3)[-1] #@
[1, 2, 3][0] + (2, )[0] + (3, )[-1] #@
e = {'key': 'value'}
e['key'] #@
"first"[0] #@
list([1, 2, 3])[-1] #@
tuple((4, 5, 6))[2] #@
A()[0] #@
A()[-1] #@
'''
ast_nodes = test_utils.extract_node(code, __name__)
expected = [1, 2, 3, 6, 'value', 'f', 3, 6, 42, 41]
for node, expected_value in zip(ast_nodes, expected):
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, expected_value)
def test_invalid_subscripts(self):
ast_nodes = test_utils.extract_node('''
class NoGetitem(object):
pass
class InvalidGetitem(object):
def __getitem__(self): pass
class InvalidGetitem2(object):
__getitem__ = 42
NoGetitem()[4] #@
InvalidGetitem()[5] #@
InvalidGetitem2()[10] #@
[1, 2, 3][None] #@
'lala'['bala'] #@
''')
for node in ast_nodes[:3]:
self.assertRaises(InferenceError, next, node.infer())
for node in ast_nodes[3:]:
self.assertEqual(next(node.infer()), util.YES)
def test_bytes_subscript(self):
node = test_utils.extract_node('''b'a'[0]''')
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Const)
if six.PY2:
self.assertEqual(inferred.value, 'a')
else:
self.assertEqual(inferred.value, 97)
#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 = parse(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 = parse(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__)
inferred = list(node.func.infer())
self.assertEqual(len(inferred), 1, inferred)
self.assertIsInstance(inferred[0], Instance)
self.assertEqual(inferred[0].name, "_Helper")
def test_builtin_open(self):
code = '''
open("toto.txt")
'''
node = test_utils.extract_node(code, __name__).func
inferred = list(node.infer())
self.assertEqual(len(inferred), 1)
if hasattr(sys, 'pypy_version_info'):
self.assertIsInstance(inferred[0], nodes.ClassDef)
self.assertEqual(inferred[0].name, 'file')
else:
self.assertIsInstance(inferred[0], nodes.FunctionDef)
self.assertEqual(inferred[0].name, 'open')
def test_callfunc_context_func(self):
code = '''
def mirror(arg=None):
return arg
un = mirror(1)
'''
ast = parse(code, __name__)
inferred = list(ast.igetattr('un'))
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.Const)
self.assertEqual(inferred[0].value, 1)
def test_callfunc_context_lambda(self):
code = '''
mirror = lambda x=None: x
un = mirror(1)
'''
ast = parse(code, __name__)
inferred = list(ast.igetattr('mirror'))
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.Lambda)
inferred = list(ast.igetattr('un'))
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.Const)
self.assertEqual(inferred[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 = parse(code, __name__)
inferred = list(ast.igetattr('sub'))
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], Instance)
self.assertEqual(inferred[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 = parse(code, __name__)
inferred = list(ast.igetattr('osp'))
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.Module)
self.assertEqual(inferred[0].name, 'os.path')
inferred = list(ast.igetattr('e'))
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.FunctionDef)
self.assertEqual(inferred[0].name, 'exists')
if sys.version_info >= (3, 0):
self.skipTest(' module has been removed')
inferred = list(ast.igetattr('make_code'))
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], Instance)
self.assertEqual(str(inferred[0]),
'Instance of %s.type' % BUILTINS)
def _test_const_inferred(self, node, value):
inferred = list(node.infer())
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.Const)
self.assertEqual(inferred[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_inferred(ast['a'], False)
self._test_const_inferred(ast['b'], True)
@test_utils.require_version(minver='3.5')
def test_matmul(self):
node = test_utils.extract_node('''
class Array:
def __matmul__(self, other):
return 42
Array() @ Array() #@
''')
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, 42)
def test_binary_op_int_add(self):
ast = builder.string_build('a = 1 + 2', __name__, __file__)
self._test_const_inferred(ast['a'], 3)
def test_binary_op_int_sub(self):
ast = builder.string_build('a = 1 - 2', __name__, __file__)
self._test_const_inferred(ast['a'], -1)
def test_binary_op_float_div(self):
ast = builder.string_build('a = 1 / 2.', __name__, __file__)
self._test_const_inferred(ast['a'], 1 / 2.)
def test_binary_op_str_mul(self):
ast = builder.string_build('a = "*" * 40', __name__, __file__)
self._test_const_inferred(ast['a'], "*" * 40)
def test_binary_op_bitand(self):
ast = builder.string_build('a = 23&20', __name__, __file__)
self._test_const_inferred(ast['a'], 23&20)
def test_binary_op_bitor(self):
ast = builder.string_build('a = 23|8', __name__, __file__)
self._test_const_inferred(ast['a'], 23|8)
def test_binary_op_bitxor(self):
ast = builder.string_build('a = 23^9', __name__, __file__)
self._test_const_inferred(ast['a'], 23^9)
def test_binary_op_shiftright(self):
ast = builder.string_build('a = 23 >>1', __name__, __file__)
self._test_const_inferred(ast['a'], 23>>1)
def test_binary_op_shiftleft(self):
ast = builder.string_build('a = 23 <<1', __name__, __file__)
self._test_const_inferred(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__)
inferred = list(ast['a'].infer())
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.List)
self.assertEqual(len(inferred[0].elts), 2)
self.assertIsInstance(inferred[0].elts[0], nodes.List)
self.assertIsInstance(inferred[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"')
inferred = ast['a'].inferred()
self.assertEqual(len(inferred), 1)
self.assertEqual(inferred[0], util.YES)
inferred = ast['b'].inferred()
self.assertEqual(len(inferred), 1)
self.assertEqual(inferred[0], util.YES)
def test_binary_op_list_mul_int(self):
'test correct handling on list multiplied by int when there are more than one'
code = '''
from ctypes import c_int
seq = [c_int()] * 4
'''
ast = parse(code, __name__)
inferred = ast['seq'].inferred()
self.assertEqual(len(inferred), 1)
listval = inferred[0]
self.assertIsInstance(listval, nodes.List)
self.assertEqual(len(listval.itered()), 4)
def test_binary_op_tuple_add(self):
ast = builder.string_build('a = (1,) + (2,)', __name__, __file__)
inferred = list(ast['a'].infer())
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.Tuple)
self.assertEqual(len(inferred[0].elts), 2)
self.assertEqual(inferred[0].elts[0].value, 1)
self.assertEqual(inferred[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 = parse(code, __name__)
inferred = list(ast.igetattr('x'))
self.assertEqual(len(inferred), 2)
value = [str(v) for v in inferred]
# 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)
inferred = list(callfuncnode.infer())
self.assertEqual(len(inferred), 2, inferred)
inferred.remove(util.YES)
self.assertIsInstance(inferred[0], nodes.Const)
self.assertIsNone(inferred[0].value)
def test_nonregr_getitem_empty_tuple(self):
code = '''
def f(x):
a = ()[x]
'''
ast = parse(code, __name__)
inferred = list(ast['f'].ilookup('a'))
self.assertEqual(len(inferred), 1)
self.assertEqual(inferred[0], util.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 = parse(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.inferred()[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):
# pylint: disable=redefined-variable-type
buffer = six.StringIO()
sys.stderr = buffer
try:
data = "b = {}[str(0)+''].a"
ast = builder.string_build(data, __name__, __file__)
list(ast['b'].infer())
output = buffer.getvalue()
finally:
sys.stderr = sys.__stderr__
# I have no idea how to test for this in another way...
msg = ("Exception exceptions.RuntimeError: "
"'generator ignored GeneratorExit' in "
"ignored")
self.assertNotIn("RuntimeError", output, msg)
def test_python25_no_relative_import(self):
ast = resources.build_file('data/package/absimport.py')
self.assertTrue(ast.absolute_import_activated(), True)
inferred = next(test_utils.get_name_node(ast, 'import_package_subpackage_module').infer())
# failed to import since absolute_import is activated
self.assertIs(inferred, util.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)
inferred = next(test_utils.get_name_node(ast, 'string').infer())
self.assertIsInstance(inferred, nodes.Module)
self.assertEqual(inferred.name, 'string')
self.assertIn('ascii_letters', inferred._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 = parse(data, __name__)
browser = next(test_utils.get_name_node(ast, 'Browser').infer())
self.assertIsInstance(browser, nodes.ClassDef)
bopen = list(browser.igetattr('open'))
self.skipTest('the commit said: "huum, see that later"')
self.assertEqual(len(bopen), 1)
self.assertIsInstance(bopen[0], nodes.FunctionDef)
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 = parse(code, __name__)
self.assertEqual(ast['SendMailController']['smtp'].decoratornames(),
decorators)
propinferred = list(ast.body[2].value.infer())
self.assertEqual(len(propinferred), 1)
propinferred = propinferred[0]
self.assertIsInstance(propinferred, Instance)
self.assertEqual(propinferred.name, 'SMTP')
self.assertEqual(propinferred.root().name, 'smtplib')
self.assertEqual(ast['SendMailController']['me'].decoratornames(),
decorators)
propinferred = list(ast.body[3].value.infer())
self.assertEqual(len(propinferred), 1)
propinferred = propinferred[0]
self.assertIsInstance(propinferred, Instance)
self.assertEqual(propinferred.name, 'SendMailController')
self.assertEqual(propinferred.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 = parse(code, __name__)
pactions = test_utils.get_name_node(ast, 'pactions')
inferred = list(pactions.infer())
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.FunctionDef)
pactions = test_utils.get_name_node(ast['EnvBasedTC2'], 'pactions')
inferred = list(pactions.infer())
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.FunctionDef)
def test_augassign(self):
code = '''
a = 1
a += 2
print (a)
'''
ast = parse(code, __name__)
inferred = list(test_utils.get_name_node(ast, 'a').infer())
self.assertEqual(len(inferred), 1)
self.assertIsInstance(inferred[0], nodes.Const)
self.assertEqual(inferred[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 = parse(code, __name__)
inferred = list(test_utils.get_name_node(ast['foo'], 'spam').infer())
self.assertEqual(len(inferred), 1)
self.assertIs(inferred[0], util.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 = parse(code, __name__)
inferred = list(Instance(ast['DataManager']).igetattr('app'))
self.assertEqual(len(inferred), 2, inferred) # None / Instance(Application)
inferred = list(test_utils.get_name_node(ast['DataManager']['test'], 'p').infer())
self.assertEqual(len(inferred), 2, inferred)
for node in inferred:
if isinstance(node, Instance) and node.name == 'Application':
break
else:
self.fail('expected to find an instance of Application in %s' % inferred)
def test_list_inference(self):
"""#20464"""
code = '''
from unknown import Unknown
A = []
B = []
def test():
xyz = [
Unknown
] + A + B
return xyz
Z = test()
'''
ast = parse(code, __name__)
inferred = next(ast['Z'].infer())
self.assertIsInstance(inferred, nodes.List)
self.assertEqual(len(inferred.elts), 1)
self.assertIs(inferred.elts[0], util.YES)
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 = parse(code, __name__)
self.assertRaises(InferenceError, list, ast['NewTest'].igetattr('arg'))
n = next(ast['n'].infer())
inferred = list(n.igetattr('arg'))
self.assertEqual(len(inferred), 1, inferred)
def test__new__bound_methods(self):
node = test_utils.extract_node('''
class cls(object): pass
cls().__new__(cls) #@
''')
inferred = next(node.infer())
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred._proxied, node.root()['cls'])
def test_two_parents_from_same_module(self):
code = '''
from data import nonregr
class Xxx(nonregr.Aaa, nonregr.Ccc):
"doc"
'''
ast = parse(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 = parse(code, __name__)
aclass = ast['A'].inferred()[0]
self.assertIsInstance(aclass, nodes.ClassDef)
self.assertIn('a', aclass._instance_attrs)
self.assertIn('b', aclass._instance_attrs)
bclass = ast['B'].inferred()[0]
self.assertIsInstance(bclass, nodes.ClassDef)
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 = parse(code, __name__)
int_node = ast['x'].inferred()[0]
self.assertIsInstance(int_node, nodes.Const)
self.assertEqual(int_node.value, 1)
list_node = ast['y'].inferred()[0]
self.assertIsInstance(list_node, nodes.List)
int_node = ast['z'].inferred()[0]
self.assertIsInstance(int_node, nodes.Const)
self.assertEqual(int_node.value, 1)
empty = ast['empty'].inferred()[0]
self.assertIsInstance(empty, nodes.Const)
self.assertEqual(empty.value, 2)
empty_list = ast['empty_list'].inferred()[0]
self.assertIsInstance(empty_list, nodes.List)
def test_infer_variable_arguments(self):
code = '''
def test(*args, **kwargs):
vararg = args
kwarg = kwargs
'''
ast = parse(code, __name__)
func = ast['test']
vararg = func.body[0].value
kwarg = func.body[1].value
kwarg_inferred = kwarg.inferred()[0]
self.assertIsInstance(kwarg_inferred, nodes.Dict)
self.assertIs(kwarg_inferred.parent, func.args)
vararg_inferred = vararg.inferred()[0]
self.assertIsInstance(vararg_inferred, nodes.Tuple)
self.assertIs(vararg_inferred.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 = parse(code, __name__)
callfunc = next(ast.nodes_of_class(nodes.Call))
func = callfunc.func
inferred = func.inferred()[0]
self.assertIsInstance(inferred, 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 = parse(code, __name__)
sub = ast['sub'].inferred()[0]
mul = ast['mul'].inferred()[0]
self.assertIs(sub, util.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 = parse(code, __name__)
sub = ast['sub'].inferred()[0]
mul = ast['mul'].inferred()[0]
self.assertIs(sub, util. 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 = parse(code, __name__)
sub = ast['sub'].inferred()[0]
mul = ast['mul'].inferred()[0]
self.assertIs(sub, util.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 = parse(code, __name__)
node = ast['c']
self.assertEqual(node.inferred(), [util.YES])
def test_infer_empty_nodes(self):
# Should not crash when trying to infer EmptyNodes.
node = nodes.EmptyNode()
self.assertEqual(node.inferred(), [util.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 = parse(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:]:
inferred = next(node.infer())
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.qname(), "{}.tuple".format(BUILTINS))
def test_frozenset_builtin_inference(self):
code = """
var = (1, 2)
frozenset() #@
frozenset([1, 2, 1]) #@
frozenset({2, 3, 1}) #@
frozenset("abcab") #@
frozenset({1: 2}) #@
frozenset(var) #@
frozenset(tuple([1])) #@
frozenset(set(tuple([4, 5, set([2])]))) #@
frozenset(None) #@
frozenset(1) #@
frozenset(1, 2) #@
"""
ast = test_utils.extract_node(code, __name__)
self.assertInferFrozenSet(ast[0], [])
self.assertInferFrozenSet(ast[1], [1, 2])
self.assertInferFrozenSet(ast[2], [1, 2, 3])
self.assertInferFrozenSet(ast[3], ["a", "b", "c"])
self.assertInferFrozenSet(ast[4], [1])
self.assertInferFrozenSet(ast[5], [1, 2])
self.assertInferFrozenSet(ast[6], [1])
for node in ast[7:]:
infered = next(node.infer())
self.assertIsInstance(infered, Instance)
self.assertEqual(infered.qname(), "{}.frozenset".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:]:
inferred = next(node.infer())
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.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:]:
inferred = next(node.infer())
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.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:]:
inferred = next(node.infer())
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.qname(), "{}.dict".format(BUILTINS))
def test_dict_inference_kwargs(self):
ast_node = test_utils.extract_node('''dict(a=1, b=2, **{'c': 3})''')
self.assertInferDict(ast_node, {'a': 1, 'b': 2, 'c': 3})
@test_utils.require_version('3.5')
def test_dict_inference_for_multiple_starred(self):
pairs = [
('dict(a=1, **{"b": 2}, **{"c":3})', {'a':1, 'b':2, 'c':3}),
('dict(a=1, **{"b": 2}, d=4, **{"c":3})', {'a':1, 'b':2, 'c':3, 'd':4}),
('dict({"a":1}, b=2, **{"c":3})', {'a':1, 'b':2, 'c':3}),
]
for code, expected_value in pairs:
node = test_utils.extract_node(code)
self.assertInferDict(node, expected_value)
def test_dict_invalid_args(self):
invalid_values = [
'dict(*1)',
'dict(**lala)',
'dict(**[])',
]
for invalid in invalid_values:
ast_node = test_utils.extract_node(invalid)
inferred = next(ast_node.infer())
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.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 = parse(code, __name__)
bases = ast['Second'].bases[0]
inferred = next(bases.infer())
self.assertTrue(inferred)
self.assertIsInstance(inferred, nodes.ClassDef)
self.assertEqual(inferred.qname(), 'collections.Counter')
class ArgumentsTest(unittest.TestCase):
@staticmethod
def _get_dict_value(inferred):
items = inferred.items
return sorted((key.value, value.value) for key, value in items)
@staticmethod
def _get_tuple_value(inferred):
elts = inferred.elts
return tuple(elt.value for elt in elts)
def test_args(self):
expected_values = [(), (1, ), (2, 3), (4, 5),
(3, ), (), (3, 4, 5),
(), (), (4, ), (4, 5),
(), (3, ), (), (), (3, ), (42, )]
ast_nodes = test_utils.extract_node('''
def func(*args):
return args
func() #@
func(1) #@
func(2, 3) #@
func(*(4, 5)) #@
def func(a, b, *args):
return args
func(1, 2, 3) #@
func(1, 2) #@
func(1, 2, 3, 4, 5) #@
def func(a, b, c=42, *args):
return args
func(1, 2) #@
func(1, 2, 3) #@
func(1, 2, 3, 4) #@
func(1, 2, 3, 4, 5) #@
func = lambda a, b, *args: args
func(1, 2) #@
func(1, 2, 3) #@
func = lambda a, b=42, *args: args
func(1) #@
func(1, 2) #@
func(1, 2, 3) #@
func(1, 2, *(42, )) #@
''')
for node, expected_value in zip(ast_nodes, expected_values):
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Tuple)
self.assertEqual(self._get_tuple_value(inferred), expected_value)
@test_utils.require_version('3.5')
def test_multiple_starred_args(self):
expected_values = [
(1, 2, 3),
(1, 4, 2, 3, 5, 6, 7),
]
ast_nodes = test_utils.extract_node('''
def func(a, b, *args):
return args
func(1, 2, *(1, ), *(2, 3)) #@
func(1, 2, *(1, ), 4, *(2, 3), 5, *(6, 7)) #@
''')
for node, expected_value in zip(ast_nodes, expected_values):
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Tuple)
self.assertEqual(self._get_tuple_value(inferred), expected_value)
def test_defaults(self):
expected_values = [42, 3, 41, 42]
ast_nodes = test_utils.extract_node('''
def func(a, b, c=42, *args):
return c
func(1, 2) #@
func(1, 2, 3) #@
func(1, 2, c=41) #@
func(1, 2, 42, 41) #@
''')
for node, expected_value in zip(ast_nodes, expected_values):
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, expected_value)
@test_utils.require_version('3.0')
def test_kwonly_args(self):
expected_values = [24, 24, 42, 23, 24, 24, 54]
ast_nodes = test_utils.extract_node('''
def test(*, f, b): return f
test(f=24, b=33) #@
def test(a, *, f): return f
test(1, f=24) #@
def test(a, *, f=42): return f
test(1) #@
test(1, f=23) #@
def test(a, b, c=42, *args, f=24):
return f
test(1, 2, 3) #@
test(1, 2, 3, 4) #@
test(1, 2, 3, 4, 5, f=54) #@
''')
for node, expected_value in zip(ast_nodes, expected_values):
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, expected_value)
def test_kwargs(self):
expected = [
[('a', 1), ('b', 2), ('c', 3)],
[('a', 1)],
[('a', 'b')],
]
ast_nodes = test_utils.extract_node('''
def test(**kwargs):
return kwargs
test(a=1, b=2, c=3) #@
test(a=1) #@
test(**{'a': 'b'}) #@
''')
for node, expected_value in zip(ast_nodes, expected):
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Dict)
value = self._get_dict_value(inferred)
self.assertEqual(value, expected_value)
def test_kwargs_and_other_named_parameters(self):
ast_nodes = test_utils.extract_node('''
def test(a=42, b=24, **kwargs):
return kwargs
test(42, 24, c=3, d=4) #@
test(49, b=24, d=4) #@
test(a=42, b=33, c=3, d=42) #@
test(a=42, **{'c':42}) #@
''')
expected_values = [
[('c', 3), ('d', 4)],
[('d', 4)],
[('c', 3), ('d', 42)],
[('c', 42)],
]
for node, expected_value in zip(ast_nodes, expected_values):
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Dict)
value = self._get_dict_value(inferred)
self.assertEqual(value, expected_value)
def test_kwargs_access_by_name(self):
expected_values = [42, 42, 42, 24]
ast_nodes = test_utils.extract_node('''
def test(**kwargs):
return kwargs['f']
test(f=42) #@
test(**{'f': 42}) #@
test(**dict(f=42)) #@
def test(f=42, **kwargs):
return kwargs['l']
test(l=24) #@
''')
for ast_node, value in zip(ast_nodes, expected_values):
inferred = next(ast_node.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, value)
def test_infer_call_result_invalid_dunder_call_on_instance(self):
ast_nodes = test_utils.extract_node('''
class A:
__call__ = 42
class B:
__call__ = A()
class C:
__call = None
A() #@
B() #@
C() #@
''')
for node in ast_nodes:
inferred = next(node.infer())
self.assertRaises(InferenceError, next, inferred.infer_call_result(node))
def test_subscript_inference_error(self):
# Used to raise StopIteration
ast_node = test_utils.extract_node('''
class AttributeDict(dict):
def __getitem__(self, name):
return self
flow = AttributeDict()
flow['app'] = AttributeDict()
flow['app']['config'] = AttributeDict()
flow['app']['config']['doffing'] = AttributeDict() #@
''')
self.assertIsNone(util.safe_infer(ast_node.targets[0]))
def test_classmethod_inferred_by_context(self):
ast_node = test_utils.extract_node('''
class Super(object):
def instance(cls):
return cls()
instance = classmethod(instance)
class Sub(Super):
def method(self):
return self
# should see the Sub.instance() is returning a Sub
# instance, not a Super instance
Sub.instance().method() #@
''')
inferred = next(ast_node.infer())
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.name, 'Sub')
@test_utils.require_version('3.5')
def test_multiple_kwargs(self):
expected_value = [
('a', 1),
('b', 2),
('c', 3),
('d', 4),
('f', 42),
]
ast_node = test_utils.extract_node('''
def test(**kwargs):
return kwargs
test(a=1, b=2, **{'c': 3}, **{'d': 4}, f=42) #@
''')
inferred = next(ast_node.infer())
self.assertIsInstance(inferred, nodes.Dict)
value = self._get_dict_value(inferred)
self.assertEqual(value, expected_value)
def test_kwargs_are_overriden(self):
ast_nodes = test_utils.extract_node('''
def test(f):
return f
test(f=23, **{'f': 34}) #@
def test(f=None):
return f
test(f=23, **{'f':23}) #@
''')
for ast_node in ast_nodes:
inferred = next(ast_node.infer())
self.assertEqual(inferred, util.YES)
def test_fail_to_infer_args(self):
ast_nodes = test_utils.extract_node('''
def test(a, **kwargs): return a
test(*missing) #@
test(*object) #@
test(*1) #@
def test(**kwargs): return kwargs
test(**miss) #@
test(**(1, 2)) #@
test(**1) #@
test(**{misss:1}) #@
test(**{object:1}) #@
test(**{1:1}) #@
test(**{'a':1, 'a':1}) #@
def test(a): return a
test() #@
test(1, 2, 3) #@
from unknown import unknown
test(*unknown) #@
def test(*args): return args
test(*unknown) #@
''')
for node in ast_nodes:
inferred = next(node.infer())
self.assertEqual(inferred, util.YES)
class CallSiteTest(unittest.TestCase):
@staticmethod
def _call_site_from_call(call):
return arguments.CallSite.from_call(call)
def _test_call_site_pair(self, code, expected_args, expected_keywords):
ast_node = test_utils.extract_node(code)
call_site = self._call_site_from_call(ast_node)
self.assertEqual(len(call_site.positional_arguments), len(expected_args))
self.assertEqual([arg.value for arg in call_site.positional_arguments],
expected_args)
self.assertEqual(len(call_site.keyword_arguments), len(expected_keywords))
for keyword, value in expected_keywords.items():
self.assertIn(keyword, call_site.keyword_arguments)
self.assertEqual(call_site.keyword_arguments[keyword].value, value)
def _test_call_site(self, pairs):
for pair in pairs:
self._test_call_site_pair(*pair)
@test_utils.require_version('3.5')
def test_call_site_starred_args(self):
pairs = [
(
"f(*(1, 2), *(2, 3), *(3, 4), **{'a':1}, **{'b': 2})",
[1, 2, 2, 3, 3, 4],
{'a': 1, 'b': 2}
),
(
"f(1, 2, *(3, 4), 5, *(6, 7), f=24, **{'c':3})",
[1, 2, 3, 4, 5, 6, 7],
{'f':24, 'c': 3},
),
# Too many fs passed into.
(
"f(f=24, **{'f':24})", [], {},
),
]
self._test_call_site(pairs)
def test_call_site(self):
pairs = [
(
"f(1, 2)", [1, 2], {}
),
(
"f(1, 2, *(1, 2))", [1, 2, 1, 2], {}
),
(
"f(a=1, b=2, c=3)", [], {'a':1, 'b':2, 'c':3}
)
]
self._test_call_site(pairs)
def _test_call_site_valid_arguments(self, values, invalid):
for value in values:
ast_node = test_utils.extract_node(value)
call_site = self._call_site_from_call(ast_node)
self.assertEqual(call_site.has_invalid_arguments(), invalid)
def test_call_site_valid_arguments(self):
values = [
"f(*lala)", "f(*1)", "f(*object)",
]
self._test_call_site_valid_arguments(values, invalid=True)
values = [
"f()", "f(*(1, ))", "f(1, 2, *(2, 3))",
]
self._test_call_site_valid_arguments(values, invalid=False)
def test_duplicated_keyword_arguments(self):
ast_node = test_utils.extract_node('f(f=24, **{"f": 25})')
site = self._call_site_from_call(ast_node)
self.assertIn('f', site.duplicated_keywords)
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_lookup.py 0000666 0000000 0000000 00000031106 12646222644 017761 0 ustar 0000000 0000000 # 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 functools
import sys
import unittest
from astroid import builder
from astroid import exceptions
from astroid import nodes
from astroid import scoped_nodes
from astroid import test_utils
from astroid import util
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 = builder.parse(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]), 1)
self.assertEqual(len(astroid.lookup('a')[1]), 1)
b = astroid._locals['b'][1]
else:
self.assertEqual(len(astroid.lookup('b')[1]), 1)
self.assertEqual(len(astroid.lookup('a')[1]), 1)
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, functools.partial(next, b_infer))
func = astroid._locals['func'][0]
self.assertEqual(len(func.lookup('c')[1]), 1)
def test_module(self):
astroid = builder.parse('pass', __name__)
# built-in objects
none = next(astroid.ilookup('None'))
self.assertIsNone(none.value)
obj = next(astroid.ilookup('object'))
self.assertIsInstance(obj, nodes.ClassDef)
self.assertEqual(obj.name, 'object')
self.assertRaises(exceptions.InferenceError,
functools.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 = builder.parse(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(exceptions.InferenceError,
functools.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.ClassDef), 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.ClassDef)
self.assertEqual(obj.name, 'object')
self.assertRaises(exceptions.InferenceError,
functools.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 = builder.parse("""
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 = builder.parse("""
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 = builder.parse("""
ten = [ var for var in range(10) ]
var
""")
var = astroid.body[1].value
if sys.version_info < (3, 0):
self.assertEqual(var.inferred(), [util.YES])
else:
self.assertRaises(exceptions.UnresolvableName, var.inferred)
def test_dict_comps(self):
astroid = builder.parse("""
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 = builder.parse("""
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 = builder.parse("""
ten = { var for var in range(10) }
var
""")
var = astroid.body[1].value
self.assertRaises(exceptions.UnresolvableName, var.inferred)
def test_generator_attributes(self):
tree = builder.parse("""
def count():
"test"
yield 0
iterer = count()
num = iterer.next()
""")
next_node = tree.body[2].value.func
gener = next_node.expr.inferred()[0]
if sys.version_info < (3, 0):
self.assertIsInstance(gener.getattr('next')[0], nodes.FunctionDef)
else:
self.assertIsInstance(gener.getattr('__next__')[0], nodes.FunctionDef)
self.assertIsInstance(gener.getattr('send')[0], nodes.FunctionDef)
self.assertIsInstance(gener.getattr('throw')[0], nodes.FunctionDef)
self.assertIsInstance(gener.getattr('close')[0], nodes.FunctionDef)
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.parse(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(exceptions.NotFoundError, p3.getattr, '__name__')
def test_function_module_special(self):
astroid = builder.parse('''
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(scoped_nodes.builtin_lookup('__dict__')[1], ())
intstmts = scoped_nodes.builtin_lookup('int')[1]
self.assertEqual(len(intstmts), 1)
self.assertIsInstance(intstmts[0], nodes.ClassDef)
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, functools.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.FunctionDef)
self.assertRaises(StopIteration, functools.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 = builder.parse(code, __name__)
it = astroid['Test']['__init__'].ilookup('FileA')
obj = next(it)
self.assertIsInstance(obj, nodes.ClassDef)
self.assertRaises(StopIteration, functools.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 = builder.parse(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()
astroid-1.4.4/astroid/tests/unittest_manager.py 0000666 0000000 0000000 00000021114 12646222644 020060 0 ustar 0000000 0000000 # 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 platform
import sys
import unittest
import six
from astroid import exceptions
from astroid import manager
from astroid.tests import resources
BUILTINS = six.moves.builtins.__name__
def _get_file_from_object(obj):
if platform.python_implementation() == 'Jython':
return obj.__file__.split("$py.class")[0] + ".py"
if sys.version_info > (3, 0):
return obj.__file__
if not obj.__file__.endswith(".py"):
return obj.__file__[:-1]
return obj.__file__
class AstroidManagerTest(resources.SysPathSetup,
resources.AstroidCacheSetupMixin,
unittest.TestCase):
def setUp(self):
super(AstroidManagerTest, self).setUp()
self.manager = manager.AstroidManager()
self.manager.clear_cache(self._builtins) # take care of borg
def test_ast_from_file(self):
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):
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):
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):
self.assertRaises(exceptions.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):
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):
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):
self.assertRaises(exceptions.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.source_file.endswith(end),
"%s doesn't endswith %s" % (module.source_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"""
self.assertEqual(
_get_file_from_object(unittest),
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(exceptions.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(exceptions.AstroidBuildingException,
self.manager.ast_from_class, None)
def testFailedImportHooks(self):
def hook(modname):
if modname == 'foo.bar':
return unittest
else:
raise exceptions.AstroidBuildingException()
with self.assertRaises(exceptions.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(exceptions.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 = manager.AstroidManager()
built = first_manager.ast_from_module_name(BUILTINS)
second_manager = manager.AstroidManager()
second_built = second_manager.ast_from_module_name(BUILTINS)
self.assertIs(built, second_built)
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_modutils.py 0000666 0000000 0000000 00000025316 12646222644 020316 0 ustar 0000000 0000000 # 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 astroid import modutils
from astroid.tests import resources
def _get_file_from_object(obj):
return modutils._path_from_filename(obj.__file__)
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):
from xml.etree import ElementTree
self.assertEqual(modutils.modpath_from_file(ElementTree.__file__),
['xml', 'etree', 'ElementTree'])
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):
filename = _get_file_from_object(modutils)
result = modutils.file_from_modpath(['astroid', 'modutils'])
self.assertEqual(os.path.realpath(result), os.path.realpath(filename))
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):
filename = _get_file_from_object(os.path)
self.assertEqual(modutils.get_source_file(os.path.__file__),
os.path.normpath(filename))
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_datetime(self):
# This is an interesting example, since datetime, on pypy,
# is under lib_pypy, rather than the usual Lib directory.
self.assertTrue(modutils.is_standard_module('datetime'))
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)
self.assertEqual(modutils.is_standard_module('marshal'), True)
def test_nonstandard(self):
self.assertEqual(modutils.is_standard_module('astroid'), False)
def test_unknown(self):
self.assertEqual(modutils.is_standard_module('unknown'), False)
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 xml import etree
# using a subpackage/submodule path as std_path argument
self.assertEqual(modutils.is_standard_module('xml.etree', etree.__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('xml.whatever', etree.__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 xml.etree import ElementTree
self.assertEqual(modutils.is_relative('ElementPath', ElementTree.__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):
package = resources.find('data/find_test')
modules = set(modutils.get_module_files(package, []))
expected = ['__init__.py', 'module.py', 'module2.py',
'noendingnewline.py', 'nonregr.py']
self.assertEqual(modules,
{os.path.join(package, x) for x in expected})
def test_load_module_set_attribute(self):
import xml.etree.ElementTree
import xml
del xml.etree.ElementTree
del sys.modules['xml.etree.ElementTree']
m = modutils.load_module_from_modpath(['xml', 'etree', 'ElementTree'])
self.assertTrue(hasattr(xml, 'etree'))
self.assertTrue(hasattr(xml.etree, 'ElementTree'))
self.assertTrue(m is xml.etree.ElementTree)
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_nodes.py 0000666 0000000 0000000 00000064071 12646222644 017567 0 ustar 0000000 0000000 # 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 textwrap
import unittest
import warnings
import six
from astroid import bases
from astroid import builder
from astroid import context as contextmod
from astroid import exceptions
from astroid import node_classes
from astroid import nodes
from astroid import parse
from astroid import util
from astroid import test_utils
from astroid import transforms
from astroid.tests import resources
abuilder = builder.AstroidBuilder()
BUILTINS = six.moves.builtins.__name__
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_as_string_for_list_containing_uninferable(self):
node = test_utils.extract_node('''
def foo(arg):
bar = [arg] * 1
''')
binop = node.body[0].value
inferred = next(binop.infer())
self.assertEqual(inferred.as_string(), '[Uninferable]')
self.assertEqual(binop.as_string(), '([arg]) * (1)')
def test_frozenset_as_string(self):
nodes = test_utils.extract_node('''
frozenset((1, 2, 3)) #@
frozenset({1, 2, 3}) #@
frozenset([1, 2, 3,]) #@
frozenset(None) #@
frozenset(1) #@
''')
nodes = [next(node.infer()) for node in nodes]
self.assertEqual(nodes[0].as_string(), 'frozenset((1, 2, 3))')
self.assertEqual(nodes[1].as_string(), 'frozenset({1, 2, 3})')
self.assertEqual(nodes[2].as_string(), 'frozenset([1, 2, 3])')
self.assertNotEqual(nodes[3].as_string(), 'frozenset(None)')
self.assertNotEqual(nodes[4].as_string(), 'frozenset(1)')
@test_utils.require_version(minver='3.0')
def test_func_signature_issue_185(self):
code = textwrap.dedent('''
def test(a, b, c=42, *, x=42, **kwargs):
print(a, b, c, args)
''')
node = parse(code)
self.assertEqual(node.as_string().strip(), code.strip())
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 = builder.parse(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))
@unittest.skipIf(six.PY3, "Python 2 specific test.")
class TryExcept2xNodeTest(_NodeTest):
CODE = """
try:
hello
except AttributeError, (retval, desc):
pass
"""
def test_tuple_attribute(self):
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):
namenode = next(self.module.igetattr('NameNode'))
self.assertTrue(isinstance(namenode, nodes.ClassDef), namenode)
self.assertEqual(namenode.root().name, 'astroid.node_classes')
self.assertEqual(namenode.qname(), 'astroid.node_classes.Name')
self.assertEqual(namenode.pytype(), '%s.type' % BUILTINS)
abspath = next(self.module2.igetattr('abspath'))
self.assertTrue(isinstance(abspath, nodes.FunctionDef), 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['NameNode']
self.assertEqual(from_.real_name('NameNode'), 'Name')
imp_ = self.module['os']
self.assertEqual(imp_.real_name('os'), 'os')
self.assertRaises(exceptions.NotFoundError, imp_.real_name, 'os.path')
imp_ = self.module['NameNode']
self.assertEqual(imp_.real_name('NameNode'), 'Name')
self.assertRaises(exceptions.NotFoundError, imp_.real_name, 'Name')
imp_ = self.module2['YO']
self.assertEqual(imp_.real_name('YO'), 'YO')
self.assertRaises(exceptions.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['NameNode']
self.assertEqual(ast.as_string(), "from astroid.node_classes import Name as NameNode")
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 = builder.parse(code)
handler_type = astroid.body[1].handlers[0].type
excs = list(node_classes.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.ClassDef)
self.assertEqual(excs[0].name, 'PickleError')
self.assertIs(excs[-1], util.YES)
def test_absolute_import(self):
astroid = resources.build_file('data/absimport.py')
ctx = contextmod.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.source_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.ClassDef)
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(exceptions.AstroidBuildingException):
builder.parse(code)
else:
ast = builder.parse(code)
assign_true = ast['True']
self.assertIsInstance(assign_true, nodes.AssignName)
self.assertEqual(assign_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 = builder.parse('''
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)
class UnboundMethodNodeTest(unittest.TestCase):
def test_no_super_getattr(self):
# This is a test for issue
# https://bitbucket.org/logilab/astroid/issue/91, which tests
# that UnboundMethod doesn't call super when doing .getattr.
ast = builder.parse('''
class A(object):
def test(self):
pass
meth = A.test
''')
node = next(ast['meth'].infer())
with self.assertRaises(exceptions.NotFoundError):
node.getattr('__missssing__')
name = node.getattr('__name__')[0]
self.assertIsInstance(name, nodes.Const)
self.assertEqual(name.value, 'test')
class BoundMethodNodeTest(unittest.TestCase):
def test_is_property(self):
ast = builder.parse('''
import abc
def cached_property():
# Not a real decorator, but we don't care
pass
def reify():
# Same as cached_property
pass
def lazy_property():
pass
def lazyproperty():
pass
def lazy(): pass
class A(object):
@property
def builtin_property(self):
return 42
@abc.abstractproperty
def abc_property(self):
return 42
@cached_property
def cached_property(self): return 42
@reify
def reified(self): return 42
@lazy_property
def lazy_prop(self): return 42
@lazyproperty
def lazyprop(self): return 42
def not_prop(self): pass
@lazy
def decorated_with_lazy(self): return 42
cls = A()
builtin_property = cls.builtin_property
abc_property = cls.abc_property
cached_p = cls.cached_property
reified = cls.reified
not_prop = cls.not_prop
lazy_prop = cls.lazy_prop
lazyprop = cls.lazyprop
decorated_with_lazy = cls.decorated_with_lazy
''')
for prop in ('builtin_property', 'abc_property', 'cached_p', 'reified',
'lazy_prop', 'lazyprop', 'decorated_with_lazy'):
inferred = next(ast[prop].infer())
self.assertIsInstance(inferred, nodes.Const, prop)
self.assertEqual(inferred.value, 42, prop)
inferred = next(ast['not_prop'].infer())
self.assertIsInstance(inferred, bases.BoundMethod)
class AliasesTest(unittest.TestCase):
def setUp(self):
self.transformer = transforms.TransformVisitor()
def parse_transform(self, code):
module = parse(code, apply_transforms=False)
return self.transformer.visit(module)
def test_aliases(self):
def test_from(node):
node.names = node.names + [('absolute_import', None)]
return node
def test_class(node):
node.name = 'Bar'
return node
def test_function(node):
node.name = 'another_test'
return node
def test_callfunc(node):
if node.func.name == 'Foo':
node.func.name = 'Bar'
return node
def test_assname(node):
if node.name == 'foo':
n = nodes.AssignName()
n.name = 'bar'
return n
def test_assattr(node):
if node.attrname == 'a':
node.attrname = 'b'
return node
def test_getattr(node):
if node.attrname == 'a':
node.attrname = 'b'
return node
def test_genexpr(node):
if node.elt.value == 1:
node.elt = nodes.Const(2)
return node
self.transformer.register_transform(nodes.From, test_from)
self.transformer.register_transform(nodes.Class, test_class)
self.transformer.register_transform(nodes.Function, test_function)
self.transformer.register_transform(nodes.CallFunc, test_callfunc)
self.transformer.register_transform(nodes.AssName, test_assname)
self.transformer.register_transform(nodes.AssAttr, test_assattr)
self.transformer.register_transform(nodes.Getattr, test_getattr)
self.transformer.register_transform(nodes.GenExpr, test_genexpr)
string = '''
from __future__ import print_function
class Foo: pass
def test(a): return a
foo = Foo()
foo.a = test(42)
foo.a
(1 for _ in range(0, 42))
'''
module = self.parse_transform(string)
self.assertEqual(len(module.body[0].names), 2)
self.assertIsInstance(module.body[0], nodes.ImportFrom)
self.assertEqual(module.body[1].name, 'Bar')
self.assertIsInstance(module.body[1], nodes.ClassDef)
self.assertEqual(module.body[2].name, 'another_test')
self.assertIsInstance(module.body[2], nodes.FunctionDef)
self.assertEqual(module.body[3].targets[0].name, 'bar')
self.assertIsInstance(module.body[3].targets[0], nodes.AssignName)
self.assertEqual(module.body[3].value.func.name, 'Bar')
self.assertIsInstance(module.body[3].value, nodes.Call)
self.assertEqual(module.body[4].targets[0].attrname, 'b')
self.assertIsInstance(module.body[4].targets[0], nodes.AssignAttr)
self.assertIsInstance(module.body[5], nodes.Expr)
self.assertEqual(module.body[5].value.attrname, 'b')
self.assertIsInstance(module.body[5].value, nodes.Attribute)
self.assertEqual(module.body[6].value.elt.value, 2)
self.assertIsInstance(module.body[6].value, nodes.GeneratorExp)
@unittest.skipIf(six.PY3, "Python 3 doesn't have Repr nodes.")
def test_repr(self):
def test_backquote(node):
node.value.name = 'bar'
return node
self.transformer.register_transform(nodes.Backquote, test_backquote)
module = self.parse_transform('`foo`')
self.assertEqual(module.body[0].value.value.name, 'bar')
self.assertIsInstance(module.body[0].value, nodes.Repr)
class DeprecationWarningsTest(unittest.TestCase):
def test_asstype_warnings(self):
string = '''
class C: pass
c = C()
with warnings.catch_warnings(record=True) as w:
pass
'''
module = parse(string)
filter_stmts_mixin = module.body[0]
assign_type_mixin = module.body[1].targets[0]
parent_assign_type_mixin = module.body[2]
warnings.simplefilter('always')
with warnings.catch_warnings(record=True) as w:
filter_stmts_mixin.ass_type()
self.assertIsInstance(w[0].message, PendingDeprecationWarning)
with warnings.catch_warnings(record=True) as w:
assign_type_mixin.ass_type()
self.assertIsInstance(w[0].message, PendingDeprecationWarning)
with warnings.catch_warnings(record=True) as w:
parent_assign_type_mixin.ass_type()
self.assertIsInstance(w[0].message, PendingDeprecationWarning)
def test_isinstance_warnings(self):
msg_format = ("%r is deprecated and slated for removal in astroid "
"2.0, use %r instead")
for cls in (nodes.Discard, nodes.Backquote, nodes.AssName,
nodes.AssAttr, nodes.Getattr, nodes.CallFunc, nodes.From):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
isinstance(42, cls)
self.assertIsInstance(w[0].message, PendingDeprecationWarning)
actual_msg = msg_format % (cls.__class__.__name__, cls.__wrapped__.__name__)
self.assertEqual(str(w[0].message), actual_msg)
@test_utils.require_version('3.5')
class Python35AsyncTest(unittest.TestCase):
def test_async_await_keywords(self):
async_def, async_for, async_with, await_node = test_utils.extract_node('''
async def func(): #@
async for i in range(10): #@
f = __(await i)
async with test(): #@
pass
''')
self.assertIsInstance(async_def, nodes.AsyncFunctionDef)
self.assertIsInstance(async_for, nodes.AsyncFor)
self.assertIsInstance(async_with, nodes.AsyncWith)
self.assertIsInstance(await_node, nodes.Await)
self.assertIsInstance(await_node.value, nodes.Name)
def _test_await_async_as_string(self, code):
ast_node = parse(code)
self.assertEqual(ast_node.as_string().strip(), code.strip())
def test_await_as_string(self):
code = textwrap.dedent('''
async def function():
await 42
''')
self._test_await_async_as_string(code)
def test_asyncwith_as_string(self):
code = textwrap.dedent('''
async def function():
async with (42):
pass
''')
self._test_await_async_as_string(code)
def test_asyncfor_as_string(self):
code = textwrap.dedent('''
async def function():
async for i in range(10):
await 42
''')
self._test_await_async_as_string(code)
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_objects.py 0000666 0000000 0000000 00000050272 12646222644 020106 0 ustar 0000000 0000000 # 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 bases
from astroid import exceptions
from astroid import nodes
from astroid import objects
from astroid import test_utils
class ObjectsTest(unittest.TestCase):
def test_frozenset(self):
node = test_utils.extract_node("""
frozenset({1: 2, 2: 3}) #@
""")
infered = next(node.infer())
self.assertIsInstance(infered, objects.FrozenSet)
self.assertEqual(infered.pytype(), "%s.frozenset" % bases.BUILTINS)
itered = infered.itered()
self.assertEqual(len(itered), 2)
self.assertIsInstance(itered[0], nodes.Const)
self.assertEqual([const.value for const in itered], [1, 2])
proxied = infered._proxied
self.assertEqual(infered.qname(), "%s.frozenset" % bases.BUILTINS)
self.assertIsInstance(proxied, nodes.ClassDef)
class SuperTests(unittest.TestCase):
def test_inferring_super_outside_methods(self):
ast_nodes = test_utils.extract_node('''
class Module(object):
pass
class StaticMethod(object):
@staticmethod
def static():
# valid, but we don't bother with it.
return super(StaticMethod, StaticMethod) #@
# super outside methods aren't inferred
super(Module, Module) #@
# no argument super is not recognised outside methods as well.
super() #@
''')
in_static = next(ast_nodes[0].value.infer())
self.assertIsInstance(in_static, bases.Instance)
self.assertEqual(in_static.qname(), "%s.super" % bases.BUILTINS)
module_level = next(ast_nodes[1].infer())
self.assertIsInstance(module_level, bases.Instance)
self.assertEqual(in_static.qname(), "%s.super" % bases.BUILTINS)
no_arguments = next(ast_nodes[2].infer())
self.assertIsInstance(no_arguments, bases.Instance)
self.assertEqual(no_arguments.qname(), "%s.super" % bases.BUILTINS)
def test_inferring_unbound_super_doesnt_work(self):
node = test_utils.extract_node('''
class Test(object):
def __init__(self):
super(Test) #@
''')
unbounded = next(node.infer())
self.assertIsInstance(unbounded, bases.Instance)
self.assertEqual(unbounded.qname(), "%s.super" % bases.BUILTINS)
def test_use_default_inference_on_not_inferring_args(self):
ast_nodes = test_utils.extract_node('''
class Test(object):
def __init__(self):
super(Lala, self) #@
super(Test, lala) #@
''')
first = next(ast_nodes[0].infer())
self.assertIsInstance(first, bases.Instance)
self.assertEqual(first.qname(), "%s.super" % bases.BUILTINS)
second = next(ast_nodes[1].infer())
self.assertIsInstance(second, bases.Instance)
self.assertEqual(second.qname(), "%s.super" % bases.BUILTINS)
@test_utils.require_version(maxver='3.0')
def test_super_on_old_style_class(self):
# super doesn't work on old style class, but leave
# that as an error for pylint. We'll infer Super objects,
# but every call will result in a failure at some point.
node = test_utils.extract_node('''
class OldStyle:
def __init__(self):
super(OldStyle, self) #@
''')
old = next(node.infer())
self.assertIsInstance(old, objects.Super)
self.assertIsInstance(old.mro_pointer, nodes.ClassDef)
self.assertEqual(old.mro_pointer.name, 'OldStyle')
with self.assertRaises(exceptions.SuperError) as cm:
old.super_mro()
self.assertEqual(str(cm.exception),
"Unable to call super on old-style classes.")
@test_utils.require_version(minver='3.0')
def test_no_arguments_super(self):
ast_nodes = test_utils.extract_node('''
class First(object): pass
class Second(First):
def test(self):
super() #@
@classmethod
def test_classmethod(cls):
super() #@
''')
first = next(ast_nodes[0].infer())
self.assertIsInstance(first, objects.Super)
self.assertIsInstance(first.type, bases.Instance)
self.assertEqual(first.type.name, 'Second')
self.assertIsInstance(first.mro_pointer, nodes.ClassDef)
self.assertEqual(first.mro_pointer.name, 'Second')
second = next(ast_nodes[1].infer())
self.assertIsInstance(second, objects.Super)
self.assertIsInstance(second.type, nodes.ClassDef)
self.assertEqual(second.type.name, 'Second')
self.assertIsInstance(second.mro_pointer, nodes.ClassDef)
self.assertEqual(second.mro_pointer.name, 'Second')
def test_super_simple_cases(self):
ast_nodes = test_utils.extract_node('''
class First(object): pass
class Second(First): pass
class Third(First):
def test(self):
super(Third, self) #@
super(Second, self) #@
# mro position and the type
super(Third, Third) #@
super(Third, Second) #@
super(Fourth, Fourth) #@
class Fourth(Third):
pass
''')
# .type is the object which provides the mro.
# .mro_pointer is the position in the mro from where
# the lookup should be done.
# super(Third, self)
first = next(ast_nodes[0].infer())
self.assertIsInstance(first, objects.Super)
self.assertIsInstance(first.type, bases.Instance)
self.assertEqual(first.type.name, 'Third')
self.assertIsInstance(first.mro_pointer, nodes.ClassDef)
self.assertEqual(first.mro_pointer.name, 'Third')
# super(Second, self)
second = next(ast_nodes[1].infer())
self.assertIsInstance(second, objects.Super)
self.assertIsInstance(second.type, bases.Instance)
self.assertEqual(second.type.name, 'Third')
self.assertIsInstance(first.mro_pointer, nodes.ClassDef)
self.assertEqual(second.mro_pointer.name, 'Second')
# super(Third, Third)
third = next(ast_nodes[2].infer())
self.assertIsInstance(third, objects.Super)
self.assertIsInstance(third.type, nodes.ClassDef)
self.assertEqual(third.type.name, 'Third')
self.assertIsInstance(third.mro_pointer, nodes.ClassDef)
self.assertEqual(third.mro_pointer.name, 'Third')
# super(Third, second)
fourth = next(ast_nodes[3].infer())
self.assertIsInstance(fourth, objects.Super)
self.assertIsInstance(fourth.type, nodes.ClassDef)
self.assertEqual(fourth.type.name, 'Second')
self.assertIsInstance(fourth.mro_pointer, nodes.ClassDef)
self.assertEqual(fourth.mro_pointer.name, 'Third')
# Super(Fourth, Fourth)
fifth = next(ast_nodes[4].infer())
self.assertIsInstance(fifth, objects.Super)
self.assertIsInstance(fifth.type, nodes.ClassDef)
self.assertEqual(fifth.type.name, 'Fourth')
self.assertIsInstance(fifth.mro_pointer, nodes.ClassDef)
self.assertEqual(fifth.mro_pointer.name, 'Fourth')
def test_super_infer(self):
node = test_utils.extract_node('''
class Super(object):
def __init__(self):
super(Super, self) #@
''')
inferred = next(node.infer())
self.assertIsInstance(inferred, objects.Super)
reinferred = next(inferred.infer())
self.assertIsInstance(reinferred, objects.Super)
self.assertIs(inferred, reinferred)
def test_inferring_invalid_supers(self):
ast_nodes = test_utils.extract_node('''
class Super(object):
def __init__(self):
# MRO pointer is not a type
super(1, self) #@
# MRO type is not a subtype
super(Super, 1) #@
# self is not a subtype of Bupper
super(Bupper, self) #@
class Bupper(Super):
pass
''')
first = next(ast_nodes[0].infer())
self.assertIsInstance(first, objects.Super)
with self.assertRaises(exceptions.SuperError) as cm:
first.super_mro()
self.assertEqual(str(cm.exception), "The first super argument must be type.")
for node in ast_nodes[1:]:
inferred = next(node.infer())
self.assertIsInstance(inferred, objects.Super, node)
with self.assertRaises(exceptions.SuperArgumentTypeError) as cm:
inferred.super_mro()
self.assertEqual(str(cm.exception),
"super(type, obj): obj must be an instance "
"or subtype of type", node)
def test_proxied(self):
node = test_utils.extract_node('''
class Super(object):
def __init__(self):
super(Super, self) #@
''')
infered = next(node.infer())
proxied = infered._proxied
self.assertEqual(proxied.qname(), "%s.super" % bases.BUILTINS)
self.assertIsInstance(proxied, nodes.ClassDef)
def test_super_bound_model(self):
ast_nodes = test_utils.extract_node('''
class First(object):
def method(self):
pass
@classmethod
def class_method(cls):
pass
class Super_Type_Type(First):
def method(self):
super(Super_Type_Type, Super_Type_Type).method #@
super(Super_Type_Type, Super_Type_Type).class_method #@
@classmethod
def class_method(cls):
super(Super_Type_Type, Super_Type_Type).method #@
super(Super_Type_Type, Super_Type_Type).class_method #@
class Super_Type_Object(First):
def method(self):
super(Super_Type_Object, self).method #@
super(Super_Type_Object, self).class_method #@
''')
# Super(type, type) is the same for both functions and classmethods.
first = next(ast_nodes[0].infer())
self.assertIsInstance(first, nodes.FunctionDef)
self.assertEqual(first.name, 'method')
second = next(ast_nodes[1].infer())
self.assertIsInstance(second, bases.BoundMethod)
self.assertEqual(second.bound.name, 'First')
self.assertEqual(second.type, 'classmethod')
third = next(ast_nodes[2].infer())
self.assertIsInstance(third, nodes.FunctionDef)
self.assertEqual(third.name, 'method')
fourth = next(ast_nodes[3].infer())
self.assertIsInstance(fourth, bases.BoundMethod)
self.assertEqual(fourth.bound.name, 'First')
self.assertEqual(fourth.type, 'classmethod')
# Super(type, obj) can lead to different attribute bindings
# depending on the type of the place where super was called.
fifth = next(ast_nodes[4].infer())
self.assertIsInstance(fifth, bases.BoundMethod)
self.assertEqual(fifth.bound.name, 'First')
self.assertEqual(fifth.type, 'method')
sixth = next(ast_nodes[5].infer())
self.assertIsInstance(sixth, bases.BoundMethod)
self.assertEqual(sixth.bound.name, 'First')
self.assertEqual(sixth.type, 'classmethod')
def test_super_getattr_single_inheritance(self):
ast_nodes = test_utils.extract_node('''
class First(object):
def test(self): pass
class Second(First):
def test2(self): pass
class Third(Second):
test3 = 42
def __init__(self):
super(Third, self).test2 #@
super(Third, self).test #@
# test3 is local, no MRO lookup is done.
super(Third, self).test3 #@
super(Third, self) #@
# Unbounds.
super(Third, Third).test2 #@
super(Third, Third).test #@
''')
first = next(ast_nodes[0].infer())
self.assertIsInstance(first, bases.BoundMethod)
self.assertEqual(first.bound.name, 'Second')
second = next(ast_nodes[1].infer())
self.assertIsInstance(second, bases.BoundMethod)
self.assertEqual(second.bound.name, 'First')
with self.assertRaises(exceptions.InferenceError):
next(ast_nodes[2].infer())
fourth = next(ast_nodes[3].infer())
with self.assertRaises(exceptions.NotFoundError):
fourth.getattr('test3')
with self.assertRaises(exceptions.NotFoundError):
next(fourth.igetattr('test3'))
first_unbound = next(ast_nodes[4].infer())
self.assertIsInstance(first_unbound, nodes.FunctionDef)
self.assertEqual(first_unbound.name, 'test2')
self.assertEqual(first_unbound.parent.name, 'Second')
second_unbound = next(ast_nodes[5].infer())
self.assertIsInstance(second_unbound, nodes.FunctionDef)
self.assertEqual(second_unbound.name, 'test')
self.assertEqual(second_unbound.parent.name, 'First')
def test_super_invalid_mro(self):
node = test_utils.extract_node('''
class A(object):
test = 42
class Super(A, A):
def __init__(self):
super(Super, self) #@
''')
inferred = next(node.infer())
with self.assertRaises(exceptions.NotFoundError):
next(inferred.getattr('test'))
def test_super_complex_mro(self):
ast_nodes = test_utils.extract_node('''
class A(object):
def spam(self): return "A"
def foo(self): return "A"
@staticmethod
def static(self): pass
class B(A):
def boo(self): return "B"
def spam(self): return "B"
class C(A):
def boo(self): return "C"
class E(C, B):
def __init__(self):
super(E, self).boo #@
super(C, self).boo #@
super(E, self).spam #@
super(E, self).foo #@
super(E, self).static #@
''')
first = next(ast_nodes[0].infer())
self.assertIsInstance(first, bases.BoundMethod)
self.assertEqual(first.bound.name, 'C')
second = next(ast_nodes[1].infer())
self.assertIsInstance(second, bases.BoundMethod)
self.assertEqual(second.bound.name, 'B')
third = next(ast_nodes[2].infer())
self.assertIsInstance(third, bases.BoundMethod)
self.assertEqual(third.bound.name, 'B')
fourth = next(ast_nodes[3].infer())
self.assertEqual(fourth.bound.name, 'A')
static = next(ast_nodes[4].infer())
self.assertIsInstance(static, nodes.FunctionDef)
self.assertEqual(static.parent.scope().name, 'A')
def test_super_data_model(self):
ast_nodes = test_utils.extract_node('''
class X(object): pass
class A(X):
def __init__(self):
super(A, self) #@
super(A, A) #@
super(X, A) #@
''')
first = next(ast_nodes[0].infer())
thisclass = first.getattr('__thisclass__')[0]
self.assertIsInstance(thisclass, nodes.ClassDef)
self.assertEqual(thisclass.name, 'A')
selfclass = first.getattr('__self_class__')[0]
self.assertIsInstance(selfclass, nodes.ClassDef)
self.assertEqual(selfclass.name, 'A')
self_ = first.getattr('__self__')[0]
self.assertIsInstance(self_, bases.Instance)
self.assertEqual(self_.name, 'A')
cls = first.getattr('__class__')[0]
self.assertEqual(cls, first._proxied)
second = next(ast_nodes[1].infer())
thisclass = second.getattr('__thisclass__')[0]
self.assertEqual(thisclass.name, 'A')
self_ = second.getattr('__self__')[0]
self.assertIsInstance(self_, nodes.ClassDef)
self.assertEqual(self_.name, 'A')
third = next(ast_nodes[2].infer())
thisclass = third.getattr('__thisclass__')[0]
self.assertEqual(thisclass.name, 'X')
selfclass = third.getattr('__self_class__')[0]
self.assertEqual(selfclass.name, 'A')
def assertEqualMro(self, klass, expected_mro):
self.assertEqual(
[member.name for member in klass.super_mro()],
expected_mro)
def test_super_mro(self):
ast_nodes = test_utils.extract_node('''
class A(object): pass
class B(A): pass
class C(A): pass
class E(C, B):
def __init__(self):
super(E, self) #@
super(C, self) #@
super(B, self) #@
super(B, 1) #@
super(1, B) #@
''')
first = next(ast_nodes[0].infer())
self.assertEqualMro(first, ['C', 'B', 'A', 'object'])
second = next(ast_nodes[1].infer())
self.assertEqualMro(second, ['B', 'A', 'object'])
third = next(ast_nodes[2].infer())
self.assertEqualMro(third, ['A', 'object'])
fourth = next(ast_nodes[3].infer())
with self.assertRaises(exceptions.SuperError):
fourth.super_mro()
fifth = next(ast_nodes[4].infer())
with self.assertRaises(exceptions.SuperError):
fifth.super_mro()
def test_super_yes_objects(self):
ast_nodes = test_utils.extract_node('''
from collections import Missing
class A(object):
def __init__(self):
super(Missing, self) #@
super(A, Missing) #@
''')
first = next(ast_nodes[0].infer())
self.assertIsInstance(first, bases.Instance)
second = next(ast_nodes[1].infer())
self.assertIsInstance(second, bases.Instance)
def test_super_invalid_types(self):
node = test_utils.extract_node('''
import collections
class A(object):
def __init__(self):
super(A, collections) #@
''')
inferred = next(node.infer())
with self.assertRaises(exceptions.SuperError):
inferred.super_mro()
with self.assertRaises(exceptions.SuperArgumentTypeError):
inferred.super_mro()
def test_super_pytype_display_type_name(self):
node = test_utils.extract_node('''
class A(object):
def __init__(self):
super(A, self) #@
''')
inferred = next(node.infer())
self.assertEqual(inferred.pytype(), "%s.super" % bases.BUILTINS)
self.assertEqual(inferred.display_type(), 'Super of')
self.assertEqual(inferred.name, 'A')
def test_super_properties(self):
node = test_utils.extract_node('''
class Foo(object):
@property
def dict(self):
return 42
class Bar(Foo):
@property
def dict(self):
return super(Bar, self).dict
Bar().dict
''')
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, 42)
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_peephole.py 0000666 0000000 0000000 00000007426 12646170047 020260 0 ustar 0000000 0000000 # 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 builder
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 = builder.parse("""
'1' + '2' + '3'
""")
self.assertIsInstance(module.body[0], astroid.Expr)
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()
astroid-1.4.4/astroid/tests/unittest_protocols.py 0000666 0000000 0000000 00000015134 12646222644 020477 0 ustar 0000000 0000000 # 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 contextlib
import unittest
import astroid
from astroid.test_utils import extract_node, require_version
from astroid import InferenceError
from astroid import nodes
from astroid import util
from astroid.node_classes import AssignName, Const, Name, Starred
@contextlib.contextmanager
def _add_transform(manager, node, transform, predicate=None):
manager.register_transform(node, transform, predicate)
try:
yield
finally:
manager.unregister_transform(node, transform, predicate)
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(AssignName))
assigned = list(for1_assnode.assigned_stmts())
self.assertConstNodesEqual([1, 2, 3], assigned)
for2_assnode = next(assign_stmts[1].nodes_of_class(AssignName))
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 = next(for1_starred.assigned_stmts())
self.assertEqual(assigned, util.YES)
def _get_starred_stmts(self, code):
assign_stmt = extract_node("{} #@".format(code))
starred = next(assign_stmt.nodes_of_class(Starred))
return next(starred.assigned_stmts())
def _helper_starred_expected_const(self, code, expected):
stmts = self._get_starred_stmts(code)
self.assertIsInstance(stmts, nodes.List)
stmts = stmts.elts
self.assertConstNodesEqual(expected, stmts)
def _helper_starred_expected(self, code, expected):
stmts = self._get_starred_stmts(code)
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) #@", util.YES)
# Not something inferrable
self._helper_starred_expected("a, *b = balou() #@", util.YES)
# In function, unknown.
self._helper_starred_expected("""
def test(arg):
head, *tail = arg #@""", util.YES)
# These cases aren't worth supporting.
self._helper_starred_expected(
"a, (*b, c), d = (1, (2, 3, 4), 5) #@", util.YES)
@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) #@")
# 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(AssignName))
assigned = list(simple_assnode.assigned_stmts())
self.assertNameNodesEqual(['a'], assigned)
assnames = assign_stmts[1].nodes_of_class(AssignName)
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)
def test_sequence_assigned_stmts_not_accepting_empty_node(self):
def transform(node):
node.root().locals['__all__'] = [node.value]
manager = astroid.MANAGER
with _add_transform(manager, astroid.Assign, transform):
module = astroid.parse('''
__all__ = ['a']
''')
module.wildcard_import_names()
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_python3.py 0000666 0000000 0000000 00000021506 12646170047 020056 0 ustar 0000000 0000000 # 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 import nodes
from astroid.node_classes import Assign, Expr, YieldFrom, Name, Const
from astroid.builder import AstroidBuilder
from astroid.scoped_nodes import ClassDef, FunctionDef
from astroid.test_utils import require_version, extract_node
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.assign_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, FunctionDef)
yieldfrom_stmt = func.body[0]
self.assertIsInstance(yieldfrom_stmt, Expr)
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, FunctionDef)
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, ClassDef)
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, ClassDef)
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, ClassDef)
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, ClassDef)
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)
@require_version('3.0')
def test_annotation_as_string(self):
code1 = dedent('''
def test(a, b:int=4, c=2, f:'lala'=4)->2:
pass''')
code2 = dedent('''
def test(a:typing.Generic[T], c:typing.Any=24)->typing.Iterable:
pass''')
for code in (code1, code2):
func = extract_node(code)
self.assertEqual(func.as_string(), code)
@require_version('3.5')
def test_unpacking_in_dicts(self):
code = "{'x': 1, **{'y': 2}}"
node = extract_node(code)
self.assertEqual(node.as_string(), code)
keys = [key for (key, _) in node.items]
self.assertIsInstance(keys[0], nodes.Const)
self.assertIsInstance(keys[1], nodes.DictUnpack)
@require_version('3.5')
def test_nested_unpacking_in_dicts(self):
code = "{'x': 1, **{'y': 2, **{'z': 3}}}"
node = extract_node(code)
self.assertEqual(node.as_string(), code)
@require_version('3.5')
def test_unpacking_in_dict_getitem(self):
node = extract_node('{1:2, **{2:3, 3:4}, **{5: 6}}')
for key, expected in ((1, 2), (2, 3), (3, 4), (5, 6)):
value = node.getitem(key)
self.assertIsInstance(value, nodes.Const)
self.assertEqual(value.value, expected)
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_raw_building.py 0000666 0000000 0000000 00000006003 12646222644 021114 0 ustar 0000000 0000000 import inspect
import os
import unittest
from six.moves import builtins # pylint: disable=import-error
from astroid.builder import AstroidBuilder
from astroid.raw_building import (
attach_dummy_node, build_module,
build_class, build_function, build_from_import
)
from astroid import test_utils
from astroid import nodes
from astroid.bases import BUILTINS
class RawBuildingTC(unittest.TestCase):
def test_attach_dummy_node(self):
node = build_module('MyModule')
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))
@test_utils.require_version(minver='3.0')
def test_io_is__io(self):
# _io module calls itself io. This leads
# to cyclic dependencies when astroid tries to resolve
# what io.BufferedReader is. The code that handles this
# is in astroid.raw_building.imported_member, which verifies
# the true name of the module.
import _io
builder = AstroidBuilder()
module = builder.inspect_build(_io)
buffered_reader = module.getattr('BufferedReader')[0]
self.assertEqual(buffered_reader.root().name, 'io')
@unittest.skipUnless(os.name == 'java', 'Requires Jython')
def test_open_is_inferred_correctly(self):
# Lot of Jython builtins don't have a __module__ attribute.
for name, _ in inspect.getmembers(builtins, predicate=inspect.isbuiltin):
if name == 'print':
continue
node = test_utils.extract_node('{0} #@'.format(name))
inferred = next(node.infer())
self.assertIsInstance(inferred, nodes.FunctionDef, name)
self.assertEqual(inferred.root().name, BUILTINS, name)
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_regrtest.py 0000666 0000000 0000000 00000024405 12646222644 020313 0 ustar 0000000 0000000 # 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 import exceptions
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
from astroid import transforms
class NonRegressionTests(resources.AstroidCacheSetupMixin,
unittest.TestCase):
def setUp(self):
sys.path.insert(0, resources.find('data'))
MANAGER.always_load_extensions = True
MANAGER.astroid_cache[BUILTINS] = self._builtins
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._failed_import_hooks = []
manager.astroid_cache = {}
manager._mod_file_cache = {}
manager._transform = transforms.TransformVisitor()
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')))
inferred = list(Instance(pylinter).igetattr('config'))
self.assertEqual(len(inferred), 1)
self.assertEqual(inferred[0].root().name, 'optparse')
self.assertEqual(inferred[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
inferred = callfunc.inferred()
self.assertEqual(len(inferred), 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_assignnames(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.Call))[-1].inferred()
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.ClassDef)
for klass in classes:
# triggers the _is_metaclass call
klass.type # pylint: disable=pointless-statement
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)
def test_ancestors_missing_from_function(self):
# Test for https://www.logilab.org/ticket/122793
node = extract_node('''
def gen(): yield
GEN = gen()
next(GEN)
''')
self.assertRaises(exceptions.InferenceError, next, node.infer())
def test_unicode_in_docstring(self):
# Crashed for astroid==1.4.1
# Test for https://bitbucket.org/logilab/astroid/issues/273/
# In a regular file, "coding: utf-8" would have been used.
node = extract_node(u'''
from __future__ import unicode_literals
class MyClass(object):
def method(self):
"With unicode : %s "
instance = MyClass()
''' % u"\u2019")
next(node.value.infer()).as_string()
class Whatever(object):
a = property(lambda x: x, lambda x: x)
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_scoped_nodes.py 0000666 0000000 0000000 00000160662 12646222644 021127 0 ustar 0000000 0000000 # 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 builder
from astroid import nodes
from astroid import scoped_nodes
from astroid import util
from astroid.exceptions import (
InferenceError, NotFoundError,
NoDefault, ResolveError, MroError,
InconsistentMroError, DuplicateBasesError,
)
from astroid.bases import (
BUILTINS, Instance,
BoundMethod, UnboundMethod, Generator
)
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.ClassDef)
self.assertEqual(yo.name, 'YO')
red = next(self.module.igetattr('redirect'))
self.assertIsInstance(red, nodes.FunctionDef)
self.assertEqual(red.name, 'four_args')
namenode = next(self.module.igetattr('NameNode'))
self.assertIsInstance(namenode, nodes.ClassDef)
self.assertEqual(namenode.name, 'Name')
# 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.ClassDef)
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_wildcard_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 = builder.parse('''
from missing import tzop
trop = "test"
__all__ = (trop, "test1", tzop, 42)
''')
res = sorted(m.wildcard_import_names())
self.assertEqual(res, ["test", "test1"])
m = builder.parse('''
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 = builder.parse(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 = builder.parse(data, 'package', 'data/package/__init__.py')
try:
m = astroid.import_module('', level=1)
self.assertEqual(m.name, 'package')
inferred = list(astroid.igetattr('subpackage'))
self.assertEqual(len(inferred), 1)
self.assertEqual(inferred[0].name, 'package.subpackage')
finally:
del sys.path[0]
def test_import_2(self):
data = '''from . import subpackage as pouet'''
astroid = builder.parse(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')
inferred = list(astroid.igetattr('pouet'))
self.assertEqual(len(inferred), 1)
self.assertEqual(inferred[0].name, 'package.subpackage')
finally:
del sys.path[0]
def test_file_stream_in_memory(self):
data = '''irrelevant_variable is irrelevant'''
astroid = builder.parse(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):
# pylint: disable=pointless-statement
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.Attribute)
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.ClassDef)
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.root().body[0]
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 = builder.parse(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()],
## ["Call(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 = builder.parse(data)
g = list(astroid['f'].ilookup('g'))[0]
self.assertEqual(g.pytype(), '%s.function' % BUILTINS)
def test_lambda_qname(self):
astroid = builder.parse('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 = builder.parse(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 = builder.parse(code, __name__)
self.assertEqual(astroid['f'].argnames(), ['a', 'b', 'c', 'args', 'kwargs'])
def test_return_nothing(self):
"""test inferred value on a function with empty return"""
data = '''
def func():
return
a = func()
'''
astroid = builder.parse(data)
call = astroid.body[1].value
func_vals = call.inferred()
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 = builder.parse(data, 'mod')
func = astroid.body[2].value.func.inferred()[0]
self.assertIsInstance(func, nodes.FunctionDef)
self.assertEqual(func.name, 'test')
one = func.getattr('bar')[0].inferred()[0]
self.assertIsInstance(one, nodes.Const)
self.assertEqual(one.value, 1)
def test_type_builtin_descriptor_subclasses(self):
astroid = builder.parse("""
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 = builder.parse("""
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')
def test_igetattr(self):
func = test_utils.extract_node('''
def test():
pass
''')
func._instance_attrs['value'] = [nodes.Const(42)]
value = func.getattr('value')
self.assertEqual(len(value), 1)
self.assertIsInstance(value[0], nodes.Const)
self.assertEqual(value[0].value, 42)
inferred = next(func.igetattr('value'))
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, 42)
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__mro__attribute(self):
node = test_utils.extract_node('''
class A(object): pass
class B(object): pass
class C(A, B): pass
''')
mro = node.getattr('__mro__')[0]
self.assertIsInstance(mro, nodes.Tuple)
self.assertEqual(mro.elts, node.mro())
def test__bases__attribute(self):
node = test_utils.extract_node('''
class A(object): pass
class B(object): pass
class C(A, B): pass
class D(C): pass
''')
bases = node.getattr('__bases__')[0]
self.assertIsInstance(bases, nodes.Tuple)
self.assertEqual(len(bases.elts), 1)
self.assertIsInstance(bases.elts[0], nodes.ClassDef)
self.assertEqual(bases.elts[0].name, 'C')
def test_cls_special_attributes_2(self):
astroid = builder.parse('''
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.AssignAttr)
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.FunctionDef), l_sibling)
self.assertEqual(l_sibling.name, 'global_access')
r_sibling = klass.next_sibling()
self.assertIsInstance(r_sibling, nodes.ClassDef)
self.assertEqual(r_sibling.name, 'YOUPI')
def test_local_attr_ancestors(self):
module = builder.parse('''
class A():
def __init__(self): pass
class B(A): pass
class C(B): pass
class D(object): pass
class F(): pass
class E(F, D): pass
''')
# Test old-style (Python 2) / new-style (Python 3+) ancestors lookups
klass2 = module['C']
it = klass2.local_attr_ancestors('__init__')
anc_klass = next(it)
self.assertIsInstance(anc_klass, nodes.ClassDef)
self.assertEqual(anc_klass.name, 'A')
if sys.version_info[0] == 2:
self.assertRaises(StopIteration, partial(next, it))
else:
anc_klass = next(it)
self.assertIsInstance(anc_klass, nodes.ClassDef)
self.assertEqual(anc_klass.name, 'object')
self.assertRaises(StopIteration, partial(next, it))
it = klass2.local_attr_ancestors('method')
self.assertRaises(StopIteration, partial(next, it))
# Test mixed-style ancestor lookups
klass2 = module['E']
it = klass2.local_attr_ancestors('__init__')
anc_klass = next(it)
self.assertIsInstance(anc_klass, nodes.ClassDef)
self.assertEqual(anc_klass.name, 'object')
self.assertRaises(StopIteration, partial(next, it))
def test_local_attr_mro(self):
module = builder.parse('''
class A(object):
def __init__(self): pass
class B(A):
def __init__(self, arg, arg2): pass
class C(A): pass
class D(C, B): pass
''')
dclass = module['D']
init = dclass.local_attr('__init__')[0]
self.assertIsInstance(init, nodes.FunctionDef)
self.assertEqual(init.parent.name, 'B')
cclass = module['C']
init = cclass.local_attr('__init__')[0]
self.assertIsInstance(init, nodes.FunctionDef)
self.assertEqual(init.parent.name, 'A')
ancestors = list(dclass.local_attr_ancestors('__init__'))
self.assertEqual([node.name for node in ancestors], ['B', 'A', 'object'])
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.ClassDef)
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['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_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 = builder.parse(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 = builder.parse(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 = builder.parse(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 = builder.parse(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 = builder.parse(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.FunctionDef)
def test_getattr_from_grandpa(self):
data = '''
class Future:
attr = 1
class Present(Future):
pass
class Past(Present):
pass
'''
astroid = builder.parse(data)
past = astroid['Past']
attr = past.getattr('attr')
self.assertEqual(len(attr), 1)
attr1 = attr[0]
self.assertIsInstance(attr1, nodes.AssignName)
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 = builder.parse(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 = builder.parse("""
class Test(object):
__metaclass__ = type
""")
klass = astroid['Test']
metaclass = klass.metaclass()
self.assertIsInstance(metaclass, scoped_nodes.ClassDef)
self.assertEqual(metaclass.name, 'type')
def test_metaclass_error(self):
astroid = builder.parse("""
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 = builder.parse("""
from abc import ABCMeta
class Test(object):
__metaclass__ = ABCMeta
""")
klass = astroid['Test']
metaclass = klass.metaclass()
self.assertIsInstance(metaclass, scoped_nodes.ClassDef)
self.assertEqual(metaclass.name, 'ABCMeta')
def test_metaclass_yes_leak(self):
astroid = builder.parse("""
# 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 = builder.parse("""
from abc import ABCMeta
class Test:
__metaclass__ = ABCMeta
""")
klass = astroid['Test']
self.assertTrue(klass.newstyle)
self.assertEqual(klass.metaclass().name, 'ABCMeta')
astroid = builder.parse("""
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 = builder.parse("""
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 = builder.parse("""
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.ClassDef)
self.assertEqual(metaclass.name, 'ABCMeta')
@test_utils.require_version(maxver='3.0')
def test_metaclass_ancestors(self):
astroid = builder.parse("""
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.ClassDef)
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_no_infinite_metaclass_loop(self):
klass = test_utils.extract_node("""
class SSS(object):
class JJJ(object):
pass
@classmethod
def Init(cls):
cls.JJJ = type('JJJ', (cls.JJJ,), {})
class AAA(SSS):
pass
class BBB(AAA.JJJ):
pass
""")
self.assertFalse(scoped_nodes._is_metaclass(klass))
ancestors = [base.name for base in klass.ancestors()]
self.assertIn('object', ancestors)
self.assertIn('JJJ', ancestors)
def test_no_infinite_metaclass_loop_with_redefine(self):
nodes = test_utils.extract_node("""
import datetime
class A(datetime.date): #@
@classmethod
def now(cls):
return cls()
class B(datetime.date): #@
pass
datetime.date = A
datetime.date = B
""")
for klass in nodes:
self.assertEqual(None, klass.metaclass())
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_using_six_add_metaclass(self):
klass = test_utils.extract_node('''
import six
import abc
@six.add_metaclass(abc.ABCMeta)
class WithMeta(object):
pass
''')
inferred = next(klass.infer())
metaclass = inferred.metaclass()
self.assertIsInstance(metaclass, scoped_nodes.ClassDef)
self.assertEqual(metaclass.qname(), 'abc.ABCMeta')
def test_using_invalid_six_add_metaclass_call(self):
klass = test_utils.extract_node('''
import six
@six.add_metaclass()
class Invalid(object):
pass
''')
inferred = next(klass.infer())
self.assertIsNone(inferred.metaclass())
def test_nonregr_infer_callresult(self):
astroid = builder.parse("""
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()), [util.YES])
def test_slots(self):
astroid = builder.parse("""
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"})
""")
expected = [
('First', ('a', 'b')),
('Second', ('a', )),
('Third', None),
('Fourth', ('a', 'b')),
('Fifth', None),
('Sixth', None),
('Seventh', ('dedent', )),
('Eight', ('parens', )),
('Ninth', None),
('Ten', ('a', 'c')),
]
for cls, expected_value in expected:
slots = astroid[cls].slots()
if expected_value is None:
self.assertIsNone(slots)
else:
self.assertEqual(list(expected_value),
[node.value for node in slots])
@test_utils.require_version(maxver='3.0')
def test_slots_py2(self):
module = builder.parse("""
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 = builder.parse("""
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 test_slots_empty_list_of_slots(self):
module = builder.parse("""
class Klass(object):
__slots__ = ()
""")
cls = module['Klass']
self.assertEqual(cls.slots(), [])
def test_slots_taken_from_parents(self):
module = builder.parse('''
class FirstParent(object):
__slots__ = ('a', 'b', 'c')
class SecondParent(FirstParent):
__slots__ = ('d', 'e')
class Third(SecondParent):
__slots__ = ('d', )
''')
cls = module['Third']
slots = cls.slots()
self.assertEqual(sorted(set(slot.value for slot in slots)),
['a', 'b', 'c', 'd', 'e'])
def test_all_ancestors_need_slots(self):
module = builder.parse('''
class A(object):
__slots__ = ('a', )
class B(A): pass
class C(B):
__slots__ = ('a', )
''')
cls = module['C']
self.assertIsNone(cls.slots())
cls = module['B']
self.assertIsNone(cls.slots())
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.")
@test_utils.require_version(maxver='3.0')
def test_combined_newstyle_oldstyle_in_mro(self):
node = test_utils.extract_node('''
class Old:
pass
class New(object):
pass
class New1(object):
pass
class New2(New, New1):
pass
class NewOld(New2, Old): #@
pass
''')
self.assertEqualMro(node, ['NewOld', 'New2', 'New', 'New1', 'object', 'Old'])
self.assertTrue(node.newstyle)
def test_with_metaclass_mro(self):
astroid = builder.parse("""
import six
class C(object):
pass
class B(C):
pass
class A(six.with_metaclass(type, B)):
pass
""")
self.assertEqualMro(astroid['A'], ['A', 'B', 'C', 'object'])
def test_mro(self):
astroid = builder.parse("""
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
class Duplicates(str, str): 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(InconsistentMroError) 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(InconsistentMroError) 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'])
with self.assertRaises(DuplicateBasesError) as cm:
astroid['Duplicates'].mro()
self.assertEqual(str(cm.exception), "Duplicates found in the mro.")
self.assertTrue(issubclass(cm.exception.__class__, MroError))
self.assertTrue(issubclass(cm.exception.__class__, ResolveError))
def test_generator_from_infer_call_result_parent(self):
func = test_utils.extract_node("""
import contextlib
@contextlib.contextmanager
def test(): #@
yield
""")
result = next(func.infer_call_result(func))
self.assertIsInstance(result, Generator)
self.assertEqual(result.parent, func)
def test_type_three_arguments(self):
classes = test_utils.extract_node("""
type('A', (object, ), {"a": 1, "b": 2, missing: 3}) #@
""")
first = next(classes.infer())
self.assertIsInstance(first, nodes.ClassDef)
self.assertEqual(first.name, "A")
self.assertEqual(first.basenames, ["object"])
self.assertIsInstance(first["a"], nodes.Const)
self.assertEqual(first["a"].value, 1)
self.assertIsInstance(first["b"], nodes.Const)
self.assertEqual(first["b"].value, 2)
with self.assertRaises(NotFoundError):
first.getattr("missing")
def test_implicit_metaclass(self):
cls = test_utils.extract_node("""
class A(object):
pass
""")
type_cls = scoped_nodes.builtin_lookup("type")[1][0]
self.assertEqual(cls.implicit_metaclass(), type_cls)
@test_utils.require_version(maxver='3.0')
def test_implicit_metaclass_is_none(self):
cls = test_utils.extract_node("""
class A: pass
""")
self.assertIsNone(cls.implicit_metaclass())
def test_local_attr_invalid_mro(self):
cls = test_utils.extract_node("""
# A has an invalid MRO, local_attr should fallback
# to using .ancestors.
class A(object, object):
test = 42
class B(A): #@
pass
""")
local = cls.local_attr('test')[0]
inferred = next(local.infer())
self.assertIsInstance(inferred, nodes.Const)
self.assertEqual(inferred.value, 42)
def test_has_dynamic_getattr(self):
module = builder.parse("""
class Getattr(object):
def __getattr__(self, attrname):
pass
class Getattribute(object):
def __getattribute__(self, attrname):
pass
class ParentGetattr(Getattr):
pass
""")
self.assertTrue(module['Getattr'].has_dynamic_getattr())
self.assertTrue(module['Getattribute'].has_dynamic_getattr())
self.assertTrue(module['ParentGetattr'].has_dynamic_getattr())
# Test that objects analyzed through the live introspection
# aren't considered to have dynamic getattr implemented.
import datetime
astroid_builder = builder.AstroidBuilder()
module = astroid_builder.module_build(datetime)
self.assertFalse(module['timedelta'].has_dynamic_getattr())
def test_duplicate_bases_namedtuple(self):
module = builder.parse("""
import collections
_A = collections.namedtuple('A', 'a')
class A(_A): pass
class B(A): pass
""")
self.assertRaises(DuplicateBasesError, module['B'].mro)
def test_instance_bound_method_lambdas(self):
ast_nodes = test_utils.extract_node('''
class Test(object): #@
lam = lambda self: self
not_method = lambda xargs: xargs
Test() #@
''')
cls = next(ast_nodes[0].infer())
self.assertIsInstance(next(cls.igetattr('lam')), scoped_nodes.Lambda)
self.assertIsInstance(next(cls.igetattr('not_method')), scoped_nodes.Lambda)
instance = next(ast_nodes[1].infer())
lam = next(instance.igetattr('lam'))
self.assertIsInstance(lam, BoundMethod)
not_method = next(instance.igetattr('not_method'))
self.assertIsInstance(not_method, scoped_nodes.Lambda)
def test_class_extra_decorators_frame_is_not_class(self):
ast_node = test_utils.extract_node('''
def ala():
def bala(): #@
func = 42
''')
self.assertEqual(ast_node.extra_decorators, [])
def test_class_extra_decorators_only_callfunc_are_considered(self):
ast_node = test_utils.extract_node('''
class Ala(object):
def func(self): #@
pass
func = 42
''')
self.assertEqual(ast_node.extra_decorators, [])
def test_class_extra_decorators_only_assignment_names_are_considered(self):
ast_node = test_utils.extract_node('''
class Ala(object):
def func(self): #@
pass
def __init__(self):
self.func = staticmethod(func)
''')
self.assertEqual(ast_node.extra_decorators, [])
def test_class_extra_decorators_only_same_name_considered(self):
ast_node = test_utils.extract_node('''
class Ala(object):
def func(self): #@
pass
bala = staticmethod(func)
''')
self.assertEqual(ast_node.extra_decorators, [])
self.assertEqual(ast_node.type, 'method')
def test_class_extra_decorators(self):
static_method, clsmethod = test_utils.extract_node('''
class Ala(object):
def static(self): #@
pass
def class_method(self): #@
pass
class_method = classmethod(class_method)
static = staticmethod(static)
''')
self.assertEqual(len(clsmethod.extra_decorators), 1)
self.assertEqual(clsmethod.type, 'classmethod')
self.assertEqual(len(static_method.extra_decorators), 1)
self.assertEqual(static_method.type, 'staticmethod')
def test_extra_decorators_only_class_level_assignments(self):
node = test_utils.extract_node('''
def _bind(arg):
return arg.bind
class A(object):
@property
def bind(self):
return 42
def irelevant(self):
# This is important, because it used to trigger
# a maximum recursion error.
bind = _bind(self)
return bind
A() #@
''')
inferred = next(node.infer())
bind = next(inferred.igetattr('bind'))
self.assertIsInstance(bind, nodes.Const)
self.assertEqual(bind.value, 42)
parent = bind.scope()
self.assertEqual(len(parent.extra_decorators), 0)
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_transforms.py 0000666 0000000 0000000 00000021246 12646170047 020651 0 ustar 0000000 0000000 # 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 .
from __future__ import print_function
import contextlib
import time
import unittest
from astroid import builder
from astroid import nodes
from astroid import parse
from astroid import transforms
@contextlib.contextmanager
def add_transform(manager, node, transform, predicate=None):
manager.register_transform(node, transform, predicate)
try:
yield
finally:
manager.unregister_transform(node, transform, predicate)
class TestTransforms(unittest.TestCase):
def setUp(self):
self.transformer = transforms.TransformVisitor()
def parse_transform(self, code):
module = parse(code, apply_transforms=False)
return self.transformer.visit(module)
def test_function_inlining_transform(self):
def transform_call(node):
# Let's do some function inlining
inferred = next(node.infer())
return inferred
self.transformer.register_transform(nodes.Call,
transform_call)
module = self.parse_transform('''
def test(): return 42
test() #@
''')
self.assertIsInstance(module.body[1], nodes.Expr)
self.assertIsInstance(module.body[1].value, nodes.Const)
self.assertEqual(module.body[1].value.value, 42)
def test_recursive_transforms_into_astroid_fields(self):
# Test that the transformer walks properly the tree
# by going recursively into the _astroid_fields per each node.
def transform_compare(node):
# Let's check the values of the ops
_, right = node.ops[0]
# Assume they are Consts and they were transformed before
# us.
return nodes.const_factory(node.left.value < right.value)
def transform_name(node):
# Should be Consts
return next(node.infer())
self.transformer.register_transform(nodes.Compare, transform_compare)
self.transformer.register_transform(nodes.Name, transform_name)
module = self.parse_transform('''
a = 42
b = 24
a < b
''')
self.assertIsInstance(module.body[2], nodes.Expr)
self.assertIsInstance(module.body[2].value, nodes.Const)
self.assertFalse(module.body[2].value.value)
def test_transform_patches_locals(self):
def transform_function(node):
assign = nodes.Assign()
name = nodes.AssignName()
name.name = 'value'
assign.targets = [name]
assign.value = nodes.const_factory(42)
node.body.append(assign)
self.transformer.register_transform(nodes.FunctionDef,
transform_function)
module = self.parse_transform('''
def test():
pass
''')
func = module.body[0]
self.assertEqual(len(func.body), 2)
self.assertIsInstance(func.body[1], nodes.Assign)
self.assertEqual(func.body[1].as_string(), 'value = 42')
def test_predicates(self):
def transform_call(node):
inferred = next(node.infer())
return inferred
def should_inline(node):
return node.func.name.startswith('inlineme')
self.transformer.register_transform(nodes.Call,
transform_call,
should_inline)
module = self.parse_transform('''
def inlineme_1():
return 24
def dont_inline_me():
return 42
def inlineme_2():
return 2
inlineme_1()
dont_inline_me()
inlineme_2()
''')
values = module.body[-3:]
self.assertIsInstance(values[0], nodes.Expr)
self.assertIsInstance(values[0].value, nodes.Const)
self.assertEqual(values[0].value.value, 24)
self.assertIsInstance(values[1], nodes.Expr)
self.assertIsInstance(values[1].value, nodes.Call)
self.assertIsInstance(values[2], nodes.Expr)
self.assertIsInstance(values[2].value, nodes.Const)
self.assertEqual(values[2].value.value, 2)
def test_transforms_are_separated(self):
# Test that the transforming is done at a separate
# step, which means that we are not doing inference
# on a partially constructred tree anymore, which was the
# source of crashes in the past when certain inference rules
# were used in a transform.
def transform_function(node):
if node.decorators:
for decorator in node.decorators.nodes:
inferred = next(decorator.infer())
if inferred.qname() == 'abc.abstractmethod':
return next(node.infer_call_result(node))
manager = builder.MANAGER
with add_transform(manager, nodes.FunctionDef, transform_function):
module = builder.parse('''
import abc
from abc import abstractmethod
class A(object):
@abc.abstractmethod
def ala(self):
return 24
@abstractmethod
def bala(self):
return 42
''')
cls = module['A']
ala = cls.body[0]
bala = cls.body[1]
self.assertIsInstance(ala, nodes.Const)
self.assertEqual(ala.value, 24)
self.assertIsInstance(bala, nodes.Const)
self.assertEqual(bala.value, 42)
def test_transforms_are_called_for_builtin_modules(self):
# Test that transforms are called for builtin modules.
def transform_function(node):
name = nodes.AssignName()
name.name = 'value'
node.args.args = [name]
return node
manager = builder.MANAGER
predicate = lambda node: node.root().name == 'time'
with add_transform(manager, nodes.FunctionDef,
transform_function, predicate):
builder_instance = builder.AstroidBuilder()
module = builder_instance.module_build(time)
asctime = module['asctime']
self.assertEqual(len(asctime.args.args), 1)
self.assertIsInstance(asctime.args.args[0], nodes.AssignName)
self.assertEqual(asctime.args.args[0].name, 'value')
def test_builder_apply_transforms(self):
def transform_function(node):
return nodes.const_factory(42)
manager = builder.MANAGER
with add_transform(manager, nodes.FunctionDef, transform_function):
astroid_builder = builder.AstroidBuilder(apply_transforms=False)
module = astroid_builder.string_build('''def test(): pass''')
# The transform wasn't applied.
self.assertIsInstance(module.body[0], nodes.FunctionDef)
def test_transform_crashes_on_is_subtype_of(self):
# Test that we don't crash when having is_subtype_of
# in a transform, as per issue #188. This happened
# before, when the transforms weren't in their own step.
def transform_class(cls):
if cls.is_subtype_of('django.db.models.base.Model'):
return cls
return cls
self.transformer.register_transform(nodes.ClassDef,
transform_class)
self.parse_transform('''
# Change environ to automatically call putenv() if it exists
import os
putenv = os.putenv
try:
# This will fail if there's no putenv
putenv
except NameError:
pass
else:
import UserDict
''')
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/unittest_utils.py 0000666 0000000 0000000 00000010531 12646223235 017604 0 ustar 0000000 0000000 # 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 builder
from astroid import InferenceError
from astroid import nodes
from astroid import node_classes
from astroid import test_utils
from astroid import util as astroid_util
class InferenceUtil(unittest.TestCase):
def test_not_exclusive(self):
module = builder.parse("""
x = 10
for x in range(5):
print (x)
if x > 0:
print ('#' * x)
""", __name__, __file__)
xass1 = module.locals['x'][0]
assert xass1.lineno == 2
xnames = [n for n in module.nodes_of_class(nodes.Name) if n.name == 'x']
assert len(xnames) == 3
assert xnames[1].lineno == 6
self.assertEqual(node_classes.are_exclusive(xass1, xnames[1]), False)
self.assertEqual(node_classes.are_exclusive(xass1, xnames[2]), False)
def test_if(self):
module = builder.parse('''
if 1:
a = 1
a = 2
elif 2:
a = 12
a = 13
else:
a = 3
a = 4
''')
a1 = module.locals['a'][0]
a2 = module.locals['a'][1]
a3 = module.locals['a'][2]
a4 = module.locals['a'][3]
a5 = module.locals['a'][4]
a6 = module.locals['a'][5]
self.assertEqual(node_classes.are_exclusive(a1, a2), False)
self.assertEqual(node_classes.are_exclusive(a1, a3), True)
self.assertEqual(node_classes.are_exclusive(a1, a5), True)
self.assertEqual(node_classes.are_exclusive(a3, a5), True)
self.assertEqual(node_classes.are_exclusive(a3, a4), False)
self.assertEqual(node_classes.are_exclusive(a5, a6), False)
def test_try_except(self):
module = builder.parse('''
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 = module.locals['exclusive_func2'][0]
f2 = module.locals['exclusive_func2'][1]
f3 = module.locals['exclusive_func2'][2]
f4 = module.locals['exclusive_func2'][3]
self.assertEqual(node_classes.are_exclusive(f1, f2), True)
self.assertEqual(node_classes.are_exclusive(f1, f3), True)
self.assertEqual(node_classes.are_exclusive(f1, f4), False)
self.assertEqual(node_classes.are_exclusive(f2, f4), True)
self.assertEqual(node_classes.are_exclusive(f3, f4), True)
self.assertEqual(node_classes.are_exclusive(f3, f2), True)
self.assertEqual(node_classes.are_exclusive(f2, f1), True)
self.assertEqual(node_classes.are_exclusive(f4, f1), False)
self.assertEqual(node_classes.are_exclusive(f4, f2), True)
def test_unpack_infer_uninferable_nodes(self):
node = test_utils.extract_node('''
x = [A] * 1
f = [x, [A] * 2]
f
''')
inferred = next(node.infer())
unpacked = list(node_classes.unpack_infer(inferred))
self.assertEqual(len(unpacked), 3)
self.assertTrue(all(elt is astroid_util.YES
for elt in unpacked))
def test_unpack_infer_empty_tuple(self):
node = test_utils.extract_node('''
()
''')
inferred = next(node.infer())
with self.assertRaises(InferenceError):
list(node_classes.unpack_infer(inferred))
if __name__ == '__main__':
unittest.main()
astroid-1.4.4/astroid/tests/__init__.py 0000666 0000000 0000000 00000000000 12632520133 016222 0 ustar 0000000 0000000 astroid-1.4.4/astroid/test_utils.py 0000666 0000000 0000000 00000015515 12646222644 015554 0 ustar 0000000 0000000 """Utility functions for test code that uses astroid ASTs as input."""
import functools
import sys
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.Call)
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.ClassDef, nodes.FunctionDef)):
# 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.Expr):
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 = builder.parse(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 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]
astroid-1.4.4/astroid/transforms.py 0000666 0000000 0000000 00000007366 12632317503 015552 0 ustar 0000000 0000000 # 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 collections
import warnings
class TransformVisitor(object):
"""A visitor for handling transforms.
The standard approach of using it is to call
:meth:`~visit` with an *astroid* module and the class
will take care of the rest, walking the tree and running the
transforms for each encountered node.
"""
def __init__(self):
self.transforms = collections.defaultdict(list)
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
warnings.warn('node %s substituted multiple times' % node)
node = ret
return node
def _visit(self, node):
if hasattr(node, '_astroid_fields'):
for field in node._astroid_fields:
value = getattr(node, field)
visited = self._visit_generic(value)
setattr(node, field, visited)
return self._transform(node)
def _visit_generic(self, node):
if isinstance(node, list):
return [self._visit_generic(child) for child in node]
elif isinstance(node, tuple):
return tuple(self._visit_generic(child) for child in node)
else:
return self._visit(node)
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 visit(self, module):
"""Walk the given astroid *tree* and transform each encountered node
Only the nodes which have transforms registered will actually
be replaced or changed.
"""
module.body = [self._visit(child) for child in module.body]
return self._transform(module)
astroid-1.4.4/astroid/util.py 0000666 0000000 0000000 00000005741 12646222644 014332 0 ustar 0000000 0000000 # 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 .
#
# The code in this file was originally part of logilab-common, licensed under
# the same license.
import warnings
from astroid import exceptions
def generate_warning(message, warning):
return lambda *args: warnings.warn(message % args, warning, stacklevel=3)
rename_warning = generate_warning(
"%r is deprecated and will be removed in astroid %.1f, use %r instead",
PendingDeprecationWarning)
attribute_to_method_warning = generate_warning(
"%s is deprecated and will be removed in astroid %.1f, use the "
"method '%s()' instead.", PendingDeprecationWarning)
attribute_to_function_warning = generate_warning(
"%s is deprecated and will be removed in astroid %.1f, use the "
"function '%s()' instead.", PendingDeprecationWarning)
method_to_function_warning = generate_warning(
"%s() is deprecated and will be removed in astroid %.1f, use the "
"function '%s()' instead.", PendingDeprecationWarning)
class _Yes(object):
"""Special inference object, which is returned when inference fails."""
def __repr__(self):
return 'YES'
__str__ = __repr__
def __getattribute__(self, name):
if name == 'next':
raise AttributeError('next method should not be called')
if name.startswith('__') and name.endswith('__'):
return super(_Yes, self).__getattribute__(name)
if name == 'accept':
return super(_Yes, self).__getattribute__(name)
return self
def __call__(self, *args, **kwargs):
return self
def accept(self, visitor):
func = getattr(visitor, "visit_yes")
return func(self)
YES = _Yes()
def safe_infer(node, context=None):
"""Return the inferred value for the given node.
Return None if inference failed or if there is some ambiguity (more than
one node has been inferred).
"""
try:
inferit = node.infer(context=context)
value = next(inferit)
except exceptions.InferenceError:
return
try:
next(inferit)
return # None if there is ambiguity on the inferred node
except exceptions.InferenceError:
return # there is some kind of ambiguity
except StopIteration:
return value
astroid-1.4.4/astroid/__init__.py 0000666 0000000 0000000 00000011571 12646222644 015112 0 ustar 0000000 0000000 # 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 Instance, BoundMethod, UnboundMethod
from astroid.node_classes import are_exclusive, unpack_infer
from astroid.scoped_nodes import builtin_lookup
from astroid.builder import parse
from astroid.util import YES
# make a manager instance (borg) as well as Project and Package classes
# accessible from astroid package
from astroid.manager import AstroidManager
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(Call, 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, objs in extension_module._locals.items():
node._locals[name] = objs
for obj in objs:
if obj.parent is extension_module:
obj.parent = node
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])
astroid-1.4.4/astroid/__pkginfo__.py 0000666 0000000 0000000 00000003072 12646222703 015575 0 ustar 0000000 0000000 # 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, 4, 4)
version = '.'.join([str(num) for num in numversion])
install_requires = ['six', 'lazy_object_proxy', 'wrapt']
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",
]
astroid-1.4.4/astroid.egg-info/ 0000777 0000000 0000000 00000000000 12646224174 014466 5 ustar 0000000 0000000 astroid-1.4.4/astroid.egg-info/dependency_links.txt 0000666 0000000 0000000 00000000001 12646224145 020532 0 ustar 0000000 0000000
astroid-1.4.4/astroid.egg-info/PKG-INFO 0000666 0000000 0000000 00000006127 12646224145 015567 0 ustar 0000000 0000000 Metadata-Version: 1.1
Name: astroid
Version: 1.4.4
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 can use 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
astroid-1.4.4/astroid.egg-info/requires.txt 0000666 0000000 0000000 00000000034 12646224145 017061 0 ustar 0000000 0000000 six
lazy_object_proxy
wrapt
astroid-1.4.4/astroid.egg-info/SOURCES.txt 0000666 0000000 0000000 00000014067 12646224146 016361 0 ustar 0000000 0000000 COPYING
COPYING.LESSER
ChangeLog
MANIFEST.in
README.rst
setup.cfg
setup.py
tox.ini
astroid/__init__.py
astroid/__pkginfo__.py
astroid/arguments.py
astroid/as_string.py
astroid/astpeephole.py
astroid/bases.py
astroid/builder.py
astroid/context.py
astroid/decorators.py
astroid/exceptions.py
astroid/inference.py
astroid/manager.py
astroid/mixins.py
astroid/modutils.py
astroid/node_classes.py
astroid/nodes.py
astroid/objects.py
astroid/protocols.py
astroid/raw_building.py
astroid/rebuilder.py
astroid/scoped_nodes.py
astroid/test_utils.py
astroid/transforms.py
astroid/util.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
astroid/brain/brain_builtin_inference.py
astroid/brain/brain_dateutil.py
astroid/brain/brain_gi.py
astroid/brain/brain_mechanize.py
astroid/brain/brain_nose.py
astroid/brain/brain_numpy.py
astroid/brain/brain_pytest.py
astroid/brain/brain_qt.py
astroid/brain/brain_six.py
astroid/brain/brain_stdlib.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_lookup.py
astroid/tests/unittest_manager.py
astroid/tests/unittest_modutils.py
astroid/tests/unittest_nodes.py
astroid/tests/unittest_objects.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_transforms.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 astroid-1.4.4/astroid.egg-info/top_level.txt 0000666 0000000 0000000 00000000010 12646224145 017205 0 ustar 0000000 0000000 astroid
astroid-1.4.4/ChangeLog 0000666 0000000 0000000 00000107370 12646222676 013116 0 ustar 0000000 0000000 Change log for the astroid package (used to be astng)
=====================================================
2016-01-15 -- 1.4.4
* unpack_infer raises InferenceError if it can't operate
with the given sequences of nodes.
* Support accessing properties with super().
* Enforce strong updates per frames.
When looking up a name in a scope, Scope.lookup will return
only the values which will be reachable after execution, as seen
in the following code:
a = 1
a = 2
In this case it doesn't make sense to return two values, but
only the last one.
2015-12-24 -- 1.4.3
* pkg_resources brain tips are a bit more specific,
by specifiying proper returns.
* Standard library modules are properly detected by is_standard_module.
This should fix issues such as https://github.com/PyCQA/pylint/issues/725.
2015-12-21 -- 1.4.2
* The slots() method conflates all the slots from the ancestors
into a list of current and parent slots.
We're doing this because this is the right semantics of slots,
they get inherited, as long as each parent defines a __slots__
entry.
* Revert to using printf-style formatting in as_string, in order
to avoid a potential problem with encodings when using .format.
Closes issue #273.
* assigned_stmts methods have the same signature from now on.
They used to have different signatures and each one made
assumptions about what could be passed to other implementations,
leading to various possible crashes when one or more arguments
weren't given. Closes issue #277.
2015-11-29 -- 1.4.1
* Add support for handling Uninferable nodes when calling as_string
Some object, for instance List or Tuple can have, after inference,
Uninferable as their elements, happening when their components
weren't couldn't be inferred properly. This means that as_string
needs to cope with expecting Uninferable nodes part of the other
nodes coming for a string transformation. The patch adds a visit
method in AsString and ``accept`` on Yes / Uninferable nodes.
Closes issue #270.
2015-11-29 -- 1.4.0
* Class.getattr('__mro__') returns the actual MRO. Closes issue #128.
* The logilab-common dependency is not needed anymore as the needed code
was integrated into astroid.
* Add 'assert_equals' method in nose.tools's brain plugin.
* Generated enum member stubs now support IntEnum and multiple
base classes.
* Add brain tips for multiprocessing.Manager and
multiprocessing.managers.SyncManager.
* Add brain tips for multiprocessing post Python 3.4+,
where the module level functions are retrieved with getattr
from a context object, leading to many no-member errors
in Pylint.
* The Generator objects inferred with `infer_call_result`
from functions have as parent the function from which they
are returned.
* Understand partially the 3-argument form of `type`.
The only change is that astroid understands members
passed in as dictionaries as the third argument.
* Improve the inference of Getattr nodes when dealing with
abstract properties from the abc module.
In astroid.bases.Instance._wrap_attr we had a detection
code for properties, which basically inferred whatever
a property returned, passing the results up the stack,
to the igetattr() method. It handled only the builtin property
but the new patch also handles a couple of other properties,
such as abc.abstractproperty.
* UnboundMethod.getattr calls the getattr of its _proxied object
and doesn't call super(...) anymore.
It previously crashed, since the first ancestor in its mro was
bases.Proxy and bases.Proxy doesn't implement the .getattr method.
Closes issue #91.
* Don't hard fail when calling .mro() on a class which has
combined both newstyle and old style classes. The class
in question is actually newstyle (and the __mro__ can be
retrieved using Python).
.mro() fallbacks to using .ancestors() in that case.
* Class.local_attr and Class.local_attr_ancestors uses internally
a mro lookup, using .mro() method, if they can.
That means for newstyle classes, when trying to lookup a member
using one of these functions, the first one according to the
mro will be returned. This reflects nicely the reality,
but it can have as a drawback the fact that it is a behaviour
change (the previous behaviour was incorrect though). Also,
having bases which can return multiple values when inferred
will not work with the new approach, because .mro() only
retrieves the first value inferred from a base.
* Expose a implicit_metaclass() method in Class. This will return
a builtins.type instance for newstyle classes.
* Add two new exceptions for handling MRO error cases. DuplicateBasesError
is emitted when duplicate bases are found in a class,
InconsistentMroError is raised when the method resolution is determined
to be inconsistent. They share a common class, MroError, which
is a subclass of ResolveError, meaning that this change is backwards
compatible.
* Classes aren't marked as interfaces anymore, in the `type` attribute.
* Class.has_dynamic_getattr doesn't return True for special methods
which aren't implemented in pure Python, as it is the case for extension modules.
Since most likely the methods were coming from a live object, this implies
that all of them will have __getattr__ and __getattribute__ present and it
is wrong to consider that those methods were actually implemented.
* Add `igetattr` method to scoped_nodes.Function.
* Add support for Python 3.5's MatMul operation: see PEP 465 for more
details.
* NotImplemented is detected properly now as being part of the
builtins module. Previously trying to infer the Name(NotImplemented)
returned an YES object.
* Add proper grammatical names for `infered` and `ass_type` methods,
namely `inferred` and `assign_type`.
The old methods will raise PendingDeprecationWarning, being slated
for removal in astroid 2.0.
* Add new AST names in order to be similar to the ones
from the builtin ast module.
With this change, Getattr becomes Attributes, Backquote becomes
Repr, Class is ClassDef, Function is FunctionDef, Discard is Expr,
CallFunc is Call, From is ImportFrom, AssName is AssignName
and AssAttr is AssignAttr. The old names are maintained for backwards
compatibility and they are interchangeable, in the sense that using
Discard will use Expr under the hood and the implemented visit_discard
in checkers will be called with Expr nodes instead. The AST does not
contain the old nodes, only the interoperability between them hides this
fact. Recommandations to move to the new nodes are emitted accordingly,
the old names will be removed in astroid 2.0.
* Star unpacking in assignments returns properly a list,
not the individual components. Closes issue #138.
* Lambdas found at class level, which have a `self` argument, are considered
* Add annotation support for function.as_string(). Closes issue #37.
* Add support for indexing bytes on Python 3.
BoundMethods when accessing them from instances of their class.
* Add support for inferring subscript on instances, which will
use __getitem__. Closes issue #124.
* Understand metaclasses added with six.add_metaclass decorator. Closes issue #129.
* Add a new convenience API, `astroid.parse`, which can be used to retrieve
an astroid AST from a source code string, similar to how ast.parse can be
used to obtain a Python AST from a source string. This is the test_utils.build_module
promoted to a public API.
* do_import_module passes the proper relative_only flag if the level is higher
than 1. This has the side effect that using `from .something import something`
in a non-package will finally result in an import-error on Pylint's side.
Until now relative_only was ignored, leading to the import of `something`,
if it was globally available.
* There's a new separate step for transforms.
Until now, the transforms were applied at the same time the tree was
being built. This was problematic if the transform functions were
using inference, since the inference was executed on a partially
constructed tree, which led to failures when post-building
information was needed (such as setting the _from_names
for the From imports).
Now there's a separate step for transforms, which are applied
using transform.TransformVisitor.
There's a couple of other related changes:
* astroid.parse and AstroidBuilder gained a new parameter
`apply_transforms`, which is a boolean flag, which will
control if the transforms are applied. We do this because
there are uses when the vanilla tree is wanted, without
any implicit modification.
* the transforms are also applied for builtin modules,
as a side effect of the fact that transform visiting
was moved in AstroidBuilder._post_build from
AstroidBuilder._data_build.
Closes issue #116.
* Add a new node, DictUnpack, which is used to represent the unpacking
of a dictionary into another dictionary, using PEP 448 specific syntax
({1:2, **{2:3})
This is a different approach than what the builtin ast module does,
since it just uses None to represent this kind of operation,
which seems conceptually wrong, due to the fact the AST contains
non-AST nodes. Closes issue #206.
* Add a new type of node, called *inference objects*. Inference objects are similar with
AST nodes, but they can be obtained only after inference, so they can't be found
inside the AST tree. Their purpose is to handle at astroid level
some operations which can't be handled when using brain transforms.
For instance, the first object added is FrozenSet, which can be manipulated
at astroid's level (inferred, itered etc). Code such as this 'frozenset((1,2))'
will not return an Instance of frozenset, without having access to its
content, but a new objects.FrozenSet, which can be used just as a nodes.Set.
* Add a new *inference object* called Super, which also adds support for understanding
super calls. astroid understands the zero-argument form of super, specific to
Python 3, where the interpreter fills itself the arguments of the call. Also, we
are understanding the 2-argument form of super, both for bounded lookups
(super(X, instance)) as well as for unbounded lookups (super(X, Y)),
having as well support for validating that the object-or-type is a subtype
of the first argument. The unbounded form of super (one argument) is not
understood, since it's useless in practice and should be removed from
Python's specification. Closes issue #89.
* astroid.utils.ASTWalker and astroid.utils.LocalsVisitor
were moved to pylint.pyreverse.utils.
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)
* fix bug with namedtuple inference (issue #3)
* get back gobject introspection from pylint-brain
* fix some test failures under pypy and py3.3, though there is one remaining
in each of these platform (2.7 tests are all green)
2013-07-29 -- 1.0.0
* Fix some omissions in py2stdlib's version of hashlib and
add a small test for it.
* Properly recognize methods annotated with abc.abstract{property,method}
as abstract.
* Allow transformation functions on any node, providing a
`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
(actually in pylint-brain, closes #8766)
* Added the test_utils module for building ASTs and
extracting deeply nested nodes for easier testing.
* Add support for py3k's keyword only arguments (PEP 3102)
* RENAME THE PROJECT to astroid
2013-04-16 -- 0.24.3
* #124360 [py3.3]: Don't crash on 'yield from' nodes
* #123062 [pylint-brain]: Use correct names for keywords for urlparse
* #123056 [pylint-brain]: Add missing methods for hashlib
* #123068: Fix inference for generator methods to correctly handle yields
in lambdas.
* #123068: Make sure .as_string() returns valid code for yields in
expressions.
* #47957: Set literals are now correctly treated as inference leaves.
* #123074: Add support for inference of subscript operations on dict
literals.
2013-02-27 -- 0.24.2
* pylint-brain: more subprocess.Popen faking (see #46273)
* #109562 [jython]: java modules have no __doc__, causing crash
* #120646 [py3]: fix for python3.3 _ast changes which may cause crash
* #109988 [py3]: test fixes
2012-10-05 -- 0.24.1
* #106191: fix __future__ absolute import w/ From node
* #50395: fix function fromlineno when some decorator is splited on
multiple lines (patch by Mark Gius)
* #92362: fix pyreverse crash on relative import
* #104041: fix crash 'module object has no file_encoding attribute'
* #4294 (pylint-brain): bad inference on mechanize.Browser.open
* #46273 (pylint-brain): bad inference subprocess.Popen.communicate
2012-07-18 -- 0.24.0
* include pylint brain extension, describing some stuff not properly understood until then.
(#100013, #53049, #23986, #72355)
* #99583: fix raw_building.object_build for pypy implementation
* use `open` rather than `file` in scoped_nodes as 2to3 miss it
2011-12-08 -- 0.23.1
* #62295: avoid "OSError: Too many open files" by moving
.file_stream as a Module property opening the file only when needed
* Lambda nodes should have a `name` attribute
* only call transformers if modname specified
2011-10-07 -- 0.23.0
* #77187: ancestor() only returns the first class when inheriting
from two classes coming from the same module
* #76159: putting module's parent directory on the path causes problems
linting when file names clash
* #74746: should return empty module when __main__ is imported (patch by
google)
* #74748: getitem protocal return constant value instead of a Const node
(patch by google)
* #77188: support lgc.decorators.classproperty
* #77253: provide a way for user code to register astng "transformers"
using manager.register_transformer(callable) where callable will be
called after an astng has been built and given the related module node
as argument
2011-07-18 -- 0.22.0
* added column offset information on nodes (patch by fawce)
* #70497: Crash on AttributeError: 'NoneType' object has no attribute '_infer_name'
* #70381: IndendationError in import causes crash
* #70565: absolute imports treated as relative (patch by Jacek Konieczny)
* #70494: fix file encoding detection with python2.x
* py3k: __builtin__ module renamed to builtins, we should consider this to properly
build ast for builtin objects
2011-01-11 -- 0.21.1
* python3: handle file encoding; fix a lot of tests
* fix #52006: "True" and "False" can be assigned as variable in Python2x
* fix #8847: pylint doesn't understand function attributes at all
* fix #8774: iterator / generator / next method
* fix bad building of ast from living object w/ container classes
(eg dict, set, list, tuple): contained elements should be turned to
ast as well (not doing it will much probably cause crash later)
* somewhat fix #57299 and other similar issue: Exception when
trying to validate file using PyQt's PyQt4.QtCore module: we can't
do much about it but at least catch such exception to avoid crash
2010-11-15 -- 0.21.0
* python3.x: first python3.x release
* fix #37105: Crash on AttributeError: 'NoneType' object has no attribute '_infer_name'
* python2.4: drop python < 2.5 support
2010-10-27 -- 0.20.4
* fix #37868 #37665 #33638 #37909: import problems with absolute_import_activated
* fix #8969: false positive when importing from zip-safe eggs
* fix #46131: minimal class decorator support
* minimal python2.7 support (dict and set comprehension)
* important progress on Py3k compatibility
2010-09-28 -- 0.20.3
* restored python 2.3 compatibility
* fix #45959: AttributeError: 'NoneType' object has no attribute 'frame', due
to handling of __class__ when importing from living object (because of missing
source code or C-compiled object)
2010-09-10 -- 0.20.2
* fix astng building bug: we've to set module.package flag at the node
creation time otherwise we'll miss this information when infering relative
import during the build process (this should fix for instance some problems
with numpy)
* added __subclasses__ to special class attribute
* fix Class.interfaces so that no InferenceError raised on empty __implements__
* yield YES on multiplication of tuple/list with non valid operand
2010-05-11 -- 0.20.1
* fix licensing to LGPL
* add ALL_NODES_CLASSES constant to nodes module
* nodes redirection cleanup (possible since refactoring)
* bug fix for python < 2.5: add Delete node on Subscript nodes if we are in a
del context
2010-03-22 -- 0.20.0
* fix #20464: raises “TypeError: '_Yes' object is not iterable†on list inference
* fix #19882: pylint hangs
* fix #20759: crash on pyreverse UNARY_OP_METHOD KeyError '~'
* fix #20760: crash on pyreverse : AttributeError: 'Subscript'
object has no attribute 'infer_lhs'
* fix #21980: [Python-modules-team] Bug#573229 : Pylint hangs;
improving the cache yields a speed improvement on big projects
* major refactoring: rebuild the tree instead of modify / monkey patching
* fix #19641: "maximum recursion depth exceeded" messages w/ python 2.6
this was introduced by a refactoring
* Ned Batchelder patch to properly import eggs with Windows line
endings. This fixes a problem with pylint not being able to
import setuptools.
* Winfried Plapper patches fixing .op attribute value for AugAssign nodes,
visit_ifexp in nodes_as_string
* Edward K. Ream / Tom Fleck patch closes #19641 (maximum recursion depth
exceeded" messages w/ python 2.6), see https://bugs.launchpad.net/pylint/+bug/456870
2009-12-18 -- 0.19.3
* fix name error making 0.19.2 almost useless
2009-12-18 -- 0.19.2
* fix #18773: inference bug on class member (due to bad handling of instance
/ class nodes "bounded" to method calls)
* fix #9515: strange message for non-class "Class baz has no egg member" (due to
bad inference of function call)
* fix #18953: inference fails with augmented assignment (special case for augmented
assignement in infer_ass method)
* fix #13944: false positive for class/instance attributes (Instance.getattr
should return assign nodes on instance classes as well as instance.
* include spelling fixes provided by Dotan Barak
2009-08-27 -- 0.19.1
* fix #8771: crash on yield expression
* fix #10024: line numbering bug with try/except/finally
* fix #10020: when building from living object, __name__ may be None
* fix #9891: help(logilab.astng) throws TypeError
* fix #9588: false positive E1101 for augmented assignment
2009-03-25 -- 0.19.0
* fixed python 2.6 issue (tests ok w/ 2.4, 2.5, 2.6. Anyone using 2.2 / 2.3
to tell us if it works?)
* some understanding of the __builtin__.property decorator
* inference: introduce UnboundMethod / rename InstanceMethod to BoundMethod
2009-03-19 -- 0.18.0
* major api / tree structure changes to make it works with compiler *and*
python >= 2.5 _ast module
* cleanup and refactoring on the way
2008-11-19 -- 0.17.4
* fix #6015: filter statements bug triggering W0631 false positive in pylint
* fix #5571: Function.is_method() should return False on module level
functions decorated by staticmethod/classmethod (avoid some crash in pylint)
* fix #5010: understand python 2.5 explicit relative imports
2008-09-10 -- 0.17.3
* fix #5889: astng crash on certain pyreverse projects
* fix bug w/ loop assignment in .lookup
* apply Maarten patch fixing a crash on TryFinalaly.block_range and fixing
'else'/'final' block line detection
2008-01-14 -- 0.17.2
* "with" statement support, patch provided by Brian Hawthorne
* fixed recursion arguments in nodes_of_class method as notified by
Dave Borowitz
* new InstanceMethod node introduced to wrap bound method (e.g. Function
node), patch provided by Dave Borowitz
2007-06-07 -- 0.17.1
* fix #3651: crash when callable as default arg
* fix #3670: subscription inference crash in some cases
* fix #3673: Lambda instance has no attribute 'pytype'
* fix crash with chained "import as"
* fix crash on numpy
* fix potential InfiniteRecursion error with builtin objects
* include patch from Marien Zwart fixing some test / py 2.5
* be more error resilient when accessing living objects from external
code in the manager
2007-02-22 -- 0.17.0
* api change to be able to infer using a context (used to infer function call
result only for now)
* slightly better inference on astng built from living object by trying to infer
dummy nodes (able to infer 'help' builtin for instance)
* external attribute definition support
* basic math operation inference
* new pytype method on possibly inferred node (e.g. module, classes, const...)
* fix a living object astng building bug, which was making "open" uninferable
* fix lookup of name in method bug (#3289)
* fix decorator lookup bug (#3261)
2006-11-23 -- 0.16.3
* enhance inference for the subscription notation (motivated by a patch from Amaury)
and for unary sub/add
2006-11-15 -- 0.16.2
* grrr, fixed python 2.3 incompatibility introduced by generator expression
scope handling
* upgrade to avoid warnings with logilab-common 0.21.0 (on which now
depends so)
* backported astutils module from logilab-common
2006-09-25 -- 0.16.1
* python 2.5 support, patch provided by Marien Zwart
* fix [Class|Module].block_range method (this fixes pylint's inline
disabling of messages on classes/modules)
* handle class.__bases__ and class.__mro__ (proper metaclass handling
still needed though)
* drop python2.2 support: remove code that was working around python2.2
* fixed generator expression scope bug
* patch transformer to extract correct line information
2006-04-19 -- 0.16.0
* fix living object building to consider classes such as property as
a class instead of a data descriptor
* fix multiple assignment inference which was discarding some solutions
* added some line manipulation methods to handle pylint's block messages
control feature (Node.last_source_line(), None.block_range(lineno)
2006-03-10 -- 0.15.1
* fix avoiding to load everything from living objects... Thanks Amaury!
* fix a possible NameError in Instance.infer_call_result
2006-03-06 -- 0.15.0
* fix possible infinite recursion on global statements (close #10342)
and in various other cases...
* fix locals/globals interactions when the global statement is used
(close #10434)
* multiple inference related bug fixes
* associate List, Tuple and Dict and Const nodes to their respective
classes
* new .ass_type method on assignment related node, returning the
assignment type node (Assign, For, ListCompFor, GenExprFor,
TryExcept)
* more API refactoring... .resolve method has disappeared, now you
have .ilookup on every nodes and .getattr/.igetattr on node
supporting the attribute protocol
* introduced a YES object that may be returned when there is ambiguity
on an inference path (typically function call when we don't know
arguments value)
* builder try to instantiate builtin exceptions subclasses to get their
instance attribute
2006-01-10 -- 0.14.0
* some major inference improvements and refactoring ! The drawback is
the introduction of some non backward compatible change in the API
but it's imho much cleaner and powerful now :)
* new boolean property .newstyle on Class nodes (implements #10073)
* new .import_module method on Module node to help in .resolve
refactoring
* .instance_attrs has list of assignments to instance attribute
dictionary as value instead of one
* added missing GenExprIf and GenExprInner nodes, and implements
as_string for each generator expression related nodes
* specifically catch KeyboardInterrupt to reraise it in some places
* fix so that module names are always absolute
* fix .resolve on package where a subpackage is imported in the
__init__ file
* fix a bug regarding construction of Function node from living object
with earlier version of python 2.4
* fix a NameError on Import and From self_resolve method
* fix a bug occurring when building an astng from a living object with
a property
* lint fixes
2005-11-07 -- 0.13.1
* fix bug on building from living module the same object in
encountered more than once time (e.g. builtins.object) (close #10069)
* fix bug in Class.ancestors() regarding inner classes (close #10072)
* fix .self_resolve() on From and Module nodes to handle package
precedence over module (close #10066)
* locals dict for package contains __path__ definition (close #10065)
* astng provide GenExpr and GenExprFor nodes with python >= 2.4
(close #10063)
* fix python2.2 compatibility (close #9922)
* link .__contains__ to .has_key on scoped node to speed up execution
* remove no more necessary .module_object() method on From and Module
nodes
* normalize parser.ParserError to SyntaxError with python 2.2
2005-10-21 -- 0.13.0
* .locals and .globals on scoped node handle now a list of references
to each assignment statements instead of a single reference to the
first assignment statement.
* fix bug with manager.astng_from_module_name when a context file is
given (notably fix ZODB 3.4 crash with pylint/pyreverse)
* fix Compare.as_string method
* fix bug with lambda object missing the "type" attribute
* some minor refactoring
* This package has been extracted from the logilab-common package, which
will be kept for some time for backward compatibility but will no
longer be maintained (this explains that this package is starting with
the 0.13 version number, since the fork occurs with the version
released in logilab-common 0.12).
astroid-1.4.4/COPYING 0000666 0000000 0000000 00000043103 12632317503 012355 0 ustar 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
astroid-1.4.4/COPYING.LESSER 0000666 0000000 0000000 00000063637 12632317503 013367 0 ustar 0000000 0000000
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard. To achieve this, non-free programs must
be allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least
three years, to give the same user the materials specified in
Subsection 6a, above, for a charge no more than the cost of
performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License
may add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).
To apply these terms, attach the following notices to the library.
It is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.
Copyright (C)
This library 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.
This library 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 library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the library,
if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James
Random Hacker.
, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
astroid-1.4.4/MANIFEST.in 0000666 0000000 0000000 00000000267 12632317503 013064 0 ustar 0000000 0000000 include ChangeLog
include README
include COPYING
include COPYING.LESSER
include tox.ini
recursive-include astroid/tests/testdata *.py *.zip *.egg
recursive-include astroid/brain *.py
astroid-1.4.4/PKG-INFO 0000666 0000000 0000000 00000006127 12646224174 012432 0 ustar 0000000 0000000 Metadata-Version: 1.1
Name: astroid
Version: 1.4.4
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 can use 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
astroid-1.4.4/README.rst 0000666 0000000 0000000 00000003746 12646222644 013030 0 ustar 0000000 0000000 .. 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 can use unittest discover::
python -m unittest discover -p "unittest*.py"
astroid-1.4.4/setup.cfg 0000666 0000000 0000000 00000000132 12646224174 013144 0 ustar 0000000 0000000 [wheel]
universal = 1
[egg_info]
tag_build =
tag_svn_revision = 0
tag_date = 0
astroid-1.4.4/setup.py 0000666 0000000 0000000 00000005406 12640767000 013040 0 ustar 0000000 0000000 #!/usr/bin/env python
# pylint: disable=W0404,W0622,W0704,W0613
# 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 .
"""Setup script for astroid."""
import os
from setuptools import setup, find_packages
from setuptools.command import easy_install
from setuptools.command import install_lib
real_path = os.path.realpath(__file__)
astroid_dir = os.path.dirname(real_path)
pkginfo = os.path.join(astroid_dir, 'astroid', '__pkginfo__.py')
with open(pkginfo, 'rb') as fobj:
exec(compile(fobj.read(), pkginfo, 'exec'), locals())
with open(os.path.join(astroid_dir, 'README.rst')) 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)
class AstroidEasyInstallLib(easy_install.easy_install):
# override this since pip/easy_install attempt to byte compile
# test data files, some of them being syntactically wrong by design,
# and this scares the end-user
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]
easy_install.easy_install.byte_compile(self, files)
def install():
return setup(name = distname,
version = version,
license = license,
description = description,
long_description = long_description,
classifiers = classifiers,
author = author,
author_email = author_email,
url = web,
include_package_data = True,
install_requires = install_requires,
packages = find_packages(),
cmdclass={'install_lib': AstroidInstallLib,
'easy_install': AstroidEasyInstallLib}
)
if __name__ == '__main__' :
install()
astroid-1.4.4/tox.ini 0000666 0000000 0000000 00000001043 12646222644 012640 0 ustar 0000000 0000000 [tox]
envlist = py27, py33, py34, py35, pypy, jython, pylint
skip_missing_interpreters = true
[testenv:pylint]
commands = pylint -rn --rcfile={toxinidir}/pylintrc {envsitepackagesdir}/astroid
[testenv]
deps =
py27,py33,pypy,jython: enum34
lazy-object-proxy
nose
py27,py33,py34,py35: numpy
pytest
python-dateutil
py27,py33,pypy,jython: singledispatch
six
wrapt
pylint: git+https://github.com/pycqa/pylint@1.5.0
commands = python -m unittest discover -s {envsitepackagesdir}/astroid/tests -p "unittest*.py"