--- 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)
--- 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:
--- 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):
--- 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
--- 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()