Commit 9fccbfe4 authored by smut@google.com's avatar smut@google.com

Revert "pylint: upgrade to 1.3.1"

This reverts commit e642ee86.

Conflicts:
	pylintrc

Reason:
	All repos are borked.

TBR=vapier

Review URL: https://codereview.chromium.org/741023003

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@293042 0039d316-1c4b-4281-b951-d872f2087c98
parent 34458d40
...@@ -90,7 +90,7 @@ load-plugins= ...@@ -90,7 +90,7 @@ load-plugins=
# unpacking-non-sequence # unpacking-non-sequence
# unused-import # unused-import
# useless-else-on-loop # useless-else-on-loop
disable=C0103,C0111,C0302,I0010,I0011,R0801,R0901,R0902,R0903,R0904,R0911,R0912,R0913,R0914,R0915,R0921,R0922,W0122,W0141,W0142,W0402,W0404,W0511,W0603,W0703,W1201,bad-continuation,anomalous-backslash-in-string,bad-context-manager,bad-indentation,bad-str-strip-call,bad-whitespace,cell-var-from-loop,deprecated-lambda,eval-used,function-redefined,import-error,locally-enabled,missing-final-newline,no-init,no-name-in-module,no-self-use,not-callable,old-style-class,protected-access,superfluous-parens,super-on-old-class,too-many-function-args,trailing-whitespace,unnecessary-semicolon,unpacking-non-sequence,unused-import,useless-else-on-loop disable=C0103,C0111,C0302,I0010,I0011,R0801,R0901,R0902,R0903,R0904,R0911,R0912,R0913,R0914,R0915,R0921,R0922,W0122,W0141,W0142,W0402,W0404,W0511,W0603,W0703,W1201
[REPORTS] [REPORTS]
...@@ -99,6 +99,9 @@ disable=C0103,C0111,C0302,I0010,I0011,R0801,R0901,R0902,R0903,R0904,R0911,R0912, ...@@ -99,6 +99,9 @@ disable=C0103,C0111,C0302,I0010,I0011,R0801,R0901,R0902,R0903,R0904,R0911,R0912,
# (visual studio) and html # (visual studio) and html
output-format=text output-format=text
# Include message's id in output
include-ids=yes
# Put messages in a separate file for each module / package specified on the # Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be # command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]". # written in a file name "pylint_global.[txt|html]".
......
URL: http://www.logilab.org/project/logilab-astng URL: http://www.logilab.org/project/logilab-astng
Version: 1.2.1 Version: 0.23.1
License: GPL License: GPL
License File: LICENSE.txt License File: LICENSE.txt
......
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
# #
# This file is part of astroid. # This file is part of logilab-astng.
# #
# astroid is free software: you can redistribute it and/or modify it # 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 # 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 # Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version. # option) any later version.
# #
# astroid is distributed in the hope that it will be useful, but # logilab-astng is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details. # for more details.
# #
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>. # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
"""Python Abstract Syntax Tree New Generation """Python Abstract Syntax Tree New Generation
The aim of this module is to provide a common base representation of The aim of this module is to provide a common base representation of
...@@ -25,7 +27,7 @@ governed by pylint's needs. ...@@ -25,7 +27,7 @@ governed by pylint's needs.
It extends class defined in the python's _ast module with some It extends class defined in the python's _ast module with some
additional methods and attributes. Instance attributes are added by a additional methods and attributes. Instance attributes are added by a
builder object, which can either generate extended ast (let's call builder object, which can either generate extended ast (let's call
them astroid ;) by visiting an existent ast tree or by inspecting living them astng ;) by visiting an existent ast tree or by inspecting living
object. Methods are added by monkey patching ast classes. object. Methods are added by monkey patching ast classes.
Main modules are: Main modules are:
...@@ -33,86 +35,39 @@ Main modules are: ...@@ -33,86 +35,39 @@ Main modules are:
* nodes and scoped_nodes for more information about methods and * nodes and scoped_nodes for more information about methods and
attributes added to different node classes attributes added to different node classes
* the manager contains a high level object to get astroid trees from * the manager contains a high level object to get astng trees from
source files and living objects. It maintains a cache of previously source files and living objects. It maintains a cache of previously
constructed tree for quick access constructed tree for quick access
* builder contains the class responsible to build astroid trees * builder contains the class responsible to build astng trees
""" """
__doctype__ = "restructuredtext en" __doctype__ = "restructuredtext en"
import sys import sys
import re if sys.version_info >= (3, 0):
from operator import attrgetter BUILTINS_MODULE = 'builtins'
else:
BUILTINS_MODULE = '__builtin__'
# WARNING: internal imports order matters ! # WARNING: internal imports order matters !
# make all exception classes accessible from astroid package # make all exception classes accessible from astng package
from astroid.exceptions import * from logilab.astng.exceptions import *
# make all node classes accessible from astroid package # make all node classes accessible from astng package
from astroid.nodes import * from logilab.astng.nodes import *
# trigger extra monkey-patching # trigger extra monkey-patching
from astroid import inference from logilab.astng import inference
# more stuff available # more stuff available
from astroid import raw_building from logilab.astng import raw_building
from astroid.bases import YES, Instance, BoundMethod, UnboundMethod from logilab.astng.bases import YES, Instance, BoundMethod, UnboundMethod
from astroid.node_classes import are_exclusive, unpack_infer from logilab.astng.node_classes import are_exclusive, unpack_infer
from astroid.scoped_nodes import builtin_lookup from logilab.astng.scoped_nodes import builtin_lookup
# make a manager instance (borg) as well as Project and Package classes # make a manager instance (borg) as well as Project and Package classes
# accessible from astroid package # accessible from astng package
from astroid.manager import AstroidManager, Project from logilab.astng.manager import ASTNGManager, Project
MANAGER = AstroidManager() MANAGER = ASTNGManager()
del AstroidManager del ASTNGManager
# transform utilities (filters and decorator)
class AsStringRegexpPredicate(object):
"""Class to be used as predicate that may be given to `register_transform`
First argument is a regular expression that will be searched against the `as_string`
representation of the node onto which it's applied.
If specified, the second argument is an `attrgetter` expression that will be
applied on the node first to get the actual node on which `as_string` should
be called.
"""
def __init__(self, regexp, expression=None):
self.regexp = re.compile(regexp)
self.expression = expression
def __call__(self, node):
if self.expression is not None:
node = attrgetter(self.expression)(node)
return self.regexp.search(node.as_string())
def inference_tip(infer_function):
"""Given an instance specific inference function, return a function to be
given to MANAGER.register_transform to set this inference function.
Typical usage
.. sourcecode:: python
MANAGER.register_transform(CallFunc, inference_tip(infer_named_tuple),
AsStringRegexpPredicate('namedtuple', 'func'))
"""
def transform(node, infer_function=infer_function):
node._explicit_inference = infer_function
return node
return transform
# load brain plugins
from os import listdir
from os.path import join, dirname
BRAIN_MODULES_DIR = join(dirname(__file__), 'brain')
if BRAIN_MODULES_DIR not in sys.path:
# add it to the end of the list so user path take precedence
sys.path.append(BRAIN_MODULES_DIR)
# load modules in this directory
for module in listdir(BRAIN_MODULES_DIR):
if module.endswith('.py'):
__import__(module[:-3])
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
# #
# This file is part of astroid. # This file is part of logilab-astng.
# #
# astroid is free software: you can redistribute it and/or modify it # 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 # 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 # Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version. # option) any later version.
# #
# astroid is distributed in the hope that it will be useful, but # logilab-astng is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details. # for more details.
# #
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>. # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
"""astroid packaging information""" """logilab.astng packaging information"""
distname = 'astroid' distname = 'logilab-astng'
modname = 'astroid' modname = 'astng'
subpackage_of = 'logilab'
numversion = (1, 2, 1) numversion = (0, 23, 1)
version = '.'.join([str(num) for num in numversion]) version = '.'.join([str(num) for num in numversion])
install_requires = ['logilab-common >= 0.60.0'] install_requires = ['logilab-common >= 0.53.0']
license = 'LGPL' license = 'LGPL'
author = 'Logilab' author = 'Logilab'
author_email = 'python-projects@lists.logilab.org' author_email = 'python-projects@lists.logilab.org'
mailinglist = "mailto://%s" % author_email mailinglist = "mailto://%s" % author_email
web = 'http://bitbucket.org/logilab/astroid' web = "http://www.logilab.org/project/%s" % distname
ftp = "ftp://ftp.logilab.org/pub/%s" % modname
description = "rebuild a new abstract syntax tree from Python's ast" description = "rebuild a new abstract syntax tree from Python's ast"
from os.path import join from os.path import join
include_dirs = ['brain', include_dirs = [join('test', 'regrtest_data'),
join('test', 'regrtest_data'), join('test', 'data'), join('test', 'data2')]
join('test', 'data'), join('test', 'data2')
]
classifiers = ["Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Quality Assurance",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 3",
]
# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
# #
# This file is part of astroid. # This file is part of logilab-astng.
# #
# astroid is free software: you can redistribute it and/or modify it # 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 # 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 # Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version. # option) any later version.
# #
# astroid is distributed in the hope that it will be useful, but # logilab-astng is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details. # for more details.
# #
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>. # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
"""The AstroidBuilder makes astroid from living object and / or from _ast """The ASTNGBuilder makes astng from living object and / or from _ast
The builder is not thread safe and can't be used to parse different sources The builder is not thread safe and can't be used to parse different sources
at the same time. at the same time.
""" """
from __future__ import with_statement
__docformat__ = "restructuredtext en" __docformat__ = "restructuredtext en"
import sys import sys, re
from os.path import splitext, basename, exists, abspath from os.path import splitext, basename, dirname, exists, abspath
from astroid.exceptions import AstroidBuildingException, InferenceError from logilab.common.modutils import modpath_from_file
from astroid.raw_building import InspectBuilder
from astroid.rebuilder import TreeRebuilder from logilab.astng.exceptions import ASTNGBuildingException, InferenceError
from astroid.manager import AstroidManager from logilab.astng.raw_building import InspectBuilder
from astroid.bases import YES, Instance from logilab.astng.rebuilder import TreeRebuilder
from astroid.modutils import modpath_from_file from logilab.astng.manager import ASTNGManager
from logilab.astng.bases import YES, Instance
from _ast import PyCF_ONLY_AST from _ast import PyCF_ONLY_AST
def parse(string): def parse(string):
...@@ -42,21 +44,21 @@ if sys.version_info >= (3, 0): ...@@ -42,21 +44,21 @@ if sys.version_info >= (3, 0):
from tokenize import detect_encoding from tokenize import detect_encoding
def open_source_file(filename): def open_source_file(filename):
with open(filename, 'rb') as byte_stream: byte_stream = open(filename, 'bU')
encoding = detect_encoding(byte_stream.readline)[0] encoding = detect_encoding(byte_stream.readline)[0]
stream = open(filename, 'rU', encoding=encoding) stream = open(filename, 'U', encoding=encoding)
try: try:
data = stream.read() data = stream.read()
except UnicodeError: # wrong encodingg except UnicodeError, uex: # wrong encodingg
# detect_encoding returns utf-8 if no encoding specified # detect_encoding returns utf-8 if no encoding specified
msg = 'Wrong (%s) or no encoding specified' % encoding msg = 'Wrong (%s) or no encoding specified' % encoding
raise AstroidBuildingException(msg) raise ASTNGBuildingException(msg)
return stream, encoding, data return stream, encoding, data
else: else:
import re import re
_ENCODING_RGX = re.compile(r"\s*#+.*coding[:=]\s*([-\w.]+)") _ENCODING_RGX = re.compile("\s*#+.*coding[:=]\s*([-\w.]+)")
def _guess_encoding(string): def _guess_encoding(string):
"""get encoding from a python file as string or return None if not found """get encoding from a python file as string or return None if not found
...@@ -79,17 +81,17 @@ else: ...@@ -79,17 +81,17 @@ else:
# ast NG builder ############################################################## # ast NG builder ##############################################################
MANAGER = AstroidManager() MANAGER = ASTNGManager()
class AstroidBuilder(InspectBuilder): class ASTNGBuilder(InspectBuilder):
"""provide astroid building methods""" """provide astng building methods"""
rebuilder = TreeRebuilder()
def __init__(self, manager=None): def __init__(self, manager=None):
InspectBuilder.__init__(self)
self._manager = manager or MANAGER self._manager = manager or MANAGER
def module_build(self, module, modname=None): def module_build(self, module, modname=None):
"""build an astroid from a living module instance """build an astng from a living module instance
""" """
node = None node = None
path = getattr(module, '__file__', None) path = getattr(module, '__file__', None)
...@@ -101,59 +103,46 @@ class AstroidBuilder(InspectBuilder): ...@@ -101,59 +103,46 @@ class AstroidBuilder(InspectBuilder):
# this is a built-in module # this is a built-in module
# get a partial representation by introspection # get a partial representation by introspection
node = self.inspect_build(module, modname=modname, path=path) node = self.inspect_build(module, modname=modname, path=path)
# we have to handle transformation by ourselves since the rebuilder
# isn't called for builtin nodes
#
# XXX it's then only called for Module nodes, not for underlying
# nodes
node = self._manager.transform(node)
return node return node
def file_build(self, path, modname=None): def file_build(self, path, modname=None):
"""build astroid from a source code file (i.e. from an ast) """build astng from a source code file (i.e. from an ast)
path is expected to be a python source file path is expected to be a python source file
""" """
try: try:
_, encoding, data = open_source_file(path) stream, encoding, data = open_source_file(path)
except IOError, exc: except IOError, exc:
msg = 'Unable to load file %r (%s)' % (path, exc) msg = 'Unable to load file %r (%s)' % (path, exc)
raise AstroidBuildingException(msg) raise ASTNGBuildingException(msg)
except SyntaxError, exc: # py3k encoding specification error except SyntaxError, exc: # py3k encoding specification error
raise AstroidBuildingException(exc) raise ASTNGBuildingException(exc)
except LookupError, exc: # unknown encoding except LookupError, exc: # unknown encoding
raise AstroidBuildingException(exc) raise ASTNGBuildingException(exc)
# get module name if necessary # get module name if necessary
if modname is None: if modname is None:
try: try:
modname = '.'.join(modpath_from_file(path)) modname = '.'.join(modpath_from_file(path))
except ImportError: except ImportError:
modname = splitext(basename(path))[0] modname = splitext(basename(path))[0]
# build astroid representation # build astng representation
module = self._data_build(data, modname, path) node = self.string_build(data, modname, path)
return self._post_build(module, encoding) node.file_encoding = encoding
return node
def string_build(self, data, modname='', path=None): def string_build(self, data, modname='', path=None):
"""build astroid from source code string and return rebuilded astroid""" """build astng from source code string and return rebuilded astng"""
module = self._data_build(data, modname, path) module = self._data_build(data, modname, path)
module.file_bytes = data.encode('utf-8') self._manager.astng_cache[module.name] = module
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: # post tree building steps after we stored the module in the cache:
for from_node in module._from_nodes: for from_node in module._from_nodes:
if from_node.modname == '__future__':
for symbol, _ in from_node.names:
module.future_imports.add(symbol)
self.add_from_names_to_locals(from_node) self.add_from_names_to_locals(from_node)
# handle delayed assattr nodes # handle delayed assattr nodes
for delayed in module._delayed_assattr: for delayed in module._delayed_assattr:
self.delayed_assattr(delayed) self.delayed_assattr(delayed)
if modname:
for transformer in self._manager.transformers:
transformer(module)
return module return module
def _data_build(self, data, modname, path): def _data_build(self, data, modname, path):
...@@ -169,11 +158,11 @@ class AstroidBuilder(InspectBuilder): ...@@ -169,11 +158,11 @@ class AstroidBuilder(InspectBuilder):
package = True package = True
else: else:
package = path and path.find('__init__.py') > -1 or False package = path and path.find('__init__.py') > -1 or False
rebuilder = TreeRebuilder(self._manager) self.rebuilder.init()
module = rebuilder.visit_module(node, modname, package) module = self.rebuilder.visit_module(node, modname, package)
module.file = module.path = node_file module.file = module.path = node_file
module._from_nodes = rebuilder._from_nodes module._from_nodes = self.rebuilder._from_nodes
module._delayed_assattr = rebuilder._delayed_assattr module._delayed_assattr = self.rebuilder._delayed_assattr
return module return module
def add_from_names_to_locals(self, node): def add_from_names_to_locals(self, node):
...@@ -187,8 +176,8 @@ class AstroidBuilder(InspectBuilder): ...@@ -187,8 +176,8 @@ class AstroidBuilder(InspectBuilder):
for (name, asname) in node.names: for (name, asname) in node.names:
if name == '*': if name == '*':
try: try:
imported = node.do_import_module() imported = node.root().import_module(node.modname)
except InferenceError: except ASTNGBuildingException:
continue continue
for name in imported.wildcard_import_names(): for name in imported.wildcard_import_names():
node.parent.set_local(name, node) node.parent.set_local(name, node)
......
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
# #
# This file is part of astroid. # This file is part of logilab-astng.
# #
# astroid is free software: you can redistribute it and/or modify it # 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 # 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 # Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version. # option) any later version.
# #
# astroid is distributed in the hope that it will be useful, but # logilab-astng is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details. # for more details.
# #
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>. # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
"""this module contains exceptions used in the astroid library """this module contains exceptions used in the astng library
""" """
__doctype__ = "restructuredtext en" __doctype__ = "restructuredtext en"
class AstroidError(Exception): class ASTNGError(Exception):
"""base exception class for all astroid related exceptions""" """base exception class for all astng related exceptions"""
class AstroidBuildingException(AstroidError): class ASTNGBuildingException(ASTNGError):
"""exception class when we are unable to build an astroid representation""" """exception class when we are unable to build an astng representation"""
class ResolveError(AstroidError): class ResolveError(ASTNGError):
"""base class of astroid resolution/inference error""" """base class of astng resolution/inference error"""
class NotFoundError(ResolveError): class NotFoundError(ResolveError):
"""raised when we are unable to resolve a name""" """raised when we are unable to resolve a name"""
...@@ -36,15 +50,10 @@ class NotFoundError(ResolveError): ...@@ -36,15 +50,10 @@ class NotFoundError(ResolveError):
class InferenceError(ResolveError): class InferenceError(ResolveError):
"""raised when we are unable to infer a node""" """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): class UnresolvableName(InferenceError):
"""raised when we are unable to resolve a name""" """raised when we are unable to resolve a name"""
class NoDefault(AstroidError): class NoDefault(ASTNGError):
"""raised by function's `default_value` method when an argument has """raised by function's `default_value` method when an argument has
no default value no default value
""" """
......
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
# #
# This file is part of astroid. # This file is part of logilab-astng.
# #
# astroid is free software: you can redistribute it and/or modify it # 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 # 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 # Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version. # option) any later version.
# #
# astroid is distributed in the hope that it will be useful, but # logilab-astng is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details. # for more details.
# #
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>. # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
"""visitor doing some postprocessing on the astroid tree. """visitor doing some postprocessing on the astng tree.
Try to resolve definitions (namespace) dictionary, relationship... Try to resolve definitions (namespace) dictionary, relationship...
This module has been imported from pyreverse This module has been imported from pyreverse
...@@ -25,23 +39,25 @@ __docformat__ = "restructuredtext en" ...@@ -25,23 +39,25 @@ __docformat__ = "restructuredtext en"
from os.path import dirname from os.path import dirname
import astroid from logilab.common.modutils import get_module_part, is_relative, \
from astroid.exceptions import InferenceError is_standard_module
from astroid.utils import LocalsVisitor
from astroid.modutils import get_module_part, is_relative, is_standard_module
class IdGeneratorMixIn(object): from logilab import astng
from logilab.astng.exceptions import InferenceError
from logilab.astng.utils import LocalsVisitor
class IdGeneratorMixIn:
""" """
Mixin adding the ability to generate integer uid Mixin adding the ability to generate integer uid
""" """
def __init__(self, start_value=0): def __init__(self, start_value=0):
self.id_count = start_value self.id_count = start_value
def init_counter(self, start_value=0): def init_counter(self, start_value=0):
"""init the id counter """init the id counter
""" """
self.id_count = start_value self.id_count = start_value
def generate_id(self): def generate_id(self):
"""generate a new identifier """generate a new identifier
""" """
...@@ -52,26 +68,26 @@ class IdGeneratorMixIn(object): ...@@ -52,26 +68,26 @@ class IdGeneratorMixIn(object):
class Linker(IdGeneratorMixIn, LocalsVisitor): class Linker(IdGeneratorMixIn, LocalsVisitor):
""" """
walk on the project tree and resolve relationships. walk on the project tree and resolve relationships.
According to options the following attributes may be added to visited nodes: According to options the following attributes may be added to visited nodes:
* uid, * uid,
a unique identifier for the node (on astroid.Project, astroid.Module, a unique identifier for the node (on astng.Project, astng.Module,
astroid.Class and astroid.locals_type). Only if the linker has been instantiated astng.Class and astng.locals_type). Only if the linker has been instantiated
with tag=True parameter (False by default). with tag=True parameter (False by default).
* Function * Function
a mapping from locals names to their bounded value, which may be a a mapping from locals names to their bounded value, which may be a
constant like a string or an integer, or an astroid node (on astroid.Module, constant like a string or an integer, or an astng node (on astng.Module,
astroid.Class and astroid.Function). astng.Class and astng.Function).
* instance_attrs_type * instance_attrs_type
as locals_type but for klass member attributes (only on astroid.Class) as locals_type but for klass member attributes (only on astng.Class)
* implements, * implements,
list of implemented interface _objects_ (only on astroid.Class nodes) list of implemented interface _objects_ (only on astng.Class nodes)
""" """
def __init__(self, project, inherited_interfaces=0, tag=False): def __init__(self, project, inherited_interfaces=0, tag=False):
IdGeneratorMixIn.__init__(self) IdGeneratorMixIn.__init__(self)
LocalsVisitor.__init__(self) LocalsVisitor.__init__(self)
...@@ -82,30 +98,30 @@ class Linker(IdGeneratorMixIn, LocalsVisitor): ...@@ -82,30 +98,30 @@ class Linker(IdGeneratorMixIn, LocalsVisitor):
# visited project # visited project
self.project = project self.project = project
def visit_project(self, node): def visit_project(self, node):
"""visit an astroid.Project node """visit an astng.Project node
* optionally tag the node with a unique id * optionally tag the node with a unique id
""" """
if self.tag: if self.tag:
node.uid = self.generate_id() node.uid = self.generate_id()
for module in node.modules: for module in node.modules:
self.visit(module) self.visit(module)
def visit_package(self, node): def visit_package(self, node):
"""visit an astroid.Package node """visit an astng.Package node
* optionally tag the node with a unique id * optionally tag the node with a unique id
""" """
if self.tag: if self.tag:
node.uid = self.generate_id() node.uid = self.generate_id()
for subelmt in node.values(): for subelmt in node.values():
self.visit(subelmt) self.visit(subelmt)
def visit_module(self, node): def visit_module(self, node):
"""visit an astroid.Module node """visit an astng.Module node
* set the locals_type mapping * set the locals_type mapping
* set the depends mapping * set the depends mapping
* optionally tag the node with a unique id * optionally tag the node with a unique id
...@@ -116,10 +132,10 @@ class Linker(IdGeneratorMixIn, LocalsVisitor): ...@@ -116,10 +132,10 @@ class Linker(IdGeneratorMixIn, LocalsVisitor):
node.depends = [] node.depends = []
if self.tag: if self.tag:
node.uid = self.generate_id() node.uid = self.generate_id()
def visit_class(self, node): def visit_class(self, node):
"""visit an astroid.Class node """visit an astng.Class node
* set the locals_type and instance_attrs_type mappings * set the locals_type and instance_attrs_type mappings
* set the implements list and build it * set the implements list and build it
* optionally tag the node with a unique id * optionally tag the node with a unique id
...@@ -146,8 +162,8 @@ class Linker(IdGeneratorMixIn, LocalsVisitor): ...@@ -146,8 +162,8 @@ class Linker(IdGeneratorMixIn, LocalsVisitor):
node.implements = () node.implements = ()
def visit_function(self, node): def visit_function(self, node):
"""visit an astroid.Function node """visit an astng.Function node
* set the locals_type mapping * set the locals_type mapping
* optionally tag the node with a unique id * optionally tag the node with a unique id
""" """
...@@ -156,14 +172,14 @@ class Linker(IdGeneratorMixIn, LocalsVisitor): ...@@ -156,14 +172,14 @@ class Linker(IdGeneratorMixIn, LocalsVisitor):
node.locals_type = {} node.locals_type = {}
if self.tag: if self.tag:
node.uid = self.generate_id() node.uid = self.generate_id()
link_project = visit_project link_project = visit_project
link_module = visit_module link_module = visit_module
link_class = visit_class link_class = visit_class
link_function = visit_function link_function = visit_function
def visit_assname(self, node): def visit_assname(self, node):
"""visit an astroid.AssName node """visit an astng.AssName node
handle locals_type handle locals_type
""" """
...@@ -176,7 +192,7 @@ class Linker(IdGeneratorMixIn, LocalsVisitor): ...@@ -176,7 +192,7 @@ class Linker(IdGeneratorMixIn, LocalsVisitor):
frame = node.frame() frame = node.frame()
else: else:
# the name has been defined as 'global' in the frame and belongs # the name has been defined as 'global' in the frame and belongs
# there. Btw the frame is not yet visited as the name is in the # there. Btw the frame is not yet visited as the name is in the
# root locals; the frame hence has no locals_type attribute # root locals; the frame hence has no locals_type attribute
frame = node.root() frame = node.root()
try: try:
...@@ -188,11 +204,11 @@ class Linker(IdGeneratorMixIn, LocalsVisitor): ...@@ -188,11 +204,11 @@ class Linker(IdGeneratorMixIn, LocalsVisitor):
already_infered.append(valnode) already_infered.append(valnode)
except KeyError: except KeyError:
frame.locals_type[node.name] = values frame.locals_type[node.name] = values
except astroid.InferenceError: except astng.InferenceError:
pass pass
def handle_assattr_type(self, node, parent): def handle_assattr_type(self, node, parent):
"""handle an astroid.AssAttr node """handle an astng.AssAttr node
handle instance_attrs_type handle instance_attrs_type
""" """
...@@ -205,23 +221,23 @@ class Linker(IdGeneratorMixIn, LocalsVisitor): ...@@ -205,23 +221,23 @@ class Linker(IdGeneratorMixIn, LocalsVisitor):
already_infered.append(valnode) already_infered.append(valnode)
except KeyError: except KeyError:
parent.instance_attrs_type[node.attrname] = values parent.instance_attrs_type[node.attrname] = values
except astroid.InferenceError: except astng.InferenceError:
pass pass
def visit_import(self, node): def visit_import(self, node):
"""visit an astroid.Import node """visit an astng.Import node
resolve module dependencies resolve module dependencies
""" """
context_file = node.root().file context_file = node.root().file
for name in node.names: for name in node.names:
relative = is_relative(name[0], context_file) relative = is_relative(name[0], context_file)
self._imported_module(node, name[0], relative) self._imported_module(node, name[0], relative)
def visit_from(self, node): def visit_from(self, node):
"""visit an astroid.From node """visit an astng.From node
resolve module dependencies resolve module dependencies
""" """
basename = node.modname basename = node.modname
...@@ -238,13 +254,13 @@ class Linker(IdGeneratorMixIn, LocalsVisitor): ...@@ -238,13 +254,13 @@ class Linker(IdGeneratorMixIn, LocalsVisitor):
if fullname.find('.') > -1: if fullname.find('.') > -1:
try: try:
# XXX: don't use get_module_part, missing package precedence # XXX: don't use get_module_part, missing package precedence
fullname = get_module_part(fullname, context_file) fullname = get_module_part(fullname)
except ImportError: except ImportError:
continue continue
if fullname != basename: if fullname != basename:
self._imported_module(node, fullname, relative) self._imported_module(node, fullname, relative)
def compute_module(self, context_name, mod_path): def compute_module(self, context_name, mod_path):
"""return true if the module should be added to dependencies""" """return true if the module should be added to dependencies"""
package_dir = dirname(self.project.path) package_dir = dirname(self.project.path)
...@@ -253,7 +269,7 @@ class Linker(IdGeneratorMixIn, LocalsVisitor): ...@@ -253,7 +269,7 @@ class Linker(IdGeneratorMixIn, LocalsVisitor):
elif is_standard_module(mod_path, (package_dir,)): elif is_standard_module(mod_path, (package_dir,)):
return 1 return 1
return 0 return 0
# protected methods ######################################################## # protected methods ########################################################
def _imported_module(self, node, mod_path, relative): def _imported_module(self, node, mod_path, relative):
......
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
# #
# This file is part of astroid. # This file is part of logilab-astng.
# #
# astroid is free software: you can redistribute it and/or modify it # 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 # 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 # Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version. # option) any later version.
# #
# astroid is distributed in the hope that it will be useful, but # logilab-astng is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details. # for more details.
# #
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>. # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
"""This module contains some mixins for the different nodes. """This module contains some mixins for the different nodes.
""" """
from astroid.exceptions import (AstroidBuildingException, InferenceError, from logilab.astng.exceptions import (ASTNGBuildingException, InferenceError,
NotFoundError) NotFoundError)
class BlockRangeMixIn(object): class BlockRangeMixIn(object):
...@@ -41,7 +55,6 @@ class BlockRangeMixIn(object): ...@@ -41,7 +55,6 @@ class BlockRangeMixIn(object):
return lineno, orelse[0].fromlineno - 1 return lineno, orelse[0].fromlineno - 1
return lineno, last or self.tolineno return lineno, last or self.tolineno
class FilterStmtsMixin(object): class FilterStmtsMixin(object):
"""Mixin for statement filtering and assignment type""" """Mixin for statement filtering and assignment type"""
...@@ -79,13 +92,14 @@ class ParentAssignTypeMixin(AssignTypeMixin): ...@@ -79,13 +92,14 @@ class ParentAssignTypeMixin(AssignTypeMixin):
return self.parent.ass_type() return self.parent.ass_type()
class FromImportMixIn(FilterStmtsMixin): class FromImportMixIn(FilterStmtsMixin):
"""MixIn for From and Import Nodes""" """MixIn for From and Import Nodes"""
def _infer_name(self, frame, name): def _infer_name(self, frame, name):
return name return name
def do_import_module(self, modname=None): def do_import_module(self, modname):
"""return the ast for a module whose name is <modname> imported by <self> """return the ast for a module whose name is <modname> imported by <self>
""" """
# handle special case where we are on a package node importing a module # handle special case where we are on a package node importing a module
...@@ -94,8 +108,6 @@ class FromImportMixIn(FilterStmtsMixin): ...@@ -94,8 +108,6 @@ class FromImportMixIn(FilterStmtsMixin):
# XXX: no more needed ? # XXX: no more needed ?
mymodule = self.root() mymodule = self.root()
level = getattr(self, 'level', None) # Import as no level 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 # XXX we should investigate deeper if we really want to check
# importing itself: modname and mymodule.name be relative or absolute # importing itself: modname and mymodule.name be relative or absolute
if mymodule.relative_to_absolute_name(modname, level) == mymodule.name: if mymodule.relative_to_absolute_name(modname, level) == mymodule.name:
...@@ -103,7 +115,7 @@ class FromImportMixIn(FilterStmtsMixin): ...@@ -103,7 +115,7 @@ class FromImportMixIn(FilterStmtsMixin):
return mymodule return mymodule
try: try:
return mymodule.import_module(modname, level=level) return mymodule.import_module(modname, level=level)
except AstroidBuildingException: except ASTNGBuildingException:
raise InferenceError(modname) raise InferenceError(modname)
except SyntaxError, ex: except SyntaxError, ex:
raise InferenceError(str(ex)) raise InferenceError(str(ex))
...@@ -120,3 +132,5 @@ class FromImportMixIn(FilterStmtsMixin): ...@@ -120,3 +132,5 @@ class FromImportMixIn(FilterStmtsMixin):
return name return name
raise NotFoundError(asname) raise NotFoundError(asname)
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
# #
# This file is part of astroid. # This file is part of logilab-astng.
# #
# astroid is free software: you can redistribute it and/or modify it # 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 # 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 # Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version. # option) any later version.
# #
# astroid is distributed in the hope that it will be useful, but # logilab-astng is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details. # for more details.
# #
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>. # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
""" """
on all nodes : on all nodes :
.is_statement, returning true if the node should be considered as a .is_statement, returning true if the node should be considered as a
...@@ -26,7 +28,7 @@ on all nodes : ...@@ -26,7 +28,7 @@ on all nodes :
.frame(), returning the first node defining a new local scope (i.e. .frame(), returning the first node defining a new local scope (i.e.
Module, Function or Class) Module, Function or Class)
.set_local(name, node), define an identifier <name> on the first parent frame, .set_local(name, node), define an identifier <name> on the first parent frame,
with the node defining it. This is used by the astroid builder and should not with the node defining it. This is used by the astng builder and should not
be used from out there. be used from out there.
on From and Import : on From and Import :
...@@ -37,15 +39,15 @@ on From and Import : ...@@ -37,15 +39,15 @@ on From and Import :
__docformat__ = "restructuredtext en" __docformat__ = "restructuredtext en"
from astroid.node_classes import Arguments, AssAttr, Assert, Assign, \ from logilab.astng.node_classes import Arguments, AssAttr, Assert, Assign, \
AssName, AugAssign, Backquote, BinOp, BoolOp, Break, CallFunc, Compare, \ AssName, AugAssign, Backquote, BinOp, BoolOp, Break, CallFunc, Compare, \
Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete, \ Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete, \
Dict, Discard, Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, For, \ Dict, Discard, Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, For, \
From, Getattr, Global, If, IfExp, Import, Index, Keyword, \ From, Getattr, Global, If, IfExp, Import, Index, Keyword, \
List, Name, Nonlocal, Pass, Print, Raise, Return, Set, Slice, Starred, Subscript, \ List, Name, Nonlocal, Pass, Print, Raise, Return, Set, Slice, Starred, Subscript, \
TryExcept, TryFinally, Tuple, UnaryOp, While, With, Yield, YieldFrom, \ TryExcept, TryFinally, Tuple, UnaryOp, While, With, Yield, \
const_factory const_factory
from astroid.scoped_nodes import Module, GenExpr, Lambda, DictComp, \ from logilab.astng.scoped_nodes import Module, GenExpr, Lambda, DictComp, \
ListComp, SetComp, Function, Class ListComp, SetComp, Function, Class
ALL_NODE_CLASSES = ( ALL_NODE_CLASSES = (
...@@ -68,6 +70,6 @@ ALL_NODE_CLASSES = ( ...@@ -68,6 +70,6 @@ ALL_NODE_CLASSES = (
TryExcept, TryFinally, Tuple, TryExcept, TryFinally, Tuple,
UnaryOp, UnaryOp,
While, With, While, With,
Yield, YieldFrom Yield,
) )
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
# #
# This file is part of astroid. # This file is part of logilab-astng.
# #
# astroid is free software: you can redistribute it and/or modify it # 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 # 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 # Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version. # option) any later version.
# #
# astroid is distributed in the hope that it will be useful, but # logilab-astng is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details. # for more details.
# #
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>. # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
"""this module contains a set of functions to handle python protocols for nodes """this module contains a set of functions to handle python protocols for nodes
where it makes sense. where it makes sense.
""" """
__doctype__ = "restructuredtext en" __doctype__ = "restructuredtext en"
from astroid.exceptions import InferenceError, NoDefault, NotFoundError from logilab.astng.exceptions import InferenceError, NoDefault
from astroid.node_classes import unpack_infer from logilab.astng.node_classes import unpack_infer
from astroid.bases import copy_context, \ from logilab.astng.bases import copy_context, \
raise_if_nothing_infered, yes_if_nothing_infered, Instance, YES raise_if_nothing_infered, yes_if_nothing_infered, Instance, Generator, YES
from astroid.nodes import const_factory from logilab.astng.nodes import const_factory
from astroid import nodes from logilab.astng import nodes
BIN_OP_METHOD = {'+': '__add__',
'-': '__sub__',
'/': '__div__',
'//': '__floordiv__',
'*': '__mul__',
'**': '__power__',
'%': '__mod__',
'&': '__and__',
'|': '__or__',
'^': '__xor__',
'<<': '__lshift__',
'>>': '__rshift__',
}
UNARY_OP_METHOD = {'+': '__pos__',
'-': '__neg__',
'~': '__invert__',
'not': None, # XXX not '__nonzero__'
}
# unary operations ############################################################ # unary operations ############################################################
...@@ -90,7 +72,7 @@ BIN_OP_IMPL = {'+': lambda a, b: a + b, ...@@ -90,7 +72,7 @@ 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,
} }
for key, impl in BIN_OP_IMPL.items(): for key, impl in BIN_OP_IMPL.items():
BIN_OP_IMPL[key+'='] = impl BIN_OP_IMPL[key+'='] = impl
...@@ -153,25 +135,6 @@ def dict_infer_binary_op(self, operator, other, context): ...@@ -153,25 +135,6 @@ def dict_infer_binary_op(self, operator, other, context):
# XXX else log TypeError # XXX else log TypeError
nodes.Dict.infer_binary_op = yes_if_nothing_infered(dict_infer_binary_op) nodes.Dict.infer_binary_op = yes_if_nothing_infered(dict_infer_binary_op)
def instance_infer_binary_op(self, operator, other, context):
try:
methods = self.getattr(BIN_OP_METHOD[operator])
except (NotFoundError, KeyError):
# Unknown operator
yield YES
else:
for method in methods:
if not isinstance(method, nodes.Function):
continue
for result in method.infer_call_result(self, context):
if result is not YES:
yield result
# We are interested only in the first infered method,
# don't go looking in the rest of the methods of the ancestors.
break
Instance.infer_binary_op = yes_if_nothing_infered(instance_infer_binary_op)
# assignment ################################################################## # assignment ##################################################################
...@@ -205,7 +168,7 @@ def _resolve_looppart(parts, asspath, context): ...@@ -205,7 +168,7 @@ def _resolve_looppart(parts, asspath, context):
assigned = stmt.getitem(index, context) assigned = stmt.getitem(index, context)
except (AttributeError, IndexError): except (AttributeError, IndexError):
continue continue
except TypeError: # stmt is unsubscriptable Const except TypeError, exc: # stmt is unsubscriptable Const
continue continue
if not asspath: if not asspath:
# we achieved to resolved the assignment path, # we achieved to resolved the assignment path,
...@@ -270,14 +233,10 @@ def _arguments_infer_argname(self, name, context): ...@@ -270,14 +233,10 @@ def _arguments_infer_argname(self, name, context):
yield self.parent.parent.frame() yield self.parent.parent.frame()
return return
if name == self.vararg: if name == self.vararg:
vararg = const_factory(()) yield const_factory(())
vararg.parent = self
yield vararg
return return
if name == self.kwarg: if name == self.kwarg:
kwarg = const_factory({}) yield const_factory({})
kwarg.parent = self
yield kwarg
return return
# if there is a default value, yield it. And then yield YES to reflect # if there is a default value, yield it. And then yield YES to reflect
# we can't guess given argument value # we can't guess given argument value
...@@ -353,13 +312,10 @@ nodes.ExceptHandler.assigned_stmts = raise_if_nothing_infered(excepthandler_assi ...@@ -353,13 +312,10 @@ nodes.ExceptHandler.assigned_stmts = raise_if_nothing_infered(excepthandler_assi
def with_assigned_stmts(self, node, context=None, asspath=None): def with_assigned_stmts(self, node, context=None, asspath=None):
if asspath is None: if asspath is None:
for _, vars in self.items: for lst in self.vars.infer(context):
if vars is None: if isinstance(lst, (nodes.Tuple, nodes.List)):
continue for item in lst.nodes:
for lst in vars.infer(context): yield item
if isinstance(lst, (nodes.Tuple, nodes.List)):
for item in lst.nodes:
yield item
nodes.With.assigned_stmts = raise_if_nothing_infered(with_assigned_stmts) nodes.With.assigned_stmts = raise_if_nothing_infered(with_assigned_stmts)
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
# #
# This file is part of astroid. # This file is part of logilab-astng.
# #
# astroid is free software: you can redistribute it and/or modify it # 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 # 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 # Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version. # option) any later version.
# #
# astroid is distributed in the hope that it will be useful, but # logilab-astng is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details. # for more details.
# #
# You should have received a copy of the GNU Lesser General Public License along # You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>. # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
"""this module contains some utilities to navigate in the tree or to """this module contains some utilities to navigate in the tree or to
extract information from it extract information from it
""" """
__docformat__ = "restructuredtext en" __docformat__ = "restructuredtext en"
from astroid.exceptions import AstroidBuildingException from logilab.astng.exceptions import ASTNGBuildingException
from astroid.builder import parse
class ASTWalker(object): class ASTWalker:
"""a walker visiting a tree in preorder, calling on the handler: """a walker visiting a tree in preorder, calling on the handler:
* visit_<class name> on entering a node, where class name is the class of * visit_<class name> on entering a node, where class name is the class of
...@@ -98,7 +99,7 @@ class LocalsVisitor(ASTWalker): ...@@ -98,7 +99,7 @@ class LocalsVisitor(ASTWalker):
if methods[0] is not None: if methods[0] is not None:
methods[0](node) methods[0](node)
if 'locals' in node.__dict__: # skip Instance and other proxy if 'locals' in node.__dict__: # skip Instance and other proxy
for local_node in node.values(): for name, local_node in node.items():
self.visit(local_node) self.visit(local_node)
if methods[1] is not None: if methods[1] is not None:
return methods[1](node) return methods[1](node)
...@@ -112,25 +113,27 @@ def _check_children(node): ...@@ -112,25 +113,27 @@ def _check_children(node):
print "Hm, child of %s is None" % node print "Hm, child of %s is None" % node
continue continue
if not hasattr(child, 'parent'): if not hasattr(child, 'parent'):
print " ERROR: %s has child %s %x with no parent" % ( print " ERROR: %s has child %s %x with no parent" % (node, child, id(child))
node, child, id(child))
elif not child.parent: elif not child.parent:
print " ERROR: %s has child %s %x with parent %r" % ( print " ERROR: %s has child %s %x with parent %r" % (node, child, id(child), child.parent)
node, child, id(child), child.parent)
elif child.parent is not node: elif child.parent is not node:
print " ERROR: %s %x has child %s %x with wrong parent %s" % ( print " ERROR: %s %x has child %s %x with wrong parent %s" % (node,
node, id(node), child, id(child), child.parent) id(node), child, id(child), child.parent)
else: else:
ok = True ok = True
if not ok: if not ok:
print "lines;", node.lineno, child.lineno print "lines;", node.lineno, child.lineno
print "of module", node.root(), node.root().name print "of module", node.root(), node.root().name
raise AstroidBuildingException raise ASTNGBuildingException
_check_children(child) _check_children(child)
from _ast import PyCF_ONLY_AST
def parse(string):
return compile(string, "<string>", 'exec', PyCF_ONLY_AST)
class TreeTester(object): class TreeTester(object):
'''A helper class to see _ast tree and compare with astroid tree '''A helper class to see _ast tree and compare with astng tree
indent: string for tree indent representation indent: string for tree indent representation
lineno: bool to tell if we should print the line numbers lineno: bool to tell if we should print the line numbers
...@@ -143,11 +146,11 @@ class TreeTester(object): ...@@ -143,11 +146,11 @@ class TreeTester(object):
. <Print> . <Print>
. . nl = True . . nl = True
. ] . ]
>>> print tester.astroid_tree_repr() >>> print tester.astng_tree_repr()
Module() Module()
body = [ body = [
Print() Print()
dest = dest =
values = [ values = [
] ]
] ]
...@@ -182,8 +185,8 @@ class TreeTester(object): ...@@ -182,8 +185,8 @@ class TreeTester(object):
if _done is None: if _done is None:
_done = set() _done = set()
if node in _done: if node in _done:
self._string += '\nloop in tree: %r (%s)' % ( self._string += '\nloop in tree: %r (%s)' % (node,
node, getattr(node, 'lineno', None)) getattr(node, 'lineno', None))
return return
_done.add(node) _done.add(node)
self._string += '\n' + indent + '<%s>' % node.__class__.__name__ self._string += '\n' + indent + '<%s>' % node.__class__.__name__
...@@ -199,7 +202,7 @@ class TreeTester(object): ...@@ -199,7 +202,7 @@ class TreeTester(object):
continue continue
if a in ("lineno", "col_offset") and not self.lineno: if a in ("lineno", "col_offset") and not self.lineno:
continue continue
self._string += '\n' + indent + a + " = " + repr(attr) self._string +='\n' + indent + a + " = " + repr(attr)
for field in node._fields or (): for field in node._fields or ():
attr = node_dict[field] attr = node_dict[field]
if attr is None: if attr is None:
...@@ -221,16 +224,16 @@ class TreeTester(object): ...@@ -221,16 +224,16 @@ class TreeTester(object):
self._string += '\n' + indent + field + " = " + repr(attr) self._string += '\n' + indent + field + " = " + repr(attr)
def build_astroid_tree(self): def build_astng_tree(self):
"""build astroid tree from the _ast tree """build astng tree from the _ast tree
""" """
from astroid.builder import AstroidBuilder from logilab.astng.builder import ASTNGBuilder
tree = AstroidBuilder().string_build(self.sourcecode) tree = ASTNGBuilder().string_build(self.sourcecode)
return tree return tree
def astroid_tree_repr(self, ids=False): def astng_tree_repr(self, ids=False):
"""build the astroid tree and return a nice tree representation""" """build the astng tree and return a nice tree representation"""
mod = self.build_astroid_tree() mod = self.build_astng_tree()
return mod.repr_tree(ids) return mod.repr_tree(ids)
......
"""Astroid hooks for the Python 2 GObject introspection bindings.
Helps with understanding everything imported from 'gi.repository'
"""
import inspect
import sys
import re
from astroid import MANAGER, AstroidBuildingException
from astroid.builder import AstroidBuilder
_inspected_modules = {}
_identifier_re = r'^[A-Za-z_]\w*$'
def _gi_build_stub(parent):
"""
Inspect the passed module recursively and build stubs for functions,
classes, etc.
"""
classes = {}
functions = {}
constants = {}
methods = {}
for name in dir(parent):
if name.startswith("__"):
continue
# Check if this is a valid name in python
if not re.match(_identifier_re, name):
continue
try:
obj = getattr(parent, name)
except:
continue
if inspect.isclass(obj):
classes[name] = obj
elif (inspect.isfunction(obj) or
inspect.isbuiltin(obj)):
functions[name] = obj
elif (inspect.ismethod(obj) or
inspect.ismethoddescriptor(obj)):
methods[name] = obj
elif type(obj) in [int, str]:
constants[name] = obj
elif (str(obj).startswith("<flags") or
str(obj).startswith("<enum ") or
str(obj).startswith("<GType ") or
inspect.isdatadescriptor(obj)):
constants[name] = 0
elif callable(obj):
# Fall back to a function for anything callable
functions[name] = obj
else:
# Assume everything else is some manner of constant
constants[name] = 0
ret = ""
if constants:
ret += "# %s contants\n\n" % parent.__name__
for name in sorted(constants):
if name[0].isdigit():
# GDK has some busted constant names like
# Gdk.EventType.2BUTTON_PRESS
continue
val = constants[name]
strval = str(val)
if type(val) is str:
strval = '"%s"' % str(val).replace("\\", "\\\\")
ret += "%s = %s\n" % (name, strval)
if ret:
ret += "\n\n"
if functions:
ret += "# %s functions\n\n" % parent.__name__
for name in sorted(functions):
func = functions[name]
ret += "def %s(*args, **kwargs):\n" % name
ret += " pass\n"
if ret:
ret += "\n\n"
if methods:
ret += "# %s methods\n\n" % parent.__name__
for name in sorted(methods):
func = methods[name]
ret += "def %s(self, *args, **kwargs):\n" % name
ret += " pass\n"
if ret:
ret += "\n\n"
if classes:
ret += "# %s classes\n\n" % parent.__name__
for name in sorted(classes):
ret += "class %s(object):\n" % name
classret = _gi_build_stub(classes[name])
if not classret:
classret = "pass\n"
for line in classret.splitlines():
ret += " " + line + "\n"
ret += "\n"
return ret
# Overwrite Module.module_import to _actually_ import the introspected module if
# it's a gi module, then build stub code by examining its info and get an astng
# from that
from astroid.scoped_nodes import Module
_orig_import_module = Module.import_module
def _new_import_module(self, modname, relative_only=False, level=None):
# Could be a static piece of gi.repository or whatever unrelated module,
# let that fall through
try:
return _orig_import_module(self, modname, relative_only, level)
except AstroidBuildingException:
# we only consider gi.repository submodules
if not modname.startswith('gi.repository.'):
if relative_only and level is None:
level = 0
modname = self.relative_to_absolute_name(modname, level)
if not modname.startswith('gi.repository.'):
raise
# build astroid representation unless we already tried so
if modname not in _inspected_modules:
modnames = [modname]
# GLib and GObject have some special case handling
# in pygobject that we need to cope with
if modname == 'gi.repository.GLib':
modnames.append('gi._glib')
elif modname == 'gi.repository.GObject':
modnames.append('gi._gobject')
try:
modcode = ''
for m in modnames:
__import__(m)
modcode += _gi_build_stub(sys.modules[m])
except ImportError:
astng = _inspected_modules[modname] = None
else:
astng = AstroidBuilder(MANAGER).string_build(modcode, modname)
_inspected_modules[modname] = astng
else:
astng = _inspected_modules[modname]
if astng is None:
raise AstroidBuildingException('Failed to import module %r' % modname)
return astng
Module.import_module = _new_import_module
from astroid import MANAGER
from astroid.builder import AstroidBuilder
def mechanize_transform(module):
fake = 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
''')
module.locals['Browser'] = fake.locals['Browser']
import py2stdlib
py2stdlib.MODULE_TRANSFORMS['mechanize'] = mechanize_transform
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
URL: http://www.logilab.org/project/logilab-common URL: http://www.logilab.org/project/logilab-common
Version: 0.63.1 Version: 0.57.1
License: GPL License: GPL
License File: LICENSE.txt License File: LICENSE.txt
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -72,7 +72,7 @@ def register_object_name(object, namepath): ...@@ -72,7 +72,7 @@ def register_object_name(object, namepath):
name = [CosNaming.NameComponent(id, kind)] name = [CosNaming.NameComponent(id, kind)]
try: try:
context = context.bind_new_context(name) context = context.bind_new_context(name)
except CosNaming.NamingContext.AlreadyBound as ex: except CosNaming.NamingContext.AlreadyBound, ex:
context = context.resolve(name)._narrow(CosNaming.NamingContext) context = context.resolve(name)._narrow(CosNaming.NamingContext)
assert context is not None, \ assert context is not None, \
'test context exists but is not a NamingContext' 'test context exists but is not a NamingContext'
...@@ -81,7 +81,7 @@ def register_object_name(object, namepath): ...@@ -81,7 +81,7 @@ def register_object_name(object, namepath):
name = [CosNaming.NameComponent(id, kind)] name = [CosNaming.NameComponent(id, kind)]
try: try:
context.bind(name, object._this()) context.bind(name, object._this())
except CosNaming.NamingContext.AlreadyBound as ex: except CosNaming.NamingContext.AlreadyBound, ex:
context.rebind(name, object._this()) context.rebind(name, object._this())
def activate_POA(): def activate_POA():
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment