summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSylvain Th?nault <sylvain.thenault@logilab.fr>2009-06-03 16:48:11 +0200
committerSylvain Th?nault <sylvain.thenault@logilab.fr>2009-06-03 16:48:11 +0200
commitb7e234f9993a61cf496a9955ddc4969a455f1982 (patch)
tree1bc65e8c5e0ef5a17bfba7847e210e8fdca04a59
parentdb8f43a27308232acbc1ecb2becd0c9c04975822 (diff)
downloadlogilab-common-b7e234f9993a61cf496a9955ddc4969a455f1982.tar.gz
new extrapath argument to modpath_from_file (see function's docstring for explanation)
-rw-r--r--ChangeLog2
-rw-r--r--modutils.py42
-rw-r--r--test/unittest_modutils.py71
3 files changed, 69 insertions, 46 deletions
diff --git a/ChangeLog b/ChangeLog
index ed95ae0..2a2d498 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,8 @@ ChangeLog for logilab.common
============================
--
+ * modutils: new extrapath argument to modpath_from_file (see function's
+ docstring for explanation)
* adbh: new alter_column_support flag, sql_set_null_allowed and
sql_change_col_type methods
diff --git a/modutils.py b/modutils.py
index 9db0b99..5755a4f 100644
--- a/modutils.py
+++ b/modutils.py
@@ -169,13 +169,28 @@ def load_module_from_file(filepath, path=None, use_sys=1):
return load_module_from_modpath(modpath_from_file(filepath), path, use_sys)
-def modpath_from_file(filename):
+def _check_init(path, mod_path):
+ """check there are some __init__.py all along the way"""
+ for part in mod_path:
+ path = join(path, part)
+ if not _has_init(path):
+ return False
+ return True
+
+
+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 '.')
:type filename: str
:param filename: file's path for which we want the module's name
+ :type extrapath: dict
+ :param extrapath:
+ optional extra search path, with path as key and package name for the path
+ as value. This is usually useful to handle package splited in multiple
+ directories using __path__ trick.
+
:raise ImportError:
if the corresponding module's name has not been found
@@ -184,24 +199,25 @@ def modpath_from_file(filename):
:return: the corresponding splitted module's name
"""
base = splitext(abspath(filename))[0]
+ if extrapath is not None:
+ for path_ in extrapath:
+ path = abspath(path_)
+ if path and base[:len(path)] == 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[:len(path)] == path:
if filename.find('site-packages') != -1 and \
path.find('site-packages') == -1:
continue
- mod_path = [module for module in base[len(path):].split(os.sep)
- if module]
- for part in mod_path[:-1]:
- path = join(path, part)
- if not _has_init(path):
- break
- else:
- break
- else:
- raise ImportError('Unable to find module for %s in %s' % (
- filename, ', \n'.join(sys.path)))
- return mod_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)))
diff --git a/test/unittest_modutils.py b/test/unittest_modutils.py
index 248bd86..acf0e3e 100644
--- a/test/unittest_modutils.py
+++ b/test/unittest_modutils.py
@@ -24,7 +24,7 @@ from logilab.common.testlib import TestCase as TLTestCase, unittest_main
from logilab.common import modutils
from logilab.common.compat import set
-from os import path
+from os import path, getcwd
from logilab import common
from logilab.common import tree
@@ -49,31 +49,31 @@ class _module_file_tc(TestCase):
mtype, mfile = _module_file('mypypa', [path.join(DATADIR, 'MyPyPa-0.1.0-py2.5.zip')])
self.assertEquals(mtype, modutils.ZIPFILE)
self.assertEquals(mfile, '')
-
+
def test_find_egg_module(self):
mtype, mfile = _module_file('mypypa', [path.join(DATADIR, 'MyPyPa-0.1.0-py2.5.egg')])
self.assertEquals(mtype, modutils.ZIPFILE)
self.assertEquals(mfile, '')
-
+
class load_module_from_name_tc(TestCase):
""" load a python module from it's name """
-
+
def test_knownValues_load_module_from_name_1(self):
self.assertEqual(modutils.load_module_from_name('sys'), sys)
def test_knownValues_load_module_from_name_2(self):
self.assertEqual(modutils.load_module_from_name('os.path'), path)
-
+
def test_raise_load_module_from_name_1(self):
- self.assertRaises(ImportError,
- modutils.load_module_from_name, 'os.path', use_sys=0)
+ self.assertRaises(ImportError,
+ modutils.load_module_from_name, 'os.path', use_sys=0)
class get_module_part_tc(TestCase):
"""given a dotted name return the module part of the name"""
-
+
def test_knownValues_get_module_part_1(self):
self.assertEqual(modutils.get_module_part('logilab.common.modutils'),
'logilab.common.modutils')
@@ -81,27 +81,32 @@ class get_module_part_tc(TestCase):
def test_knownValues_get_module_part_2(self):
self.assertEqual(modutils.get_module_part('logilab.common.modutils.get_module_part'),
'logilab.common.modutils')
-
+
def test_knownValues_get_module_part_3(self):
self.assertEqual(modutils.get_module_part('db.get_connexion', modutils.__file__),
'db')
-
+
def test_knownValues_get_compiled_module_part(self):
self.assertEqual(modutils.get_module_part('math.log10'), 'math')
self.assertEqual(modutils.get_module_part('math.log10', __file__), 'math')
-
+
def test_knownValues_get_builtin_module_part(self):
self.assertEqual(modutils.get_module_part('sys.path'), 'sys')
self.assertEqual(modutils.get_module_part('sys.path', '__file__'), 'sys')
-
+
class modpath_from_file_tc(TestCase):
""" given an absolute file path return the python module's path as a list """
-
+
def test_knownValues_modpath_from_file_1(self):
self.assertEqual(modutils.modpath_from_file(modutils.__file__),
['logilab', 'common', 'modutils'])
-
+
+ def test_knownValues_modpath_from_file_2(self):
+ self.assertEqual(modutils.modpath_from_file('unittest_modutils.py',
+ {getcwd(): 'arbitrary.pkg'}),
+ ['arbitrary', 'pkg', 'unittest_modutils'])
+
def test_raise_modpath_from_file_Exception(self):
self.assertRaises(Exception, modutils.modpath_from_file, '/turlututu')
@@ -110,16 +115,16 @@ class file_from_modpath_tc(TestCase):
"""given a mod path (i.e. splited module / package name), return the
corresponding file, giving priority to source file over precompiled file
if it exists"""
-
+
def test_knownValues_file_from_modpath_1(self):
self.assertEqual(path.realpath(modutils.file_from_modpath(['logilab', 'common', 'modutils'])),
path.realpath(modutils.__file__.replace('.pyc', '.py')))
-
+
def test_knownValues_file_from_modpath_2(self):
from os import path
self.assertEqual(path.realpath(modutils.file_from_modpath(['os', 'path']).replace('.pyc', '.py')),
path.realpath(path.__file__.replace('.pyc', '.py')))
-
+
def test_knownValues_file_from_modpath_3(self):
try:
# don't fail if pyxml isn't installed
@@ -129,36 +134,36 @@ class file_from_modpath_tc(TestCase):
else:
self.assertEqual(path.realpath(modutils.file_from_modpath(['xml', 'dom', 'ext']).replace('.pyc', '.py')),
path.realpath(ext.__file__.replace('.pyc', '.py')))
-
+
def test_knownValues_file_from_modpath_4(self):
self.assertEqual(modutils.file_from_modpath(['sys']),
None)
-
+
def test_raise_file_from_modpath_Exception(self):
self.assertRaises(ImportError, modutils.file_from_modpath, ['turlututu'])
class get_source_file_tc(TestCase):
-
+
def test(self):
from os import path
self.assertEqual(modutils.get_source_file(path.__file__),
path.__file__.replace('.pyc', '.py'))
-
+
def test_raise(self):
self.assertRaises(modutils.NoSourceFile, modutils.get_source_file,'whatever')
-
+
class is_standard_module_tc(TestCase):
"""
return true if the module may be considered as a module from the standard
library
"""
-
+
def test_knownValues_is_standard_module_0(self):
self.assertEqual(modutils.is_standard_module('__builtin__'), True)
-
+
def test_knownValues_is_standard_module_1(self):
self.assertEqual(modutils.is_standard_module('sys'), True)
-
+
def test_knownValues_is_standard_module_2(self):
self.assertEqual(modutils.is_standard_module('logilab'), False)
@@ -172,22 +177,22 @@ class is_standard_module_tc(TestCase):
self.assertEqual(modutils.is_standard_module('data.module', (DATADIR,)), True)
self.assertEqual(modutils.is_standard_module('data.module', (path.abspath(DATADIR),)), True)
-
+
class is_relative_tc(TestCase):
-
+
def test_knownValues_is_relative_1(self):
self.assertEqual(modutils.is_relative('modutils', common.__path__[0]), True)
def test_knownValues_is_relative_2(self):
self.assertEqual(modutils.is_relative('modutils', tree.__file__), True)
-
+
def test_knownValues_is_relative_3(self):
self.assertEqual(modutils.is_relative('logilab.common.modutils',
common.__path__[0]), False)
-
+
class get_modules_tc(TestCase):
-
+
def test_knownValues_get_modules_1(self): # XXXFIXME: TOWRITE
"""given a directory return a list of all available python modules, even
in subdirectories
@@ -202,7 +207,7 @@ class get_modules_tc(TestCase):
class get_modules_files_tc(TestCase):
-
+
def test_knownValues_get_module_files_1(self): # XXXFIXME: TOWRITE
"""given a directory return a list of all available python module's files, even
in subdirectories
@@ -222,11 +227,11 @@ class get_modules_files_tc(TestCase):
self.assert_( hasattr(logilab, 'common') )
self.assert_( hasattr(logilab.common, 'fileutils') )
self.assert_( m is logilab.common.fileutils )
-
+
from logilab.common.testlib import DocTest
class ModuleDocTest(DocTest):
"""test doc test in this module"""
- from logilab.common import modutils as module
+ from logilab.common import modutils as module
del DocTest # necessary if we don't want it to be executed (we don't...)