diff options
author | Torsten Marek <shlomme@gmail.com> | 2014-11-09 12:53:50 +0100 |
---|---|---|
committer | Torsten Marek <shlomme@gmail.com> | 2014-11-09 12:53:50 +0100 |
commit | 70b7afc4e70de165b4770bd9abda6a9b5440fdef (patch) | |
tree | a6a3d7b34143ff9bbd33314267e95841e3bef2e6 /astroid/modutils.py | |
parent | 494664168fe9545f0d6b8a8cb1a7d3141383c842 (diff) | |
download | astroid-git-70b7afc4e70de165b4770bd9abda6a9b5440fdef.tar.gz |
Never load C extensions that are not from the standard library and also never load any compiled Python files.
Fixes pylint issue #347.
Diffstat (limited to 'astroid/modutils.py')
-rw-r--r-- | astroid/modutils.py | 79 |
1 files changed, 43 insertions, 36 deletions
diff --git a/astroid/modutils.py b/astroid/modutils.py index efc999b4..896f79d1 100644 --- a/astroid/modutils.py +++ b/astroid/modutils.py @@ -20,8 +20,8 @@ :type PY_SOURCE_EXTS: tuple(str) :var PY_SOURCE_EXTS: list of possible python source file extension -:type STD_LIB_DIR: str -:var STD_LIB_DIR: directory where standard modules are located +:type STD_LIB_DIRS: list 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 @@ -30,28 +30,17 @@ from __future__ import with_statement __docformat__ = "restructuredtext en" -import sys +import imp import os +import sys from os.path import splitext, join, abspath, isdir, dirname, exists -from imp import find_module, load_module, C_BUILTIN, PY_COMPILED, PKG_DIRECTORY from distutils.sysconfig import get_python_lib from distutils.errors import DistutilsPlatformError +import zipimport -try: - import zipimport -except ImportError: - zipimport = None - -ZIPFILE = object() - +PY_ZIPMODULE = object() from logilab.common import _handle_blacklist -# Notes about STD_LIB_DIR -# Consider arch-specific installation for STD_LIB_DIR definition -# :mod:`distutils.sysconfig` contains to much hardcoded values to rely on -# -# :see: `Problems with /usr/lib64 builds <http://bugs.python.org/issue1294959>`_ -# :see: `FHS <http://www.pathname.com/fhs/pub/fhs-2.3.html#LIBLTQUALGTALTERNATEFORMATESSENTIAL>`_ if sys.platform.startswith('win'): PY_SOURCE_EXTS = ('py', 'pyw') PY_COMPILED_EXTS = ('dll', 'pyd') @@ -59,12 +48,25 @@ else: PY_SOURCE_EXTS = ('py',) PY_COMPILED_EXTS = ('so',) +# Notes about STD_LIB_DIRS +# Consider arch-specific installation for STD_LIB_DIR definition +# :mod:`distutils.sysconfig` contains to much hardcoded values to rely on +# +# :see: `Problems with /usr/lib64 builds <http://bugs.python.org/issue1294959>`_ +# :see: `FHS <http://www.pathname.com/fhs/pub/fhs-2.3.html#LIBLTQUALGTALTERNATEFORMATESSENTIAL>`_ try: - STD_LIB_DIR = get_python_lib(standard_lib=1) + # The explicit 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 = [ + get_python_lib(standard_lib=True, prefix=sys.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_DIR = '//' + STD_LIB_DIRS = [] EXT_LIB_DIR = get_python_lib() @@ -142,8 +144,8 @@ def load_module_from_modpath(parts, path=None, use_sys=1): # 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 = find_module(part, path) - module = load_module(curname, mp_file, mp_filename, mp_desc) + mp_file, mp_filename, mp_desc = imp.find_module(part, path) + module = imp.load_module(curname, mp_file, mp_filename, mp_desc) if prevmodule: setattr(prevmodule, part, module) _file = getattr(module, '__file__', '') @@ -228,8 +230,10 @@ def modpath_from_file(filename, extrapath=None): 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 @@ -254,7 +258,7 @@ def file_from_modpath(modpath, path=None, context_file=None): :raise ImportError: if there is no such module in the directory - :rtype: str or None + :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' @@ -271,7 +275,7 @@ def file_from_modpath(modpath, path=None, context_file=None): return _file_from_modpath(modpath, path, context) elif modpath == ['os', 'path']: # FIXME: currently ignoring search_path... - return os.path.__file__ + return os.path.__file__, imp.PY_SOURCE return _file_from_modpath(modpath, path, context) @@ -399,7 +403,7 @@ def is_python_source(filename): return splitext(filename)[1][1:] in PY_SOURCE_EXTS -def is_standard_module(modname, std_path=(STD_LIB_DIR,)): +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) @@ -430,6 +434,8 @@ def is_standard_module(modname, std_path=(STD_LIB_DIR,)): filename = abspath(filename) if filename.startswith(EXT_LIB_DIR): return False + if std_path is None: + std_path = STD_LIB_DIRS for path in std_path: if filename.startswith(_abspath(path)): return True @@ -457,7 +463,7 @@ def is_relative(modname, from_file): if from_file in sys.path: return False try: - find_module(modname.split('.')[0], [from_file]) + imp.find_module(modname.split('.')[0], [from_file]) return True except ImportError: return False @@ -480,17 +486,18 @@ def _file_from_modpath(modpath, path=None, context=None): mtype, mp_filename = _module_file(modpath, path) else: mtype, mp_filename = _module_file(modpath, path) - if mtype == PY_COMPILED: + if mtype == imp.PY_COMPILED: try: - return get_source_file(mp_filename) + return get_source_file(mp_filename), imp.PY_SOURCE except NoSourceFile: - return mp_filename - elif mtype == C_BUILTIN: + return mp_filename, imp.PY_COMPILED + elif mtype == imp.C_BUILTIN: # integrated builtin module - return None - elif mtype == PKG_DIRECTORY: + return None, imp.C_BUILTIN + elif mtype == imp.PKG_DIRECTORY: mp_filename = _has_init(mp_filename) - return mp_filename + mtype = imp.PY_SOURCE + return mp_filename, mtype def _search_zip(modpath, pic): for filepath, importer in pic.items(): @@ -499,7 +506,7 @@ def _search_zip(modpath, pic): 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 ZIPFILE, abspath(filepath) + os.path.sep + os.path.sep.join(modpath), filepath + return PY_ZIPMODULE, abspath(filepath) + os.path.sep + os.path.sep.join(modpath), filepath raise ImportError('No module named %s' % '.'.join(modpath)) @@ -573,7 +580,7 @@ def _module_file(modpath, path=None): # >>> imp.find_module('posix') # (None, None, ('', '', 6)) try: - _, mp_filename, mp_desc = find_module(modname, path) + _, mp_filename, mp_desc = imp.find_module(modname, path) except ImportError: if checkeggs: return _search_zip(modpath, pic)[:2] @@ -596,7 +603,7 @@ def _module_file(modpath, path=None): imported.append(modpath.pop(0)) mtype = mp_desc[2] if modpath: - if mtype != PKG_DIRECTORY: + 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 |