| Index: third_party/logilab/astng/manager.py
|
| diff --git a/third_party/logilab/astroid/manager.py b/third_party/logilab/astng/manager.py
|
| similarity index 53%
|
| rename from third_party/logilab/astroid/manager.py
|
| rename to third_party/logilab/astng/manager.py
|
| index fde52e2b138c5a0eb59d42125e99416b263799e7..8a4f02bb642ed2e3a348d11eaccd252418574e66 100644
|
| --- a/third_party/logilab/astroid/manager.py
|
| +++ b/third_party/logilab/astng/manager.py
|
| @@ -1,45 +1,46 @@
|
| -# 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
|
| +# 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
|
| # 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
|
| +# 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 astroid. If not, see <http://www.gnu.org/licenses/>.
|
| -"""astroid manager: avoid multiple astroid build of a same module when
|
| -possible by providing a class responsible to get astroid representation
|
| +# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
|
| +"""astng manager: avoid multiple astng build of a same module when
|
| +possible by providing a class responsible to get astng representation
|
| from various source and using a cache of built modules)
|
| """
|
|
|
| __docformat__ = "restructuredtext en"
|
|
|
| +import sys
|
| import os
|
| -from os.path import dirname, join, isdir, exists
|
| -from warnings import warn
|
| +from os.path import dirname, basename, abspath, join, isdir, exists
|
|
|
| -from logilab.common.configuration import OptionsProviderMixIn
|
| -
|
| -from astroid.exceptions import AstroidBuildingException
|
| -from astroid.modutils import NoSourceFile, is_python_source, \
|
| +from logilab.common.modutils import NoSourceFile, is_python_source, \
|
| file_from_modpath, load_module_from_name, modpath_from_file, \
|
| get_module_files, get_source_file, zipimport
|
| +from logilab.common.configuration import OptionsProviderMixIn
|
|
|
| +from logilab.astng.exceptions import ASTNGBuildingException
|
|
|
| -def astroid_wrapper(func, modname):
|
| - """wrapper to give to AstroidManager.project_from_files"""
|
| +def astng_wrapper(func, modname):
|
| + """wrapper to give to ASTNGManager.project_from_files"""
|
| print 'parsing %s...' % modname
|
| try:
|
| return func(modname)
|
| - except AstroidBuildingException, exc:
|
| + except ASTNGBuildingException, exc:
|
| print exc
|
| except Exception, exc:
|
| import traceback
|
| @@ -57,14 +58,14 @@ def safe_repr(obj):
|
|
|
|
|
|
|
| -class AstroidManager(OptionsProviderMixIn):
|
| - """the astroid manager, responsible to build astroid from files
|
| +class ASTNGManager(OptionsProviderMixIn):
|
| + """the astng manager, responsible to build astng from files
|
| or modules.
|
|
|
| Use the Borg pattern.
|
| """
|
|
|
| - name = 'astroid loader'
|
| + name = 'astng loader'
|
| options = (("ignore",
|
| {'type' : "csv", 'metavar' : "<file>",
|
| 'dest' : "black_list", "default" : ('CVS',),
|
| @@ -75,20 +76,20 @@ class AstroidManager(OptionsProviderMixIn):
|
| {'default': "No Name", 'type' : 'string', 'short': 'p',
|
| 'metavar' : '<project name>',
|
| 'help' : 'set the project name.'}),
|
| - )
|
| + )
|
| brain = {}
|
| def __init__(self):
|
| - self.__dict__ = AstroidManager.brain
|
| + self.__dict__ = ASTNGManager.brain
|
| if not self.__dict__:
|
| OptionsProviderMixIn.__init__(self)
|
| self.load_defaults()
|
| # NOTE: cache entries are added by the [re]builder
|
| - self.astroid_cache = {}
|
| + self.astng_cache = {}
|
| self._mod_file_cache = {}
|
| - self.transforms = {}
|
| + self.transformers = []
|
|
|
| - def ast_from_file(self, filepath, modname=None, fallback=True, source=False):
|
| - """given a module name, return the astroid object"""
|
| + def astng_from_file(self, filepath, modname=None, fallback=True, source=False):
|
| + """given a module name, return the astng object"""
|
| try:
|
| filepath = get_source_file(filepath, include_no_ext=True)
|
| source = True
|
| @@ -99,23 +100,23 @@ class AstroidManager(OptionsProviderMixIn):
|
| modname = '.'.join(modpath_from_file(filepath))
|
| except ImportError:
|
| modname = filepath
|
| - if modname in self.astroid_cache and self.astroid_cache[modname].file == filepath:
|
| - return self.astroid_cache[modname]
|
| + if modname in self.astng_cache:
|
| + return self.astng_cache[modname]
|
| if source:
|
| - from astroid.builder import AstroidBuilder
|
| - return AstroidBuilder(self).file_build(filepath, modname)
|
| + from logilab.astng.builder import ASTNGBuilder
|
| + return ASTNGBuilder(self).file_build(filepath, modname)
|
| elif fallback and modname:
|
| - return self.ast_from_module_name(modname)
|
| - raise AstroidBuildingException('unable to get astroid for file %s' %
|
| - filepath)
|
| -
|
| - def ast_from_module_name(self, modname, context_file=None):
|
| - """given a module name, return the astroid object"""
|
| - if modname in self.astroid_cache:
|
| - return self.astroid_cache[modname]
|
| + return self.astng_from_module_name(modname)
|
| + raise ASTNGBuildingException('unable to get astng for file %s' %
|
| + filepath)
|
| +
|
| + def astng_from_module_name(self, modname, context_file=None):
|
| + """given a module name, return the astng object"""
|
| + if modname in self.astng_cache:
|
| + return self.astng_cache[modname]
|
| if modname == '__main__':
|
| - from astroid.builder import AstroidBuilder
|
| - return AstroidBuilder(self).string_build('', modname)
|
| + from logilab.astng.builder import ASTNGBuilder
|
| + return ASTNGBuilder(self).string_build('', modname)
|
| old_cwd = os.getcwd()
|
| if context_file:
|
| os.chdir(dirname(context_file))
|
| @@ -130,17 +131,17 @@ class AstroidManager(OptionsProviderMixIn):
|
| module = load_module_from_name(modname)
|
| except Exception, ex:
|
| msg = 'Unable to load module %s (%s)' % (modname, ex)
|
| - raise AstroidBuildingException(msg)
|
| - return self.ast_from_module(module, modname)
|
| - return self.ast_from_file(filepath, modname, fallback=False)
|
| + raise ASTNGBuildingException(msg)
|
| + return self.astng_from_module(module, modname)
|
| + return self.astng_from_file(filepath, modname, fallback=False)
|
| finally:
|
| os.chdir(old_cwd)
|
|
|
| def zip_import_data(self, filepath):
|
| if zipimport is None:
|
| return None
|
| - from astroid.builder import AstroidBuilder
|
| - builder = AstroidBuilder(self)
|
| + from logilab.astng.builder import ASTNGBuilder
|
| + builder = ASTNGBuilder(self)
|
| for ext in ('.zip', '.egg'):
|
| try:
|
| eggpath, resource = filepath.rsplit(ext + '/', 1)
|
| @@ -150,7 +151,7 @@ class AstroidManager(OptionsProviderMixIn):
|
| importer = zipimport.zipimporter(eggpath + ext)
|
| zmodname = resource.replace('/', '.')
|
| if importer.is_package(resource):
|
| - zmodname = zmodname + '.__init__'
|
| + zmodname = zmodname + '.__init__'
|
| module = builder.string_build(importer.get_source(resource),
|
| zmodname, filepath)
|
| return module
|
| @@ -167,41 +168,41 @@ class AstroidManager(OptionsProviderMixIn):
|
| context_file=contextfile)
|
| except ImportError, ex:
|
| msg = 'Unable to load module %s (%s)' % (modname, ex)
|
| - value = AstroidBuildingException(msg)
|
| + value = ASTNGBuildingException(msg)
|
| self._mod_file_cache[(modname, contextfile)] = value
|
| - if isinstance(value, AstroidBuildingException):
|
| + if isinstance(value, ASTNGBuildingException):
|
| raise value
|
| return value
|
|
|
| - def ast_from_module(self, module, modname=None):
|
| - """given an imported module, return the astroid object"""
|
| + def astng_from_module(self, module, modname=None):
|
| + """given an imported module, return the astng object"""
|
| modname = modname or module.__name__
|
| - if modname in self.astroid_cache:
|
| - return self.astroid_cache[modname]
|
| + if modname in self.astng_cache:
|
| + return self.astng_cache[modname]
|
| try:
|
| # some builtin modules don't have __file__ attribute
|
| filepath = module.__file__
|
| if is_python_source(filepath):
|
| - return self.ast_from_file(filepath, modname)
|
| + return self.astng_from_file(filepath, modname)
|
| except AttributeError:
|
| pass
|
| - from astroid.builder import AstroidBuilder
|
| - return AstroidBuilder(self).module_build(module, modname)
|
| + from logilab.astng.builder import ASTNGBuilder
|
| + return ASTNGBuilder(self).module_build(module, modname)
|
|
|
| - def ast_from_class(self, klass, modname=None):
|
| - """get astroid for the given class"""
|
| + def astng_from_class(self, klass, modname=None):
|
| + """get astng for the given class"""
|
| if modname is None:
|
| try:
|
| modname = klass.__module__
|
| except AttributeError:
|
| - raise AstroidBuildingException(
|
| + raise ASTNGBuildingException(
|
| 'Unable to get module for class %s' % safe_repr(klass))
|
| - modastroid = self.ast_from_module_name(modname)
|
| - return modastroid.getattr(klass.__name__)[0] # XXX
|
| + modastng = self.astng_from_module_name(modname)
|
| + return modastng.getattr(klass.__name__)[0] # XXX
|
|
|
|
|
| - def infer_ast_from_something(self, obj, context=None):
|
| - """infer astroid for the given class"""
|
| + def infer_astng_from_something(self, obj, context=None):
|
| + """infer astng for the given class"""
|
| if hasattr(obj, '__class__') and not isinstance(obj, type):
|
| klass = obj.__class__
|
| else:
|
| @@ -209,31 +210,31 @@ class AstroidManager(OptionsProviderMixIn):
|
| try:
|
| modname = klass.__module__
|
| except AttributeError:
|
| - raise AstroidBuildingException(
|
| + raise ASTNGBuildingException(
|
| 'Unable to get module for %s' % safe_repr(klass))
|
| except Exception, ex:
|
| - raise AstroidBuildingException(
|
| + raise ASTNGBuildingException(
|
| 'Unexpected error while retrieving module for %s: %s'
|
| % (safe_repr(klass), ex))
|
| try:
|
| name = klass.__name__
|
| except AttributeError:
|
| - raise AstroidBuildingException(
|
| + raise ASTNGBuildingException(
|
| 'Unable to get name for %s' % safe_repr(klass))
|
| except Exception, ex:
|
| - raise AstroidBuildingException(
|
| + raise ASTNGBuildingException(
|
| 'Unexpected error while retrieving name for %s: %s'
|
| % (safe_repr(klass), ex))
|
| # take care, on living object __module__ is regularly wrong :(
|
| - modastroid = self.ast_from_module_name(modname)
|
| + modastng = self.astng_from_module_name(modname)
|
| if klass is obj:
|
| - for infered in modastroid.igetattr(name, context):
|
| + for infered in modastng.igetattr(name, context):
|
| yield infered
|
| else:
|
| - for infered in modastroid.igetattr(name, context):
|
| + for infered in modastng.igetattr(name, context):
|
| yield infered.instanciate_class()
|
|
|
| - def project_from_files(self, files, func_wrapper=astroid_wrapper,
|
| + def project_from_files(self, files, func_wrapper=astng_wrapper,
|
| project_name=None, black_list=None):
|
| """return a Project from a list of files or modules"""
|
| # build the project representation
|
| @@ -247,77 +248,28 @@ class AstroidManager(OptionsProviderMixIn):
|
| fpath = join(something, '__init__.py')
|
| else:
|
| fpath = something
|
| - astroid = func_wrapper(self.ast_from_file, fpath)
|
| - if astroid is None:
|
| + astng = func_wrapper(self.astng_from_file, fpath)
|
| + if astng is None:
|
| continue
|
| # XXX why is first file defining the project.path ?
|
| - project.path = project.path or astroid.file
|
| - project.add_module(astroid)
|
| - base_name = astroid.name
|
| + project.path = project.path or astng.file
|
| + project.add_module(astng)
|
| + base_name = astng.name
|
| # recurse in package except if __init__ was explicitly given
|
| - if astroid.package and something.find('__init__') == -1:
|
| + if astng.package and something.find('__init__') == -1:
|
| # recurse on others packages / modules if this is a package
|
| - for fpath in get_module_files(dirname(astroid.file),
|
| + for fpath in get_module_files(dirname(astng.file),
|
| black_list):
|
| - astroid = func_wrapper(self.ast_from_file, fpath)
|
| - if astroid is None or astroid.name == base_name:
|
| + astng = func_wrapper(self.astng_from_file, fpath)
|
| + if astng is None or astng.name == base_name:
|
| continue
|
| - project.add_module(astroid)
|
| + project.add_module(astng)
|
| return project
|
|
|
| - def register_transform(self, node_class, transform, predicate=None):
|
| - """Register `transform(node)` function to be applied on the given
|
| - Astroid's `node_class` if `predicate` is None or return a true value
|
| - when called with the node as argument.
|
| -
|
| - The transform function may return a value which is then used to
|
| - substitute the original node in the tree.
|
| - """
|
| - self.transforms.setdefault(node_class, []).append((transform, predicate))
|
| -
|
| - def unregister_transform(self, node_class, transform, predicate=None):
|
| - """Unregister the given transform."""
|
| - self.transforms[node_class].remove((transform, predicate))
|
| -
|
| - def transform(self, node):
|
| - """Call matching transforms for the given node if any and return the
|
| - transformed node.
|
| - """
|
| - cls = node.__class__
|
| - if cls not in self.transforms:
|
| - # no transform registered for this class of node
|
| - return node
|
| -
|
| - transforms = self.transforms[cls]
|
| - orig_node = node # copy the reference
|
| - for transform_func, predicate in transforms:
|
| - if predicate is None or predicate(node):
|
| - ret = transform_func(node)
|
| - # if the transformation function returns something, it's
|
| - # expected to be a replacement for the node
|
| - if ret is not None:
|
| - if node is not orig_node:
|
| - # node has already be modified by some previous
|
| - # transformation, warn about it
|
| - warn('node %s substituted multiple times' % node)
|
| - node = ret
|
| - return node
|
| -
|
| - def cache_module(self, module):
|
| - """Cache a module if no module with the same name is known yet."""
|
| - self.astroid_cache.setdefault(module.name, module)
|
| -
|
| - def clear_cache(self):
|
| - 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
|
| - from astroid.raw_building import astroid_bootstrapping
|
| - astroid_bootstrapping()
|
| -
|
| + def register_transformer(self, transformer):
|
| + self.transformers.append(transformer)
|
|
|
| -class Project(object):
|
| +class Project:
|
| """a project handle a set of modules / packages"""
|
| def __init__(self, name=''):
|
| self.name = name
|
|
|