# HG changeset patch # User sylvain.thenault@logilab.fr # Date 1236600272 -3600 # Node ID b5fdad9208f8f87e016fd0e26eedcd2828474c7f # Parent 625e597731198ae94151195336df20daca20fa86 search for cubes in a list of directories diff -r 625e59773119 -r b5fdad9208f8 cwconfig.py --- a/cwconfig.py Wed Mar 04 16:53:10 2009 +0100 +++ b/cwconfig.py Mon Mar 09 13:04:32 2009 +0100 @@ -10,7 +10,7 @@ import sys import os import logging -from os.path import exists, join, expanduser, abspath, basename +from os.path import exists, join, expanduser, abspath, normpath, basename, isdir from logilab.common.decorators import cached from logilab.common.logging_ext import set_log_methods, init_log @@ -152,7 +152,7 @@ file(join(CUBES_DIR, '__init__.py'), 'w').close() elif exists(join(CW_SOFTWARE_ROOT, '.hg')): mode = 'dev' - CUBES_DIR = join(CW_SOFTWARE_ROOT, '../cubes') + CUBES_DIR = abspath(normpath(join(CW_SOFTWARE_ROOT, '../cubes'))) else: mode = 'installed' CUBES_DIR = '/usr/share/cubicweb/cubes/' @@ -225,7 +225,7 @@ """ if cls.mode in ('dev', 'test') and not os.environ.get('APYCOT_ROOT'): return join(CW_SOFTWARE_ROOT, 'web') - return join(cls.cubes_dir(), 'shared') + return self.cube_dir('shared') @classmethod def i18n_lib_dir(cls): @@ -236,26 +236,38 @@ @classmethod def available_cubes(cls): - cubes_dir = cls.cubes_dir() - return sorted(cube for cube in os.listdir(cubes_dir) - if os.path.isdir(os.path.join(cubes_dir, cube)) - and not cube in ('CVS', '.svn', 'shared', '.hg')) + cubes = set() + for directory in cls.cubes_search_path(): + for cube in os.listdir(directory): + if isdir(join(directory, cube)) and not cube in ('CVS', '.svn', 'shared', '.hg'): + cubes.add(cube) + return sorted(cubes) @classmethod - def cubes_dir(cls): - """return the application cubes directory""" - return env_path('CW_CUBES', cls.CUBES_DIR, 'cubes') + def cubes_search_path(cls): + """return the path of directories where cubes should be searched""" + path = [] + try: + for directory in os.environ['CW_CUBES_PATH'].split(os.pathsep): + directory = abspath(normpath(directory)) + if exists(directory) and not directory in path: + path.append(directory) + except KeyError: + pass + if not cls.CUBES_DIR in path: + path.append(cls.CUBES_DIR) + return path @classmethod def cube_dir(cls, cube): """return the cube directory for the given cube id, raise ConfigurationError if it doesn't exists """ - cube_dir = join(cls.cubes_dir(), cube) - if not exists(cube_dir): - raise ConfigurationError('no cube %s in %s' % ( - cube, cls.cubes_dir())) - return cube_dir + for directory in cls.cubes_search_path(): + cubedir = join(directory, cube) + if exists(cubedir): + return cubedir + raise ConfigurationError('no cube %s in %s' % (cube, cls.cubes_search_path())) @classmethod def cube_migration_scripts_dir(cls, cube): @@ -341,12 +353,13 @@ @classmethod def cls_adjust_sys_path(cls): """update python path if necessary""" + if not cls.CUBES_DIR in sys.path: + sys.path.insert(0, cls.CUBES_DIR) try: - templdir = abspath(join(cls.cubes_dir(), '..')) - if not templdir in sys.path: - sys.path.insert(0, templdir) - except ConfigurationError: - return # cube dir doesn't exists + import cubes + cubes.__path__ = cls.cubes_search_path() + except ImportError: + return # cubes dir doesn't exists @classmethod def load_cwctl_plugins(cls): @@ -358,10 +371,9 @@ if exists(join(CW_SOFTWARE_ROOT, ctlfile)): load_module_from_file(join(CW_SOFTWARE_ROOT, ctlfile)) cls.info('loaded cubicweb-ctl plugin %s', ctlfile) - templdir = cls.cubes_dir() for cube in cls.available_cubes(): - pluginfile = join(templdir, cube, 'ecplugin.py') - initfile = join(templdir, cube, '__init__.py') + pluginfile = join(cls.cube_dir(cube), 'ecplugin.py') + initfile = join(cls.cube_dir(cube), '__init__.py') if exists(pluginfile): try: __import__('cubes.%s.ecplugin' % cube) diff -r 625e59773119 -r b5fdad9208f8 cwctl.py --- a/cwctl.py Wed Mar 04 16:53:10 2009 +0100 +++ b/cwctl.py Mon Mar 09 13:04:32 2009 +0100 @@ -173,19 +173,18 @@ continue print ' ', line print + cubesdirs = ', '.join(CubicWebConfiguration.cubes_search_path()) try: - cubesdir = CubicWebConfiguration.cubes_dir() namesize = max(len(x) for x in CubicWebConfiguration.available_cubes()) except ConfigurationError, ex: print 'No cubes available:', ex except ValueError: - print 'No cubes available in %s' % cubesdir + print 'No cubes available in %s' % cubesdirs else: - print 'Available cubes (%s):' % cubesdir + print 'Available cubes (%s):' % cubesdirs for cube in CubicWebConfiguration.available_cubes(): if cube in ('CVS', '.svn', 'shared', '.hg'): continue - templdir = join(cubesdir, cube) try: tinfo = CubicWebConfiguration.cube_pkginfo(cube) tversion = tinfo.version @@ -198,7 +197,7 @@ or tinfo.__doc__) if shortdesc: print ' '+ ' \n'.join(shortdesc.splitlines()) - modes = detect_available_modes(templdir) + modes = detect_available_modes(CubicWebConfiguration.cube_dir(cube)) print ' available modes: %s' % ', '.join(modes) print try: diff -r 625e59773119 -r b5fdad9208f8 devtools/devctl.py --- a/devtools/devctl.py Wed Mar 04 16:53:10 2009 +0100 +++ b/devtools/devctl.py Mon Mar 09 13:04:32 2009 +0100 @@ -286,10 +286,10 @@ """run the command with its specific arguments""" CUBEDIR = DevCubeConfiguration.cubes_dir() if args: - cubes = [join(CUBEDIR, app) for app in args] + cubes = [DevCubeConfiguration.cube_dir(cube) for cube in args] else: - cubes = [join(CUBEDIR, app) for app in listdir(CUBEDIR) - if exists(join(CUBEDIR, app, 'i18n'))] + cubes = [DevCubeConfiguration.cube_dir(cube) for cube in DevCubeConfiguration.available_cubes()] + cubes = [cubepath for cubepath in cubes if exists(join(cubepath, 'i18n'))] update_cubes_catalogs(cubes) def update_cubes_catalogs(cubes): diff -r 625e59773119 -r b5fdad9208f8 goa/goactl.py --- a/goa/goactl.py Wed Mar 04 16:53:10 2009 +0100 +++ b/goa/goactl.py Mon Mar 09 13:04:32 2009 +0100 @@ -211,12 +211,12 @@ # link every supported components packagesdir = join(appldir, 'cubes') create_init_file(join(appldir, 'cubes'), 'cubes') - cubesdir = CubicWebConfiguration.cubes_dir() - for include in ('addressbook','basket', 'blog','classfolders', - 'classtags', 'comment', 'file', 'link', + for include in ('addressbook','basket', 'blog','folder', + 'tag', 'comment', 'file', 'link', 'mailinglist', 'person', 'task', 'zone', ): - create_symlink(join(cubesdir, include), join(packagesdir, include)) + create_symlink(CubicWebConfiguration.cube_dir(include), + join(packagesdir, include)) # generate sample config from cubicweb.goa.goaconfig import GAEConfiguration from cubicweb.common.migration import MigrationHelper diff -r 625e59773119 -r b5fdad9208f8 test/unittest_cwconfig.py --- a/test/unittest_cwconfig.py Wed Mar 04 16:53:10 2009 +0100 +++ b/test/unittest_cwconfig.py Mon Mar 09 13:04:32 2009 +0100 @@ -1,4 +1,6 @@ +import sys import os +from os.path import dirname, join, abspath from tempfile import mktemp from logilab.common.testlib import TestCase, unittest_main @@ -69,6 +71,33 @@ ['entities', 'web/views', 'sobjects', 'file/entities.py', 'file/views', 'file/hooks.py', 'email/entities.py', 'email/views', 'email/hooks.py']) - + + def test_cubes_path(self): + os.environ['CW_CUBES_PATH'] = join(dirname(__file__), 'data', 'cubes') + self.assertEquals(self.config.cubes_search_path(), + [abspath(join(dirname(__file__), 'data', 'cubes')), + self.config.CUBES_DIR]) + os.environ['CW_CUBES_PATH'] = '%s%s%s%s%s' % (join(dirname(__file__), 'data', 'cubes'), + os.pathsep, self.config.CUBES_DIR, + os.pathsep, 'unexistant') + # filter out unexistant and duplicates + self.assertEquals(self.config.cubes_search_path(), + [abspath(join(dirname(__file__), 'data', 'cubes')), + self.config.CUBES_DIR]) + self.failUnless('mycube' in self.config.available_cubes()) + # test cubes python path + self.config.adjust_sys_path() + import cubes + self.assertEquals(cubes.__path__, self.config.cubes_search_path()) + # this import should succeed once path is adjusted + from cubes import mycube + self.assertEquals(mycube.__path__, [abspath(join(dirname(__file__), 'data', 'cubes', 'mycube'))]) + # file cube should be overriden by the one found in data/cubes + sys.modules.pop('cubes.file', None) + del cubes.file + from cubes import file + self.assertEquals(file.__path__, [abspath(join(dirname(__file__), 'data', 'cubes', 'file'))]) + + if __name__ == '__main__': unittest_main()