| OLD | NEW | 
|    1 # copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |    1 # copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. | 
|    2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |    2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr | 
|    3 # |    3 # | 
|    4 # This file is part of astroid. |    4 # This file is part of astroid. | 
|    5 # |    5 # | 
|    6 # astroid is free software: you can redistribute it and/or modify it under |    6 # astroid is free software: you can redistribute it and/or modify it under | 
|    7 # the terms of the GNU Lesser General Public License as published by the Free |    7 # the terms of the GNU Lesser General Public License as published by the Free | 
|    8 # Software Foundation, either version 2.1 of the License, or (at your option) an
     y |    8 # Software Foundation, either version 2.1 of the License, or (at your option) an
     y | 
|    9 # later version. |    9 # later version. | 
|   10 # |   10 # | 
|   11 # astroid is distributed in the hope that it will be useful, but WITHOUT |   11 # astroid is distributed in the hope that it will be useful, but WITHOUT | 
|   12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |   12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 
|   13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more |   13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more | 
|   14 # details. |   14 # details. | 
|   15 # |   15 # | 
|   16 # You should have received a copy of the GNU Lesser General Public License along |   16 # You should have received a copy of the GNU Lesser General Public License along | 
|   17 # with astroid.  If not, see <http://www.gnu.org/licenses/>. |   17 # with astroid.  If not, see <http://www.gnu.org/licenses/>. | 
|   18 """Python modules manipulation utility functions. |   18 """Python modules manipulation utility functions. | 
|   19  |   19  | 
|   20 :type PY_SOURCE_EXTS: tuple(str) |   20 :type PY_SOURCE_EXTS: tuple(str) | 
|   21 :var PY_SOURCE_EXTS: list of possible python source file extension |   21 :var PY_SOURCE_EXTS: list of possible python source file extension | 
|   22  |   22  | 
|   23 :type STD_LIB_DIR: str |   23 :type STD_LIB_DIRS: list of str | 
|   24 :var STD_LIB_DIR: directory where standard modules are located |   24 :var STD_LIB_DIRS: directories where standard modules are located | 
|   25  |   25  | 
|   26 :type BUILTIN_MODULES: dict |   26 :type BUILTIN_MODULES: dict | 
|   27 :var BUILTIN_MODULES: dictionary with builtin module names has key |   27 :var BUILTIN_MODULES: dictionary with builtin module names has key | 
|   28 """ |   28 """ | 
|   29 from __future__ import with_statement |   29 from __future__ import with_statement | 
|   30  |   30  | 
|   31 __docformat__ = "restructuredtext en" |   31 __docformat__ = "restructuredtext en" | 
|   32  |   32  | 
 |   33 import imp | 
 |   34 import os | 
|   33 import sys |   35 import sys | 
|   34 import os |  | 
|   35 from os.path import splitext, join, abspath, isdir, dirname, exists |  | 
|   36 from imp import find_module, load_module, C_BUILTIN, PY_COMPILED, PKG_DIRECTORY |  | 
|   37 from distutils.sysconfig import get_python_lib |   36 from distutils.sysconfig import get_python_lib | 
|   38 from distutils.errors import DistutilsPlatformError |   37 from distutils.errors import DistutilsPlatformError | 
 |   38 import zipimport | 
|   39  |   39  | 
|   40 try: |   40 try: | 
|   41     import zipimport |   41     import pkg_resources | 
|   42 except ImportError: |   42 except ImportError: | 
|   43     zipimport = None |   43     pkg_resources = None | 
|   44  |  | 
|   45 ZIPFILE = object() |  | 
|   46  |   44  | 
|   47 from logilab.common import _handle_blacklist |   45 from logilab.common import _handle_blacklist | 
|   48  |   46  | 
|   49 # Notes about STD_LIB_DIR |   47 PY_ZIPMODULE = object() | 
|   50 # Consider arch-specific installation for STD_LIB_DIR definition |   48  | 
|   51 # :mod:`distutils.sysconfig` contains to much hardcoded values to rely on |  | 
|   52 # |  | 
|   53 # :see: `Problems with /usr/lib64 builds <http://bugs.python.org/issue1294959>`_ |  | 
|   54 # :see: `FHS <http://www.pathname.com/fhs/pub/fhs-2.3.html#LIBLTQUALGTALTERNATEF
     ORMATESSENTIAL>`_ |  | 
|   55 if sys.platform.startswith('win'): |   49 if sys.platform.startswith('win'): | 
|   56     PY_SOURCE_EXTS = ('py', 'pyw') |   50     PY_SOURCE_EXTS = ('py', 'pyw') | 
|   57     PY_COMPILED_EXTS = ('dll', 'pyd') |   51     PY_COMPILED_EXTS = ('dll', 'pyd') | 
|   58 else: |   52 else: | 
|   59     PY_SOURCE_EXTS = ('py',) |   53     PY_SOURCE_EXTS = ('py',) | 
|   60     PY_COMPILED_EXTS = ('so',) |   54     PY_COMPILED_EXTS = ('so',) | 
|   61  |   55  | 
 |   56 # Notes about STD_LIB_DIRS | 
 |   57 # Consider arch-specific installation for STD_LIB_DIR definition | 
 |   58 # :mod:`distutils.sysconfig` contains to much hardcoded values to rely on | 
 |   59 # | 
 |   60 # :see: `Problems with /usr/lib64 builds <http://bugs.python.org/issue1294959>`_ | 
 |   61 # :see: `FHS <http://www.pathname.com/fhs/pub/fhs-2.3.html#LIBLTQUALGTALTERNATEF
     ORMATESSENTIAL>`_ | 
|   62 try: |   62 try: | 
|   63     STD_LIB_DIR = get_python_lib(standard_lib=1) |   63     # The explicit prefix is to work around a patch in virtualenv that | 
 |   64     # replaces the 'real' sys.prefix (i.e. the location of the binary) | 
 |   65     # with the prefix from which the virtualenv was created. This throws | 
 |   66     # off the detection logic for standard library modules, thus the | 
 |   67     # workaround. | 
 |   68     STD_LIB_DIRS = [ | 
 |   69         get_python_lib(standard_lib=True, prefix=sys.prefix), | 
 |   70         get_python_lib(standard_lib=True)] | 
 |   71     if os.name == 'nt': | 
 |   72         STD_LIB_DIRS.append(os.path.join(sys.prefix, 'dlls')) | 
 |   73         try: | 
 |   74             # real_prefix is defined when running inside virtualenv. | 
 |   75             STD_LIB_DIRS.append(os.path.join(sys.real_prefix, 'dlls')) | 
 |   76         except AttributeError: | 
 |   77             pass | 
|   64 # get_python_lib(standard_lib=1) is not available on pypy, set STD_LIB_DIR to |   78 # get_python_lib(standard_lib=1) is not available on pypy, set STD_LIB_DIR to | 
|   65 # non-valid path, see https://bugs.pypy.org/issue1164 |   79 # non-valid path, see https://bugs.pypy.org/issue1164 | 
|   66 except DistutilsPlatformError: |   80 except DistutilsPlatformError: | 
|   67     STD_LIB_DIR = '//' |   81     STD_LIB_DIRS = [] | 
|   68  |   82  | 
|   69 EXT_LIB_DIR = get_python_lib() |   83 EXT_LIB_DIR = get_python_lib() | 
|   70  |   84  | 
|   71 BUILTIN_MODULES = dict(zip(sys.builtin_module_names, |   85 BUILTIN_MODULES = dict(zip(sys.builtin_module_names, | 
|   72                            [1]*len(sys.builtin_module_names))) |   86                            [1]*len(sys.builtin_module_names))) | 
|   73  |   87  | 
|   74  |   88  | 
|   75 class NoSourceFile(Exception): |   89 class NoSourceFile(Exception): | 
|   76     """exception raised when we are not able to get a python |   90     """exception raised when we are not able to get a python | 
|   77     source file for a precompiled file |   91     source file for a precompiled file | 
|   78     """ |   92     """ | 
|   79  |   93  | 
 |   94 def _normalize_path(path): | 
 |   95     return os.path.normcase(os.path.abspath(path)) | 
 |   96  | 
 |   97  | 
 |   98 _NORM_PATH_CACHE = {} | 
 |   99  | 
 |  100 def _cache_normalize_path(path): | 
 |  101     """abspath with caching""" | 
 |  102     # _module_file calls abspath on every path in sys.path every time it's | 
 |  103     # called; on a larger codebase this easily adds up to half a second just | 
 |  104     # assembling path components. This cache alleviates that. | 
 |  105     try: | 
 |  106         return _NORM_PATH_CACHE[path] | 
 |  107     except KeyError: | 
 |  108         if not path: # don't cache result for '' | 
 |  109             return _normalize_path(path) | 
 |  110         result = _NORM_PATH_CACHE[path] = _normalize_path(path) | 
 |  111         return result | 
|   80  |  112  | 
|   81 def load_module_from_name(dotted_name, path=None, use_sys=1): |  113 def load_module_from_name(dotted_name, path=None, use_sys=1): | 
|   82     """Load a Python module from its name. |  114     """Load a Python module from its name. | 
|   83  |  115  | 
|   84     :type dotted_name: str |  116     :type dotted_name: str | 
|   85     :param dotted_name: python name of a module or package |  117     :param dotted_name: python name of a module or package | 
|   86  |  118  | 
|   87     :type path: list or None |  119     :type path: list or None | 
|   88     :param path: |  120     :param path: | 
|   89       optional list of path where the module or package should be |  121       optional list of path where the module or package should be | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  135         modpath.append(part) |  167         modpath.append(part) | 
|  136         curname = '.'.join(modpath) |  168         curname = '.'.join(modpath) | 
|  137         module = None |  169         module = None | 
|  138         if len(modpath) != len(parts): |  170         if len(modpath) != len(parts): | 
|  139             # even with use_sys=False, should try to get outer packages from sys
     .modules |  171             # even with use_sys=False, should try to get outer packages from sys
     .modules | 
|  140             module = sys.modules.get(curname) |  172             module = sys.modules.get(curname) | 
|  141         elif use_sys: |  173         elif use_sys: | 
|  142             # because it may have been indirectly loaded through a parent |  174             # because it may have been indirectly loaded through a parent | 
|  143             module = sys.modules.get(curname) |  175             module = sys.modules.get(curname) | 
|  144         if module is None: |  176         if module is None: | 
|  145             mp_file, mp_filename, mp_desc = find_module(part, path) |  177             mp_file, mp_filename, mp_desc = imp.find_module(part, path) | 
|  146             module = load_module(curname, mp_file, mp_filename, mp_desc) |  178             module = imp.load_module(curname, mp_file, mp_filename, mp_desc) | 
 |  179             # mp_file still needs to be closed. | 
 |  180             if mp_file: | 
 |  181                 mp_file.close() | 
|  147         if prevmodule: |  182         if prevmodule: | 
|  148             setattr(prevmodule, part, module) |  183             setattr(prevmodule, part, module) | 
|  149         _file = getattr(module, '__file__', '') |  184         _file = getattr(module, '__file__', '') | 
|  150         if not _file and len(modpath) != len(parts): |  185         if not _file and len(modpath) != len(parts): | 
|  151             raise ImportError('no module in %s' % '.'.join(parts[len(modpath):])
     ) |  186             raise ImportError('no module in %s' % '.'.join(parts[len(modpath):])
     ) | 
|  152         path = [dirname(_file)] |  187         path = [os.path.dirname(_file)] | 
|  153         prevmodule = module |  188         prevmodule = module | 
|  154     return module |  189     return module | 
|  155  |  190  | 
|  156  |  191  | 
|  157 def load_module_from_file(filepath, path=None, use_sys=1, extrapath=None): |  192 def load_module_from_file(filepath, path=None, use_sys=1, extrapath=None): | 
|  158     """Load a Python module from it's path. |  193     """Load a Python module from it's path. | 
|  159  |  194  | 
|  160     :type filepath: str |  195     :type filepath: str | 
|  161     :param filepath: path to the python module or package |  196     :param filepath: path to the python module or package | 
|  162  |  197  | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|  176     :rtype: module |  211     :rtype: module | 
|  177     :return: the loaded module |  212     :return: the loaded module | 
|  178     """ |  213     """ | 
|  179     modpath = modpath_from_file(filepath, extrapath) |  214     modpath = modpath_from_file(filepath, extrapath) | 
|  180     return load_module_from_modpath(modpath, path, use_sys) |  215     return load_module_from_modpath(modpath, path, use_sys) | 
|  181  |  216  | 
|  182  |  217  | 
|  183 def _check_init(path, mod_path): |  218 def _check_init(path, mod_path): | 
|  184     """check there are some __init__.py all along the way""" |  219     """check there are some __init__.py all along the way""" | 
|  185     for part in mod_path: |  220     for part in mod_path: | 
|  186         path = join(path, part) |  221         path = os.path.join(path, part) | 
|  187         if not _has_init(path): |  222         if not _has_init(path): | 
|  188             return False |  223             return False | 
|  189     return True |  224     return True | 
|  190  |  225  | 
|  191  |  226  | 
|  192 def modpath_from_file(filename, extrapath=None): |  227 def modpath_from_file(filename, extrapath=None): | 
|  193     """given a file path return the corresponding splitted module's name |  228     """given a file path return the corresponding splitted module's name | 
|  194     (i.e name of a module or package splitted on '.') |  229     (i.e name of a module or package splitted on '.') | 
|  195  |  230  | 
|  196     :type filename: str |  231     :type filename: str | 
|  197     :param filename: file's path for which we want the module's name |  232     :param filename: file's path for which we want the module's name | 
|  198  |  233  | 
|  199     :type extrapath: dict |  234     :type extrapath: dict | 
|  200     :param extrapath: |  235     :param extrapath: | 
|  201       optional extra search path, with path as key and package name for the path |  236       optional extra search path, with path as key and package name for the path | 
|  202       as value. This is usually useful to handle package splitted in multiple |  237       as value. This is usually useful to handle package splitted in multiple | 
|  203       directories using __path__ trick. |  238       directories using __path__ trick. | 
|  204  |  239  | 
|  205  |  240  | 
|  206     :raise ImportError: |  241     :raise ImportError: | 
|  207       if the corresponding module's name has not been found |  242       if the corresponding module's name has not been found | 
|  208  |  243  | 
|  209     :rtype: list(str) |  244     :rtype: list(str) | 
|  210     :return: the corresponding splitted module's name |  245     :return: the corresponding splitted module's name | 
|  211     """ |  246     """ | 
|  212     base = splitext(abspath(filename))[0] |  247     base = os.path.splitext(os.path.abspath(filename))[0] | 
|  213     if extrapath is not None: |  248     if extrapath is not None: | 
|  214         for path_ in extrapath: |  249         for path_ in extrapath: | 
|  215             path = _abspath(path_) |  250             path = os.path.abspath(path_) | 
|  216             if path and base[:len(path)] == path: |  251             if path and os.path.normcase(base[:len(path)]) == os.path.normcase(p
     ath): | 
|  217                 submodpath = [pkg for pkg in base[len(path):].split(os.sep) |  252                 submodpath = [pkg for pkg in base[len(path):].split(os.sep) | 
|  218                               if pkg] |  253                               if pkg] | 
|  219                 if _check_init(path, submodpath[:-1]): |  254                 if _check_init(path, submodpath[:-1]): | 
|  220                     return extrapath[path_].split('.') + submodpath |  255                     return extrapath[path_].split('.') + submodpath | 
|  221     for path in sys.path: |  256     for path in sys.path: | 
|  222         path = _abspath(path) |  257         path = _cache_normalize_path(path) | 
|  223         if path and base.startswith(path): |  258         if path and os.path.normcase(base).startswith(path): | 
|  224             modpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg] |  259             modpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg] | 
|  225             if _check_init(path, modpath[:-1]): |  260             if _check_init(path, modpath[:-1]): | 
|  226                 return modpath |  261                 return modpath | 
|  227     raise ImportError('Unable to find module for %s in %s' % ( |  262     raise ImportError('Unable to find module for %s in %s' % ( | 
|  228         filename, ', \n'.join(sys.path))) |  263         filename, ', \n'.join(sys.path))) | 
|  229  |  264  | 
|  230  |  265  | 
 |  266 def file_from_modpath(modpath, path=None, context_file=None): | 
 |  267     return file_info_from_modpath(modpath, path, context_file)[0] | 
|  231  |  268  | 
|  232 def file_from_modpath(modpath, path=None, context_file=None): |  269 def file_info_from_modpath(modpath, path=None, context_file=None): | 
|  233     """given a mod path (i.e. splitted module / package name), return the |  270     """given a mod path (i.e. splitted module / package name), return the | 
|  234     corresponding file, giving priority to source file over precompiled |  271     corresponding file, giving priority to source file over precompiled | 
|  235     file if it exists |  272     file if it exists | 
|  236  |  273  | 
|  237     :type modpath: list or tuple |  274     :type modpath: list or tuple | 
|  238     :param modpath: |  275     :param modpath: | 
|  239       splitted module's name (i.e name of a module or package splitted |  276       splitted module's name (i.e name of a module or package splitted | 
|  240       on '.') |  277       on '.') | 
|  241       (this means explicit relative imports that start with dots have |  278       (this means explicit relative imports that start with dots have | 
|  242       empty strings in this list!) |  279       empty strings in this list!) | 
|  243  |  280  | 
|  244     :type path: list or None |  281     :type path: list or None | 
|  245     :param path: |  282     :param path: | 
|  246       optional list of path where the module or package should be |  283       optional list of path where the module or package should be | 
|  247       searched (use sys.path if nothing or None is given) |  284       searched (use sys.path if nothing or None is given) | 
|  248  |  285  | 
|  249     :type context_file: str or None |  286     :type context_file: str or None | 
|  250     :param context_file: |  287     :param context_file: | 
|  251       context file to consider, necessary if the identifier has been |  288       context file to consider, necessary if the identifier has been | 
|  252       introduced using a relative import unresolvable in the actual |  289       introduced using a relative import unresolvable in the actual | 
|  253       context (i.e. modutils) |  290       context (i.e. modutils) | 
|  254  |  291  | 
|  255     :raise ImportError: if there is no such module in the directory |  292     :raise ImportError: if there is no such module in the directory | 
|  256  |  293  | 
|  257     :rtype: str or None |  294     :rtype: (str or None, import type) | 
|  258     :return: |  295     :return: | 
|  259       the path to the module's file or None if it's an integrated |  296       the path to the module's file or None if it's an integrated | 
|  260       builtin module such as 'sys' |  297       builtin module such as 'sys' | 
|  261     """ |  298     """ | 
|  262     if context_file is not None: |  299     if context_file is not None: | 
|  263         context = dirname(context_file) |  300         context = os.path.dirname(context_file) | 
|  264     else: |  301     else: | 
|  265         context = context_file |  302         context = context_file | 
|  266     if modpath[0] == 'xml': |  303     if modpath[0] == 'xml': | 
|  267         # handle _xmlplus |  304         # handle _xmlplus | 
|  268         try: |  305         try: | 
|  269             return _file_from_modpath(['_xmlplus'] + modpath[1:], path, context) |  306             return _file_from_modpath(['_xmlplus'] + modpath[1:], path, context) | 
|  270         except ImportError: |  307         except ImportError: | 
|  271             return _file_from_modpath(modpath, path, context) |  308             return _file_from_modpath(modpath, path, context) | 
|  272     elif modpath == ['os', 'path']: |  309     elif modpath == ['os', 'path']: | 
|  273         # FIXME: currently ignoring search_path... |  310         # FIXME: currently ignoring search_path... | 
|  274         return os.path.__file__ |  311         return os.path.__file__, imp.PY_SOURCE | 
|  275     return _file_from_modpath(modpath, path, context) |  312     return _file_from_modpath(modpath, path, context) | 
|  276  |  313  | 
|  277  |  314  | 
|  278  |  | 
|  279 def get_module_part(dotted_name, context_file=None): |  315 def get_module_part(dotted_name, context_file=None): | 
|  280     """given a dotted name return the module part of the name : |  316     """given a dotted name return the module part of the name : | 
|  281  |  317  | 
|  282     >>> get_module_part('logilab.common.modutils.get_module_part') |  318     >>> get_module_part('logilab.common.modutils.get_module_part') | 
|  283     'logilab.common.modutils' |  319     'logilab.common.modutils' | 
|  284  |  320  | 
|  285     :type dotted_name: str |  321     :type dotted_name: str | 
|  286     :param dotted_name: full name of the identifier we are interested in |  322     :param dotted_name: full name of the identifier we are interested in | 
|  287  |  323  | 
|  288     :type context_file: str or None |  324     :type context_file: str or None | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
|  316         # don't use += or insert, we want a new list to be created ! |  352         # don't use += or insert, we want a new list to be created ! | 
|  317     path = None |  353     path = None | 
|  318     starti = 0 |  354     starti = 0 | 
|  319     if parts[0] == '': |  355     if parts[0] == '': | 
|  320         assert context_file is not None, \ |  356         assert context_file is not None, \ | 
|  321                 'explicit relative import, but no context_file?' |  357                 'explicit relative import, but no context_file?' | 
|  322         path = [] # prevent resolving the import non-relatively |  358         path = [] # prevent resolving the import non-relatively | 
|  323         starti = 1 |  359         starti = 1 | 
|  324     while parts[starti] == '': # for all further dots: change context |  360     while parts[starti] == '': # for all further dots: change context | 
|  325         starti += 1 |  361         starti += 1 | 
|  326         context_file = dirname(context_file) |  362         context_file = os.path.dirname(context_file) | 
|  327     for i in range(starti, len(parts)): |  363     for i in range(starti, len(parts)): | 
|  328         try: |  364         try: | 
|  329             file_from_modpath(parts[starti:i+1], path=path, |  365             file_from_modpath(parts[starti:i+1], path=path, | 
|  330                               context_file=context_file) |  366                               context_file=context_file) | 
|  331         except ImportError: |  367         except ImportError: | 
|  332             if not i >= max(1, len(parts) - 2): |  368             if not i >= max(1, len(parts) - 2): | 
|  333                 raise |  369                 raise | 
|  334             return '.'.join(parts[:i]) |  370             return '.'.join(parts[:i]) | 
|  335     return dotted_name |  371     return dotted_name | 
|  336  |  372  | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
|  355     """ |  391     """ | 
|  356     files = [] |  392     files = [] | 
|  357     for directory, dirnames, filenames in os.walk(src_directory): |  393     for directory, dirnames, filenames in os.walk(src_directory): | 
|  358         _handle_blacklist(blacklist, dirnames, filenames) |  394         _handle_blacklist(blacklist, dirnames, filenames) | 
|  359         # check for __init__.py |  395         # check for __init__.py | 
|  360         if not '__init__.py' in filenames: |  396         if not '__init__.py' in filenames: | 
|  361             dirnames[:] = () |  397             dirnames[:] = () | 
|  362             continue |  398             continue | 
|  363         for filename in filenames: |  399         for filename in filenames: | 
|  364             if _is_python_file(filename): |  400             if _is_python_file(filename): | 
|  365                 src = join(directory, filename) |  401                 src = os.path.join(directory, filename) | 
|  366                 files.append(src) |  402                 files.append(src) | 
|  367     return files |  403     return files | 
|  368  |  404  | 
|  369  |  405  | 
|  370 def get_source_file(filename, include_no_ext=False): |  406 def get_source_file(filename, include_no_ext=False): | 
|  371     """given a python module's file name return the matching source file |  407     """given a python module's file name return the matching source file | 
|  372     name (the filename will be returned identically if it's a already an |  408     name (the filename will be returned identically if it's a already an | 
|  373     absolute path to a python source file...) |  409     absolute path to a python source file...) | 
|  374  |  410  | 
|  375     :type filename: str |  411     :type filename: str | 
|  376     :param filename: python module's file name |  412     :param filename: python module's file name | 
|  377  |  413  | 
|  378  |  414  | 
|  379     :raise NoSourceFile: if no source file exists on the file system |  415     :raise NoSourceFile: if no source file exists on the file system | 
|  380  |  416  | 
|  381     :rtype: str |  417     :rtype: str | 
|  382     :return: the absolute path of the source file if it exists |  418     :return: the absolute path of the source file if it exists | 
|  383     """ |  419     """ | 
|  384     base, orig_ext = splitext(abspath(filename)) |  420     base, orig_ext = os.path.splitext(os.path.abspath(filename)) | 
|  385     for ext in PY_SOURCE_EXTS: |  421     for ext in PY_SOURCE_EXTS: | 
|  386         source_path = '%s.%s' % (base, ext) |  422         source_path = '%s.%s' % (base, ext) | 
|  387         if exists(source_path): |  423         if os.path.exists(source_path): | 
|  388             return source_path |  424             return source_path | 
|  389     if include_no_ext and not orig_ext and exists(base): |  425     if include_no_ext and not orig_ext and os.path.exists(base): | 
|  390         return base |  426         return base | 
|  391     raise NoSourceFile(filename) |  427     raise NoSourceFile(filename) | 
|  392  |  428  | 
|  393  |  429  | 
|  394 def is_python_source(filename): |  430 def is_python_source(filename): | 
|  395     """ |  431     """ | 
|  396     rtype: bool |  432     rtype: bool | 
|  397     return: True if the filename is a python source file |  433     return: True if the filename is a python source file | 
|  398     """ |  434     """ | 
|  399     return splitext(filename)[1][1:] in PY_SOURCE_EXTS |  435     return os.path.splitext(filename)[1][1:] in PY_SOURCE_EXTS | 
|  400  |  436  | 
|  401  |  437  | 
|  402 def is_standard_module(modname, std_path=(STD_LIB_DIR,)): |  438 def is_standard_module(modname, std_path=None): | 
|  403     """try to guess if a module is a standard python module (by default, |  439     """try to guess if a module is a standard python module (by default, | 
|  404     see `std_path` parameter's description) |  440     see `std_path` parameter's description) | 
|  405  |  441  | 
|  406     :type modname: str |  442     :type modname: str | 
|  407     :param modname: name of the module we are interested in |  443     :param modname: name of the module we are interested in | 
|  408  |  444  | 
|  409     :type std_path: list(str) or tuple(str) |  445     :type std_path: list(str) or tuple(str) | 
|  410     :param std_path: list of path considered has standard |  446     :param std_path: list of path considered has standard | 
|  411  |  447  | 
|  412  |  448  | 
|  413     :rtype: bool |  449     :rtype: bool | 
|  414     :return: |  450     :return: | 
|  415       true if the module: |  451       true if the module: | 
|  416       - is located on the path listed in one of the directory in `std_path` |  452       - is located on the path listed in one of the directory in `std_path` | 
|  417       - is a built-in module |  453       - is a built-in module | 
|  418     """ |  454     """ | 
|  419     modname = modname.split('.')[0] |  455     modname = modname.split('.')[0] | 
|  420     try: |  456     try: | 
|  421         filename = file_from_modpath([modname]) |  457         filename = file_from_modpath([modname]) | 
|  422     except ImportError: |  458     except ImportError: | 
|  423         # import failed, i'm probably not so wrong by supposing it's |  459         # import failed, i'm probably not so wrong by supposing it's | 
|  424         # not standard... |  460         # not standard... | 
|  425         return False |  461         return False | 
|  426     # modules which are not living in a file are considered standard |  462     # modules which are not living in a file are considered standard | 
|  427     # (sys and __builtin__ for instance) |  463     # (sys and __builtin__ for instance) | 
|  428     if filename is None: |  464     if filename is None: | 
|  429         return True |  465         return True | 
|  430     filename = abspath(filename) |  466     filename = _normalize_path(filename) | 
|  431     if filename.startswith(EXT_LIB_DIR): |  467     if filename.startswith(_cache_normalize_path(EXT_LIB_DIR)): | 
|  432         return False |  468         return False | 
 |  469     if std_path is None: | 
 |  470         std_path = STD_LIB_DIRS | 
|  433     for path in std_path: |  471     for path in std_path: | 
|  434         if filename.startswith(_abspath(path)): |  472         if filename.startswith(_cache_normalize_path(path)): | 
|  435             return True |  473             return True | 
|  436     return False |  474     return False | 
|  437  |  475  | 
|  438  |  476  | 
|  439  |  477  | 
|  440 def is_relative(modname, from_file): |  478 def is_relative(modname, from_file): | 
|  441     """return true if the given module name is relative to the given |  479     """return true if the given module name is relative to the given | 
|  442     file name |  480     file name | 
|  443  |  481  | 
|  444     :type modname: str |  482     :type modname: str | 
|  445     :param modname: name of the module we are interested in |  483     :param modname: name of the module we are interested in | 
|  446  |  484  | 
|  447     :type from_file: str |  485     :type from_file: str | 
|  448     :param from_file: |  486     :param from_file: | 
|  449       path of the module from which modname has been imported |  487       path of the module from which modname has been imported | 
|  450  |  488  | 
|  451     :rtype: bool |  489     :rtype: bool | 
|  452     :return: |  490     :return: | 
|  453       true if the module has been imported relatively to `from_file` |  491       true if the module has been imported relatively to `from_file` | 
|  454     """ |  492     """ | 
|  455     if not isdir(from_file): |  493     if not os.path.isdir(from_file): | 
|  456         from_file = dirname(from_file) |  494         from_file = os.path.dirname(from_file) | 
|  457     if from_file in sys.path: |  495     if from_file in sys.path: | 
|  458         return False |  496         return False | 
|  459     try: |  497     try: | 
|  460         find_module(modname.split('.')[0], [from_file]) |  498         stream, _, _ = imp.find_module(modname.split('.')[0], [from_file]) | 
 |  499  | 
 |  500         # Close the stream to avoid ResourceWarnings. | 
 |  501         if stream: | 
 |  502             stream.close() | 
|  461         return True |  503         return True | 
|  462     except ImportError: |  504     except ImportError: | 
|  463         return False |  505         return False | 
|  464  |  506  | 
|  465  |  507  | 
|  466 # internal only functions ##################################################### |  508 # internal only functions ##################################################### | 
|  467  |  509  | 
|  468 def _file_from_modpath(modpath, path=None, context=None): |  510 def _file_from_modpath(modpath, path=None, context=None): | 
|  469     """given a mod path (i.e. splitted module / package name), return the |  511     """given a mod path (i.e. splitted module / package name), return the | 
|  470     corresponding file |  512     corresponding file | 
|  471  |  513  | 
|  472     this function is used internally, see `file_from_modpath`'s |  514     this function is used internally, see `file_from_modpath`'s | 
|  473     documentation for more information |  515     documentation for more information | 
|  474     """ |  516     """ | 
|  475     assert len(modpath) > 0 |  517     assert len(modpath) > 0 | 
|  476     if context is not None: |  518     if context is not None: | 
|  477         try: |  519         try: | 
|  478             mtype, mp_filename = _module_file(modpath, [context]) |  520             mtype, mp_filename = _module_file(modpath, [context]) | 
|  479         except ImportError: |  521         except ImportError: | 
|  480             mtype, mp_filename = _module_file(modpath, path) |  522             mtype, mp_filename = _module_file(modpath, path) | 
|  481     else: |  523     else: | 
|  482         mtype, mp_filename = _module_file(modpath, path) |  524         mtype, mp_filename = _module_file(modpath, path) | 
|  483     if mtype == PY_COMPILED: |  525     if mtype == imp.PY_COMPILED: | 
|  484         try: |  526         try: | 
|  485             return get_source_file(mp_filename) |  527             return get_source_file(mp_filename), imp.PY_SOURCE | 
|  486         except NoSourceFile: |  528         except NoSourceFile: | 
|  487             return mp_filename |  529             return mp_filename, imp.PY_COMPILED | 
|  488     elif mtype == C_BUILTIN: |  530     elif mtype == imp.C_BUILTIN: | 
|  489         # integrated builtin module |  531         # integrated builtin module | 
|  490         return None |  532         return None, imp.C_BUILTIN | 
|  491     elif mtype == PKG_DIRECTORY: |  533     elif mtype == imp.PKG_DIRECTORY: | 
|  492         mp_filename = _has_init(mp_filename) |  534         mp_filename = _has_init(mp_filename) | 
|  493     return mp_filename |  535         mtype = imp.PY_SOURCE | 
 |  536     return mp_filename, mtype | 
|  494  |  537  | 
|  495 def _search_zip(modpath, pic): |  538 def _search_zip(modpath, pic): | 
|  496     for filepath, importer in pic.items(): |  539     for filepath, importer in pic.items(): | 
|  497         if importer is not None: |  540         if importer is not None: | 
|  498             if importer.find_module(modpath[0]): |  541             if importer.find_module(modpath[0]): | 
|  499                 if not importer.find_module(os.path.sep.join(modpath)): |  542                 if not importer.find_module(os.path.sep.join(modpath)): | 
|  500                     raise ImportError('No module named %s in %s/%s' % ( |  543                     raise ImportError('No module named %s in %s/%s' % ( | 
|  501                         '.'.join(modpath[1:]), filepath, modpath)) |  544                         '.'.join(modpath[1:]), filepath, modpath)) | 
|  502                 return ZIPFILE, abspath(filepath) + os.path.sep + os.path.sep.jo
     in(modpath), filepath |  545                 return PY_ZIPMODULE, os.path.abspath(filepath) + os.path.sep + o
     s.path.sep.join(modpath), filepath | 
|  503     raise ImportError('No module named %s' % '.'.join(modpath)) |  546     raise ImportError('No module named %s' % '.'.join(modpath)) | 
|  504  |  547  | 
|  505  |  548  | 
|  506 def _abspath(path, _abspathcache={}): #pylint: disable=dangerous-default-value |  | 
|  507     """abspath with caching""" |  | 
|  508     # _module_file calls abspath on every path in sys.path every time it's |  | 
|  509     # called; on a larger codebase this easily adds up to half a second just |  | 
|  510     # assembling path components. This cache alleviates that. |  | 
|  511     try: |  | 
|  512         return _abspathcache[path] |  | 
|  513     except KeyError: |  | 
|  514         if not path: # don't cache result for '' |  | 
|  515             return abspath(path) |  | 
|  516         _abspathcache[path] = abspath(path) |  | 
|  517         return _abspathcache[path] |  | 
|  518  |  | 
|  519 try: |  | 
|  520     import pkg_resources |  | 
|  521 except ImportError: |  | 
|  522     pkg_resources = None |  | 
|  523  |  | 
|  524 def _module_file(modpath, path=None): |  549 def _module_file(modpath, path=None): | 
|  525     """get a module type / file path |  550     """get a module type / file path | 
|  526  |  551  | 
|  527     :type modpath: list or tuple |  552     :type modpath: list or tuple | 
|  528     :param modpath: |  553     :param modpath: | 
|  529       splitted module's name (i.e name of a module or package splitted |  554       splitted module's name (i.e name of a module or package splitted | 
|  530       on '.'), with leading empty strings for explicit relative import |  555       on '.'), with leading empty strings for explicit relative import | 
|  531  |  556  | 
|  532     :type path: list or None |  557     :type path: list or None | 
|  533     :param path: |  558     :param path: | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|  545         for __path in _path: |  570         for __path in _path: | 
|  546             if not __path in pic: |  571             if not __path in pic: | 
|  547                 try: |  572                 try: | 
|  548                     pic[__path] = zipimport.zipimporter(__path) |  573                     pic[__path] = zipimport.zipimporter(__path) | 
|  549                 except zipimport.ZipImportError: |  574                 except zipimport.ZipImportError: | 
|  550                     pic[__path] = None |  575                     pic[__path] = None | 
|  551         checkeggs = True |  576         checkeggs = True | 
|  552     except AttributeError: |  577     except AttributeError: | 
|  553         checkeggs = False |  578         checkeggs = False | 
|  554     # pkg_resources support (aka setuptools namespace packages) |  579     # pkg_resources support (aka setuptools namespace packages) | 
|  555     if pkg_resources is not None and modpath[0] in pkg_resources._namespace_pack
     ages and len(modpath) > 1: |  580     if (pkg_resources is not None | 
 |  581             and modpath[0] in pkg_resources._namespace_packages | 
 |  582             and modpath[0] in sys.modules | 
 |  583             and len(modpath) > 1): | 
|  556         # setuptools has added into sys.modules a module object with proper |  584         # setuptools has added into sys.modules a module object with proper | 
|  557         # __path__, get back information from there |  585         # __path__, get back information from there | 
|  558         module = sys.modules[modpath.pop(0)] |  586         module = sys.modules[modpath.pop(0)] | 
|  559         path = module.__path__ |  587         path = module.__path__ | 
|  560     imported = [] |  588     imported = [] | 
|  561     while modpath: |  589     while modpath: | 
|  562         modname = modpath[0] |  590         modname = modpath[0] | 
|  563         # take care to changes in find_module implementation wrt builtin modules |  591         # take care to changes in find_module implementation wrt builtin modules | 
|  564         # |  592         # | 
|  565         # Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23) |  593         # Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23) | 
|  566         # >>> imp.find_module('posix') |  594         # >>> imp.find_module('posix') | 
|  567         # (None, 'posix', ('', '', 6)) |  595         # (None, 'posix', ('', '', 6)) | 
|  568         # |  596         # | 
|  569         # Python 3.3.1 (default, Apr 26 2013, 12:08:46) |  597         # Python 3.3.1 (default, Apr 26 2013, 12:08:46) | 
|  570         # >>> imp.find_module('posix') |  598         # >>> imp.find_module('posix') | 
|  571         # (None, None, ('', '', 6)) |  599         # (None, None, ('', '', 6)) | 
|  572         try: |  600         try: | 
|  573             _, mp_filename, mp_desc = find_module(modname, path) |  601             stream, mp_filename, mp_desc = imp.find_module(modname, path) | 
|  574         except ImportError: |  602         except ImportError: | 
|  575             if checkeggs: |  603             if checkeggs: | 
|  576                 return _search_zip(modpath, pic)[:2] |  604                 return _search_zip(modpath, pic)[:2] | 
|  577             raise |  605             raise | 
|  578         else: |  606         else: | 
 |  607             # Don't forget to close the stream to avoid | 
 |  608             # spurious ResourceWarnings. | 
 |  609             if stream: | 
 |  610                stream.close() | 
 |  611  | 
|  579             if checkeggs and mp_filename: |  612             if checkeggs and mp_filename: | 
|  580                 fullabspath = [_abspath(x) for x in _path] |  613                 fullabspath = [_cache_normalize_path(x) for x in _path] | 
|  581                 try: |  614                 try: | 
|  582                     pathindex = fullabspath.index(dirname(abspath(mp_filename))) |  615                     pathindex = fullabspath.index(os.path.dirname(_normalize_pat
     h(mp_filename))) | 
|  583                     emtype, emp_filename, zippath = _search_zip(modpath, pic) |  616                     emtype, emp_filename, zippath = _search_zip(modpath, pic) | 
|  584                     if pathindex > _path.index(zippath): |  617                     if pathindex > _path.index(zippath): | 
|  585                         # an egg takes priority |  618                         # an egg takes priority | 
|  586                         return emtype, emp_filename |  619                         return emtype, emp_filename | 
|  587                 except ValueError: |  620                 except ValueError: | 
|  588                     # XXX not in _path |  621                     # XXX not in _path | 
|  589                     pass |  622                     pass | 
|  590                 except ImportError: |  623                 except ImportError: | 
|  591                     pass |  624                     pass | 
|  592                 checkeggs = False |  625                 checkeggs = False | 
|  593         imported.append(modpath.pop(0)) |  626         imported.append(modpath.pop(0)) | 
|  594         mtype = mp_desc[2] |  627         mtype = mp_desc[2] | 
|  595         if modpath: |  628         if modpath: | 
|  596             if mtype != PKG_DIRECTORY: |  629             if mtype != imp.PKG_DIRECTORY: | 
|  597                 raise ImportError('No module %s in %s' % ('.'.join(modpath), |  630                 raise ImportError('No module %s in %s' % ('.'.join(modpath), | 
|  598                                                           '.'.join(imported))) |  631                                                           '.'.join(imported))) | 
|  599             # XXX guess if package is using pkgutil.extend_path by looking for |  632             # XXX guess if package is using pkgutil.extend_path by looking for | 
|  600             # those keywords in the first four Kbytes |  633             # those keywords in the first four Kbytes | 
|  601             try: |  634             try: | 
|  602                 with open(join(mp_filename, '__init__.py')) as stream: |  635                 with open(os.path.join(mp_filename, '__init__.py'), 'rb') as str
     eam: | 
|  603                     data = stream.read(4096) |  636                     data = stream.read(4096) | 
|  604             except IOError: |  637             except IOError: | 
|  605                 path = [mp_filename] |  638                 path = [mp_filename] | 
|  606             else: |  639             else: | 
|  607                 if 'pkgutil' in data and 'extend_path' in data: |  640                 if b'pkgutil' in data and b'extend_path' in data: | 
|  608                     # extend_path is called, search sys.path for module/packages |  641                     # extend_path is called, search sys.path for module/packages | 
|  609                     # of this name see pkgutil.extend_path documentation |  642                     # of this name see pkgutil.extend_path documentation | 
|  610                     path = [join(p, *imported) for p in sys.path |  643                     path = [os.path.join(p, *imported) for p in sys.path | 
|  611                             if isdir(join(p, *imported))] |  644                             if os.path.isdir(os.path.join(p, *imported))] | 
|  612                 else: |  645                 else: | 
|  613                     path = [mp_filename] |  646                     path = [mp_filename] | 
|  614     return mtype, mp_filename |  647     return mtype, mp_filename | 
|  615  |  648  | 
|  616 def _is_python_file(filename): |  649 def _is_python_file(filename): | 
|  617     """return true if the given filename should be considered as a python file |  650     """return true if the given filename should be considered as a python file | 
|  618  |  651  | 
|  619     .pyc and .pyo are ignored |  652     .pyc and .pyo are ignored | 
|  620     """ |  653     """ | 
|  621     for ext in ('.py', '.so', '.pyd', '.pyw'): |  654     for ext in ('.py', '.so', '.pyd', '.pyw'): | 
|  622         if filename.endswith(ext): |  655         if filename.endswith(ext): | 
|  623             return True |  656             return True | 
|  624     return False |  657     return False | 
|  625  |  658  | 
|  626  |  659  | 
|  627 def _has_init(directory): |  660 def _has_init(directory): | 
|  628     """if the given directory has a valid __init__ file, return its path, |  661     """if the given directory has a valid __init__ file, return its path, | 
|  629     else return None |  662     else return None | 
|  630     """ |  663     """ | 
|  631     mod_or_pack = join(directory, '__init__') |  664     mod_or_pack = os.path.join(directory, '__init__') | 
|  632     for ext in PY_SOURCE_EXTS + ('pyc', 'pyo'): |  665     for ext in PY_SOURCE_EXTS + ('pyc', 'pyo'): | 
|  633         if exists(mod_or_pack + '.' + ext): |  666         if os.path.exists(mod_or_pack + '.' + ext): | 
|  634             return mod_or_pack + '.' + ext |  667             return mod_or_pack + '.' + ext | 
|  635     return None |  668     return None | 
| OLD | NEW |