diff options
author | Denis Laxalde <denis.laxalde@logilab.fr> | 2016-11-14 09:48:38 +0100 |
---|---|---|
committer | Denis Laxalde <denis.laxalde@logilab.fr> | 2016-11-14 09:48:38 +0100 |
commit | 02334198369c0f65a9da6d544d0f15f4ac7d4812 (patch) | |
tree | defd9357680714891e4a7e2a6a235056089e4fef | |
parent | c36a5d74e4ac35d79206b6215726757385af536c (diff) | |
download | logilab-common-02334198369c0f65a9da6d544d0f15f4ac7d4812.tar.gz |
[modutils] Copy back modpath_from_file from astroid
Astroid has copy of modutils, originally from logilab-common, which has been
modified and improved since. Copy back the `modpath_from_file` function in
logilab-common, so that it is more robust to file path "subtelities" (case,
symlinks, user, in particular).
-rw-r--r-- | logilab/common/modutils.py | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/logilab/common/modutils.py b/logilab/common/modutils.py index e70a1a9..6d13201 100644 --- a/logilab/common/modutils.py +++ b/logilab/common/modutils.py @@ -32,12 +32,14 @@ __docformat__ = "restructuredtext en" import sys import os -from os.path import splitext, join, abspath, isdir, dirname, exists, basename +from os.path import (splitext, join, abspath, isdir, dirname, exists, + basename, expanduser, normcase, realpath) from imp import find_module, load_module, C_BUILTIN, PY_COMPILED, PKG_DIRECTORY from distutils.sysconfig import get_config_var, get_python_lib, get_python_version from distutils.errors import DistutilsPlatformError -from six.moves import range +from six import PY3 +from six.moves import map, range try: import zipimport @@ -219,6 +221,19 @@ def _check_init(path, mod_path): return True +def _canonicalize_path(path): + return realpath(expanduser(path)) + + +def _path_from_filename(filename): + if PY3: + return filename + else: + if filename.endswith(".pyc"): + return filename[:-1] + return filename + + def modpath_from_file(filename, extrapath=None): """given a file path return the corresponding splitted module's name (i.e name of a module or package splitted on '.') @@ -239,26 +254,29 @@ def modpath_from_file(filename, extrapath=None): :rtype: list(str) :return: the corresponding splitted module's name """ - base = splitext(abspath(filename))[0] + filename = _path_from_filename(filename) + filename = _canonicalize_path(filename) + base = os.path.splitext(filename)[0] + if extrapath is not None: - for path_ in extrapath: + for path_ in map(_canonicalize_path, extrapath): path = abspath(path_) - if path and base[:len(path)] == path: + if path and normcase(base[:len(path)]) == normcase(path): submodpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg] if _check_init(path, submodpath[:-1]): return extrapath[path_].split('.') + submodpath - for path in sys.path: - path = abspath(path) - if path and base.startswith(path): + + for path in map(_canonicalize_path, sys.path): + if path and normcase(base).startswith(path): modpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg] if _check_init(path, modpath[:-1]): return modpath + raise ImportError('Unable to find module for %s in %s' % ( filename, ', \n'.join(sys.path))) - def file_from_modpath(modpath, path=None, context_file=None): """given a mod path (i.e. splitted module / package name), return the corresponding file, giving priority to source file over precompiled |