62 ('encoding', |
62 ('encoding', |
63 {'type' : 'string', |
63 {'type' : 'string', |
64 'default': 'UTF-8', |
64 'default': 'UTF-8', |
65 'help': _('user interface encoding'), |
65 'help': _('user interface encoding'), |
66 'group': 'ui', 'sitewide': True, |
66 'group': 'ui', 'sitewide': True, |
67 }), |
67 }), |
68 ('language', |
68 ('language', |
69 {'type' : 'string', |
69 {'type' : 'string', |
70 'default': 'en', |
70 'default': 'en', |
71 'vocabulary': Method('available_languages'), |
71 'vocabulary': Method('available_languages'), |
72 'help': _('language of the user interface'), |
72 'help': _('language of the user interface'), |
73 'group': 'ui', |
73 'group': 'ui', |
74 }), |
74 }), |
75 ('date-format', |
75 ('date-format', |
76 {'type' : 'string', |
76 {'type' : 'string', |
77 'default': '%Y/%m/%d', |
77 'default': '%Y/%m/%d', |
78 'help': _('how to format date in the ui ("man strftime" for format description)'), |
78 'help': _('how to format date in the ui ("man strftime" for format description)'), |
79 'group': 'ui', |
79 'group': 'ui', |
80 }), |
80 }), |
81 ('datetime-format', |
81 ('datetime-format', |
82 {'type' : 'string', |
82 {'type' : 'string', |
83 'default': '%Y/%m/%d %H:%M', |
83 'default': '%Y/%m/%d %H:%M', |
84 'help': _('how to format date and time in the ui ("man strftime" for format description)'), |
84 'help': _('how to format date and time in the ui ("man strftime" for format description)'), |
85 'group': 'ui', |
85 'group': 'ui', |
86 }), |
86 }), |
87 ('time-format', |
87 ('time-format', |
88 {'type' : 'string', |
88 {'type' : 'string', |
89 'default': '%H:%M', |
89 'default': '%H:%M', |
90 'help': _('how to format time in the ui ("man strftime" for format description)'), |
90 'help': _('how to format time in the ui ("man strftime" for format description)'), |
91 'group': 'ui', |
91 'group': 'ui', |
92 }), |
92 }), |
93 ('float-format', |
93 ('float-format', |
94 {'type' : 'string', |
94 {'type' : 'string', |
95 'default': '%.3f', |
95 'default': '%.3f', |
96 'help': _('how to format float numbers in the ui'), |
96 'help': _('how to format float numbers in the ui'), |
97 'group': 'ui', |
97 'group': 'ui', |
98 }), |
98 }), |
99 ('default-text-format', |
99 ('default-text-format', |
100 {'type' : 'choice', |
100 {'type' : 'choice', |
101 'choices': ('text/plain', 'text/rest', 'text/html'), |
101 'choices': ('text/plain', 'text/rest', 'text/html'), |
102 'default': 'text/html', # use fckeditor in the web ui |
102 'default': 'text/html', # use fckeditor in the web ui |
103 'help': _('default text format for rich text fields.'), |
103 'help': _('default text format for rich text fields.'), |
104 'group': 'ui', |
104 'group': 'ui', |
105 }), |
105 }), |
106 ('short-line-size', |
106 ('short-line-size', |
107 {'type' : 'int', |
107 {'type' : 'int', |
108 'default': 40, |
108 'default': 40, |
109 'help': _('maximum number of characters in short description'), |
109 'help': _('maximum number of characters in short description'), |
112 ) |
112 ) |
113 |
113 |
114 def register_persistent_options(options): |
114 def register_persistent_options(options): |
115 global PERSISTENT_OPTIONS |
115 global PERSISTENT_OPTIONS |
116 PERSISTENT_OPTIONS = merge_options(PERSISTENT_OPTIONS + options) |
116 PERSISTENT_OPTIONS = merge_options(PERSISTENT_OPTIONS + options) |
117 |
117 |
118 CFGTYPE2ETYPE_MAP = { |
118 CFGTYPE2ETYPE_MAP = { |
119 'string': 'String', |
119 'string': 'String', |
120 'choice': 'String', |
120 'choice': 'String', |
121 'yn': 'Boolean', |
121 'yn': 'Boolean', |
122 'int': 'Int', |
122 'int': 'Int', |
123 'float' : 'Float', |
123 'float' : 'Float', |
124 } |
124 } |
125 |
125 |
126 class CubicWebNoAppConfiguration(ConfigurationMixIn): |
126 class CubicWebNoAppConfiguration(ConfigurationMixIn): |
127 """base class for cubicweb configuration without a specific instance directory |
127 """base class for cubicweb configuration without a specific instance directory |
128 """ |
128 """ |
129 __metaclass__ = metaconfiguration |
129 __metaclass__ = metaconfiguration |
130 # to set in concrete configuration |
130 # to set in concrete configuration |
196 'help': 'comma separated list of identifiers of application objects (<registry>.<oid>) to disable', |
196 'help': 'comma separated list of identifiers of application objects (<registry>.<oid>) to disable', |
197 'group': 'appobjects', 'inputlevel': 2, |
197 'group': 'appobjects', 'inputlevel': 2, |
198 }), |
198 }), |
199 ) |
199 ) |
200 # static and class methods used to get application independant resources ## |
200 # static and class methods used to get application independant resources ## |
201 |
201 |
202 @staticmethod |
202 @staticmethod |
203 def cubicweb_version(): |
203 def cubicweb_version(): |
204 """return installed cubicweb version""" |
204 """return installed cubicweb version""" |
205 from logilab.common.changelog import Version |
205 from logilab.common.changelog import Version |
206 from cubicweb import __pkginfo__ |
206 from cubicweb import __pkginfo__ |
207 version = __pkginfo__.numversion |
207 version = __pkginfo__.numversion |
208 assert len(version) == 3, version |
208 assert len(version) == 3, version |
209 return Version(version) |
209 return Version(version) |
210 |
210 |
211 @staticmethod |
211 @staticmethod |
212 def persistent_options_configuration(): |
212 def persistent_options_configuration(): |
213 return Configuration(options=PERSISTENT_OPTIONS) |
213 return Configuration(options=PERSISTENT_OPTIONS) |
214 |
214 |
215 @classmethod |
215 @classmethod |
218 library views and data may be found) |
218 library views and data may be found) |
219 """ |
219 """ |
220 if cls.mode in ('dev', 'test') and not os.environ.get('APYCOT_ROOT'): |
220 if cls.mode in ('dev', 'test') and not os.environ.get('APYCOT_ROOT'): |
221 return join(CW_SOFTWARE_ROOT, 'web') |
221 return join(CW_SOFTWARE_ROOT, 'web') |
222 return cls.cube_dir('shared') |
222 return cls.cube_dir('shared') |
223 |
223 |
224 @classmethod |
224 @classmethod |
225 def i18n_lib_dir(cls): |
225 def i18n_lib_dir(cls): |
226 """return application's i18n directory""" |
226 """return application's i18n directory""" |
227 if cls.mode in ('dev', 'test') and not os.environ.get('APYCOT_ROOT'): |
227 if cls.mode in ('dev', 'test') and not os.environ.get('APYCOT_ROOT'): |
228 return join(CW_SOFTWARE_ROOT, 'i18n') |
228 return join(CW_SOFTWARE_ROOT, 'i18n') |
234 for directory in cls.cubes_search_path(): |
234 for directory in cls.cubes_search_path(): |
235 for cube in os.listdir(directory): |
235 for cube in os.listdir(directory): |
236 if isdir(join(directory, cube)) and not cube in ('CVS', '.svn', 'shared', '.hg'): |
236 if isdir(join(directory, cube)) and not cube in ('CVS', '.svn', 'shared', '.hg'): |
237 cubes.add(cube) |
237 cubes.add(cube) |
238 return sorted(cubes) |
238 return sorted(cubes) |
239 |
239 |
240 @classmethod |
240 @classmethod |
241 def cubes_search_path(cls): |
241 def cubes_search_path(cls): |
242 """return the path of directories where cubes should be searched""" |
242 """return the path of directories where cubes should be searched""" |
243 path = [] |
243 path = [] |
244 try: |
244 try: |
249 except KeyError: |
249 except KeyError: |
250 pass |
250 pass |
251 if not cls.CUBES_DIR in path: |
251 if not cls.CUBES_DIR in path: |
252 path.append(cls.CUBES_DIR) |
252 path.append(cls.CUBES_DIR) |
253 return path |
253 return path |
254 |
254 |
255 @classmethod |
255 @classmethod |
256 def cube_dir(cls, cube): |
256 def cube_dir(cls, cube): |
257 """return the cube directory for the given cube id, |
257 """return the cube directory for the given cube id, |
258 raise ConfigurationError if it doesn't exists |
258 raise ConfigurationError if it doesn't exists |
259 """ |
259 """ |
265 |
265 |
266 @classmethod |
266 @classmethod |
267 def cube_migration_scripts_dir(cls, cube): |
267 def cube_migration_scripts_dir(cls, cube): |
268 """cube migration scripts directory""" |
268 """cube migration scripts directory""" |
269 return join(cls.cube_dir(cube), 'migration') |
269 return join(cls.cube_dir(cube), 'migration') |
270 |
270 |
271 @classmethod |
271 @classmethod |
272 def cube_pkginfo(cls, cube): |
272 def cube_pkginfo(cls, cube): |
273 """return the information module for the given cube""" |
273 """return the information module for the given cube""" |
274 cube = CW_MIGRATION_MAP.get(cube, cube) |
274 cube = CW_MIGRATION_MAP.get(cube, cube) |
275 try: |
275 try: |
278 raise ConfigurationError('unable to find packaging information for ' |
278 raise ConfigurationError('unable to find packaging information for ' |
279 'cube %s (%s: %s)' % (cube, ex.__class__.__name__, ex)) |
279 'cube %s (%s: %s)' % (cube, ex.__class__.__name__, ex)) |
280 |
280 |
281 @classmethod |
281 @classmethod |
282 def cube_version(cls, cube): |
282 def cube_version(cls, cube): |
283 """return the version of the cube located in the given directory |
283 """return the version of the cube located in the given directory |
284 """ |
284 """ |
285 from logilab.common.changelog import Version |
285 from logilab.common.changelog import Version |
286 version = cls.cube_pkginfo(cube).numversion |
286 version = cls.cube_pkginfo(cube).numversion |
287 assert len(version) == 3, version |
287 assert len(version) == 3, version |
288 return Version(version) |
288 return Version(version) |
341 try: |
341 try: |
342 deps.remove(cube) |
342 deps.remove(cube) |
343 except KeyError: |
343 except KeyError: |
344 continue |
344 continue |
345 return tuple(reversed(cubes)) |
345 return tuple(reversed(cubes)) |
346 |
346 |
347 @classmethod |
347 @classmethod |
348 def cls_adjust_sys_path(cls): |
348 def cls_adjust_sys_path(cls): |
349 """update python path if necessary""" |
349 """update python path if necessary""" |
350 cubes_parent_dir = normpath(join(cls.CUBES_DIR, '..')) |
350 cubes_parent_dir = normpath(join(cls.CUBES_DIR, '..')) |
351 if not cubes_parent_dir in sys.path: |
351 if not cubes_parent_dir in sys.path: |
379 try: |
379 try: |
380 __import__('cubes.%s' % cube) |
380 __import__('cubes.%s' % cube) |
381 except: |
381 except: |
382 cls.exception('while loading cube %s', cube) |
382 cls.exception('while loading cube %s', cube) |
383 else: |
383 else: |
384 cls.warning('no __init__ file in cube %s', cube) |
384 cls.warning('no __init__ file in cube %s', cube) |
385 |
385 |
386 @classmethod |
386 @classmethod |
387 def init_available_cubes(cls): |
387 def init_available_cubes(cls): |
388 """cubes may register some sources (svnfile for instance) in their |
388 """cubes may register some sources (svnfile for instance) in their |
389 __init__ file, so they should be loaded early in the startup process |
389 __init__ file, so they should be loaded early in the startup process |
391 for cube in cls.available_cubes(): |
391 for cube in cls.available_cubes(): |
392 try: |
392 try: |
393 __import__('cubes.%s' % cube) |
393 __import__('cubes.%s' % cube) |
394 except Exception, ex: |
394 except Exception, ex: |
395 cls.warning("can't init cube %s: %s", cube, ex) |
395 cls.warning("can't init cube %s: %s", cube, ex) |
396 |
396 |
397 cubicweb_vobject_path = set(['entities']) |
397 cubicweb_vobject_path = set(['entities']) |
398 cube_vobject_path = set(['entities']) |
398 cube_vobject_path = set(['entities']) |
399 |
399 |
400 @classmethod |
400 @classmethod |
401 def build_vregistry_path(cls, templpath, evobjpath=None, tvobjpath=None): |
401 def build_vregistry_path(cls, templpath, evobjpath=None, tvobjpath=None): |
439 if exists(path): |
439 if exists(path): |
440 vregpath.append(path) |
440 vregpath.append(path) |
441 elif exists(path + '.py'): |
441 elif exists(path + '.py'): |
442 vregpath.append(path + '.py') |
442 vregpath.append(path + '.py') |
443 return vregpath |
443 return vregpath |
444 |
444 |
445 def __init__(self): |
445 def __init__(self): |
446 ConfigurationMixIn.__init__(self) |
446 ConfigurationMixIn.__init__(self) |
447 self.adjust_sys_path() |
447 self.adjust_sys_path() |
448 self.load_defaults() |
448 self.load_defaults() |
449 self.translations = {} |
449 self.translations = {} |
450 |
450 |
451 def adjust_sys_path(self): |
451 def adjust_sys_path(self): |
452 self.cls_adjust_sys_path() |
452 self.cls_adjust_sys_path() |
453 |
453 |
454 def init_log(self, logthreshold=None, debug=False, |
454 def init_log(self, logthreshold=None, debug=False, |
455 logfile=None, syslog=False): |
455 logfile=None, syslog=False): |
456 """init the log service""" |
456 """init the log service""" |
457 if logthreshold is None: |
457 if logthreshold is None: |
458 if debug: |
458 if debug: |
459 logthreshold = 'DEBUG' |
459 logthreshold = 'DEBUG' |
466 def vregistry_path(self): |
466 def vregistry_path(self): |
467 """return a list of files or directories where the registry will look |
467 """return a list of files or directories where the registry will look |
468 for application objects. By default return nothing in NoApp config. |
468 for application objects. By default return nothing in NoApp config. |
469 """ |
469 """ |
470 return [] |
470 return [] |
471 |
471 |
472 def eproperty_definitions(self): |
472 def eproperty_definitions(self): |
473 cfg = self.persistent_options_configuration() |
473 cfg = self.persistent_options_configuration() |
474 for section, options in cfg.options_by_section(): |
474 for section, options in cfg.options_by_section(): |
475 section = section.lower() |
475 section = section.lower() |
476 for optname, optdict, value in options: |
476 for optname, optdict, value in options: |
479 default = cfg.option_default(optname, optdict) |
479 default = cfg.option_default(optname, optdict) |
480 pdef = {'type': type, 'vocabulary': vocab, 'default': default, |
480 pdef = {'type': type, 'vocabulary': vocab, 'default': default, |
481 'help': optdict['help'], |
481 'help': optdict['help'], |
482 'sitewide': optdict.get('sitewide', False)} |
482 'sitewide': optdict.get('sitewide', False)} |
483 yield key, pdef |
483 yield key, pdef |
484 |
484 |
485 def map_option(self, optdict): |
485 def map_option(self, optdict): |
486 try: |
486 try: |
487 vocab = optdict['choices'] |
487 vocab = optdict['choices'] |
488 except KeyError: |
488 except KeyError: |
489 vocab = optdict.get('vocabulary') |
489 vocab = optdict.get('vocabulary') |
490 if isinstance(vocab, Method): |
490 if isinstance(vocab, Method): |
491 vocab = getattr(self, vocab.method, ()) |
491 vocab = getattr(self, vocab.method, ()) |
492 return CFGTYPE2ETYPE_MAP[optdict['type']], vocab |
492 return CFGTYPE2ETYPE_MAP[optdict['type']], vocab |
493 |
493 |
494 |
494 |
495 class CubicWebConfiguration(CubicWebNoAppConfiguration): |
495 class CubicWebConfiguration(CubicWebNoAppConfiguration): |
496 """base class for cubicweb server and web configurations""" |
496 """base class for cubicweb server and web configurations""" |
497 |
497 |
498 INSTANCE_DATA_DIR = None |
498 INSTANCE_DATA_DIR = None |
499 if CubicWebNoAppConfiguration.mode == 'test': |
499 if CubicWebNoAppConfiguration.mode == 'test': |
500 root = os.environ['APYCOT_ROOT'] |
500 root = os.environ['APYCOT_ROOT'] |
501 REGISTRY_DIR = '%s/etc/cubicweb.d/' % root |
501 REGISTRY_DIR = '%s/etc/cubicweb.d/' % root |
502 RUNTIME_DIR = '/tmp/' |
502 RUNTIME_DIR = '/tmp/' |
515 |
515 |
516 # for some commands (creation...) we don't want to initialize gettext |
516 # for some commands (creation...) we don't want to initialize gettext |
517 set_language = True |
517 set_language = True |
518 # set this to true to avoid false error message while creating an application |
518 # set this to true to avoid false error message while creating an application |
519 creating = False |
519 creating = False |
520 |
520 |
521 options = CubicWebNoAppConfiguration.options + ( |
521 options = CubicWebNoAppConfiguration.options + ( |
522 ('log-file', |
522 ('log-file', |
523 {'type' : 'string', |
523 {'type' : 'string', |
524 'default': Method('default_log_file'), |
524 'default': Method('default_log_file'), |
525 'help': 'file where output logs should be written', |
525 'help': 'file where output logs should be written', |
538 'help': 'listening port of the SMTP mail server', |
538 'help': 'listening port of the SMTP mail server', |
539 'group': 'email', 'inputlevel': 1, |
539 'group': 'email', 'inputlevel': 1, |
540 }), |
540 }), |
541 ('sender-name', |
541 ('sender-name', |
542 {'type' : 'string', |
542 {'type' : 'string', |
543 'default': Method('default_application_id'), |
543 'default': Method('default_application_id'), |
544 'help': 'name used as HELO name for outgoing emails from the \ |
544 'help': 'name used as HELO name for outgoing emails from the \ |
545 repository.', |
545 repository.', |
546 'group': 'email', 'inputlevel': 2, |
546 'group': 'email', 'inputlevel': 2, |
547 }), |
547 }), |
548 ('sender-addr', |
548 ('sender-addr', |
556 |
556 |
557 @classmethod |
557 @classmethod |
558 def runtime_dir(cls): |
558 def runtime_dir(cls): |
559 """run time directory for pid file...""" |
559 """run time directory for pid file...""" |
560 return env_path('CW_RUNTIME', cls.RUNTIME_DIR, 'run time') |
560 return env_path('CW_RUNTIME', cls.RUNTIME_DIR, 'run time') |
561 |
561 |
562 @classmethod |
562 @classmethod |
563 def registry_dir(cls): |
563 def registry_dir(cls): |
564 """return the control directory""" |
564 """return the control directory""" |
565 return env_path('CW_REGISTRY', cls.REGISTRY_DIR, 'registry') |
565 return env_path('CW_REGISTRY', cls.REGISTRY_DIR, 'registry') |
566 |
566 |
568 def instance_data_dir(cls): |
568 def instance_data_dir(cls): |
569 """return the instance data directory""" |
569 """return the instance data directory""" |
570 return env_path('CW_INSTANCE_DATA', |
570 return env_path('CW_INSTANCE_DATA', |
571 cls.INSTANCE_DATA_DIR or cls.REGISTRY_DIR, |
571 cls.INSTANCE_DATA_DIR or cls.REGISTRY_DIR, |
572 'additional data') |
572 'additional data') |
573 |
573 |
574 @classmethod |
574 @classmethod |
575 def migration_scripts_dir(cls): |
575 def migration_scripts_dir(cls): |
576 """cubicweb migration scripts directory""" |
576 """cubicweb migration scripts directory""" |
577 return env_path('CW_MIGRATION', cls.MIGRATION_DIR, 'migration') |
577 return env_path('CW_MIGRATION', cls.MIGRATION_DIR, 'migration') |
578 |
578 |
581 """return a configuration instance for the given application identifier |
581 """return a configuration instance for the given application identifier |
582 """ |
582 """ |
583 config = config or guess_configuration(cls.application_home(appid)) |
583 config = config or guess_configuration(cls.application_home(appid)) |
584 configcls = configuration_cls(config) |
584 configcls = configuration_cls(config) |
585 return configcls(appid) |
585 return configcls(appid) |
586 |
586 |
587 @classmethod |
587 @classmethod |
588 def possible_configurations(cls, appid): |
588 def possible_configurations(cls, appid): |
589 """return the name of possible configurations for the given |
589 """return the name of possible configurations for the given |
590 application id |
590 application id |
591 """ |
591 """ |
592 home = cls.application_home(appid) |
592 home = cls.application_home(appid) |
593 return possible_configurations(home) |
593 return possible_configurations(home) |
594 |
594 |
595 @classmethod |
595 @classmethod |
596 def application_home(cls, appid): |
596 def application_home(cls, appid): |
597 """return the home directory of the application with the given |
597 """return the home directory of the application with the given |
598 application id |
598 application id |
599 """ |
599 """ |
608 'twisted' : ('common', 'web'),} |
608 'twisted' : ('common', 'web'),} |
609 @classmethod |
609 @classmethod |
610 def accept_mode(cls, mode): |
610 def accept_mode(cls, mode): |
611 #assert mode in cls.MODES, mode |
611 #assert mode in cls.MODES, mode |
612 return mode in cls.MCOMPAT[cls.name] |
612 return mode in cls.MCOMPAT[cls.name] |
613 |
613 |
614 # default configuration methods ########################################### |
614 # default configuration methods ########################################### |
615 |
615 |
616 def default_application_id(self): |
616 def default_application_id(self): |
617 """return the application identifier, useful for option which need this |
617 """return the application identifier, useful for option which need this |
618 as default value |
618 as default value |
619 """ |
619 """ |
620 return self.appid |
620 return self.appid |
632 except IOError: |
632 except IOError: |
633 path = '%s-%s.log' % (basepath, i) |
633 path = '%s-%s.log' % (basepath, i) |
634 i += 1 |
634 i += 1 |
635 return path |
635 return path |
636 return '/var/log/cubicweb/%s-%s.log' % (self.appid, self.name) |
636 return '/var/log/cubicweb/%s-%s.log' % (self.appid, self.name) |
637 |
637 |
638 def default_pid_file(self): |
638 def default_pid_file(self): |
639 """return default path to the pid file of the application'server""" |
639 """return default path to the pid file of the application'server""" |
640 return join(self.runtime_dir(), '%s-%s.pid' % (self.appid, self.name)) |
640 return join(self.runtime_dir(), '%s-%s.pid' % (self.appid, self.name)) |
641 |
641 |
642 # instance methods used to get application specific resources ############# |
642 # instance methods used to get application specific resources ############# |
643 |
643 |
644 def __init__(self, appid): |
644 def __init__(self, appid): |
645 self.appid = appid |
645 self.appid = appid |
646 CubicWebNoAppConfiguration.__init__(self) |
646 CubicWebNoAppConfiguration.__init__(self) |
647 self._cubes = None |
647 self._cubes = None |
648 self._site_loaded = set() |
648 self._site_loaded = set() |
656 sys.path.insert(0, self.apphome) |
656 sys.path.insert(0, self.apphome) |
657 |
657 |
658 @property |
658 @property |
659 def apphome(self): |
659 def apphome(self): |
660 return join(self.registry_dir(), self.appid) |
660 return join(self.registry_dir(), self.appid) |
661 |
661 |
662 @property |
662 @property |
663 def appdatahome(self): |
663 def appdatahome(self): |
664 return join(self.instance_data_dir(), self.appid) |
664 return join(self.instance_data_dir(), self.appid) |
665 |
665 |
666 def init_cubes(self, cubes): |
666 def init_cubes(self, cubes): |
667 assert self._cubes is None |
667 assert self._cubes is None |
668 self._cubes = self.reorder_cubes(cubes) |
668 self._cubes = self.reorder_cubes(cubes) |
669 # load cubes'__init__.py file first |
669 # load cubes'__init__.py file first |
670 for cube in cubes: |
670 for cube in cubes: |
673 # reload config file in cases options are defined in cubes __init__ |
673 # reload config file in cases options are defined in cubes __init__ |
674 # or site_cubicweb files |
674 # or site_cubicweb files |
675 self.load_file_configuration(self.main_config_file()) |
675 self.load_file_configuration(self.main_config_file()) |
676 # configuration initialization hook |
676 # configuration initialization hook |
677 self.load_configuration() |
677 self.load_configuration() |
678 |
678 |
679 def cubes(self): |
679 def cubes(self): |
680 """return the list of cubes used by this instance |
680 """return the list of cubes used by this instance |
681 |
681 |
682 result is ordered from the top level cubes to inner dependencies |
682 result is ordered from the top level cubes to inner dependencies |
683 cubes |
683 cubes |
684 """ |
684 """ |
685 assert self._cubes is not None |
685 assert self._cubes is not None |
686 return self._cubes |
686 return self._cubes |
687 |
687 |
688 def cubes_path(self): |
688 def cubes_path(self): |
689 """return the list of path to cubes used by this instance, from outer |
689 """return the list of path to cubes used by this instance, from outer |
690 most to inner most cubes |
690 most to inner most cubes |
691 """ |
691 """ |
692 return [self.cube_dir(p) for p in self.cubes()] |
692 return [self.cube_dir(p) for p in self.cubes()] |
694 def add_cubes(self, cubes): |
694 def add_cubes(self, cubes): |
695 """add given cubes to the list of used cubes""" |
695 """add given cubes to the list of used cubes""" |
696 if not isinstance(cubes, list): |
696 if not isinstance(cubes, list): |
697 cubes = list(cubes) |
697 cubes = list(cubes) |
698 self._cubes = self.reorder_cubes(list(self._cubes) + cubes) |
698 self._cubes = self.reorder_cubes(list(self._cubes) + cubes) |
699 |
699 |
700 def main_config_file(self): |
700 def main_config_file(self): |
701 """return application's control configuration file""" |
701 """return application's control configuration file""" |
702 return join(self.apphome, '%s.conf' % self.name) |
702 return join(self.apphome, '%s.conf' % self.name) |
703 |
703 |
704 def save(self): |
704 def save(self): |
705 """write down current configuration""" |
705 """write down current configuration""" |
706 self.generate_config(open(self.main_config_file(), 'w')) |
706 self.generate_config(open(self.main_config_file(), 'w')) |
707 |
707 |
708 @cached |
708 @cached |
711 infos = [] |
711 infos = [] |
712 for pkg in self.cubes(): |
712 for pkg in self.cubes(): |
713 version = self.cube_version(pkg) |
713 version = self.cube_version(pkg) |
714 infos.append('%s-%s' % (pkg, version)) |
714 infos.append('%s-%s' % (pkg, version)) |
715 return md5.new(';'.join(infos)).hexdigest() |
715 return md5.new(';'.join(infos)).hexdigest() |
716 |
716 |
717 def load_site_cubicweb(self): |
717 def load_site_cubicweb(self): |
718 """load (web?) application's specific site_cubicweb file""" |
718 """load (web?) application's specific site_cubicweb file""" |
719 for path in reversed([self.apphome] + self.cubes_path()): |
719 for path in reversed([self.apphome] + self.cubes_path()): |
720 sitefile = join(path, 'site_cubicweb.py') |
720 sitefile = join(path, 'site_cubicweb.py') |
721 if exists(sitefile) and not sitefile in self._site_loaded: |
721 if exists(sitefile) and not sitefile in self._site_loaded: |
725 sitefile = join(path, 'site_erudi.py') |
725 sitefile = join(path, 'site_erudi.py') |
726 if exists(sitefile) and not sitefile in self._site_loaded: |
726 if exists(sitefile) and not sitefile in self._site_loaded: |
727 self._load_site_cubicweb(sitefile) |
727 self._load_site_cubicweb(sitefile) |
728 self._site_loaded.add(sitefile) |
728 self._site_loaded.add(sitefile) |
729 self.warning('site_erudi.py is deprecated, should be renamed to site_cubicweb.py') |
729 self.warning('site_erudi.py is deprecated, should be renamed to site_cubicweb.py') |
730 |
730 |
731 def _load_site_cubicweb(self, sitefile): |
731 def _load_site_cubicweb(self, sitefile): |
732 context = {} |
732 context = {} |
733 execfile(sitefile, context, context) |
733 execfile(sitefile, context, context) |
734 self.info('%s loaded', sitefile) |
734 self.info('%s loaded', sitefile) |
735 # cube specific options |
735 # cube specific options |
736 if context.get('options'): |
736 if context.get('options'): |
737 self.register_options(context['options']) |
737 self.register_options(context['options']) |
738 self.load_defaults() |
738 self.load_defaults() |
739 |
739 |
740 def load_configuration(self): |
740 def load_configuration(self): |
741 """load application's configuration files""" |
741 """load application's configuration files""" |
742 super(CubicWebConfiguration, self).load_configuration() |
742 super(CubicWebConfiguration, self).load_configuration() |
743 if self.apphome and self.set_language: |
743 if self.apphome and self.set_language: |
744 # init gettext |
744 # init gettext |
745 self._set_language() |
745 self._set_language() |
746 |
746 |
747 def init_log(self, logthreshold=None, debug=False, force=False): |
747 def init_log(self, logthreshold=None, debug=False, force=False): |
748 """init the log service""" |
748 """init the log service""" |
749 if not force and hasattr(self, '_logging_initialized'): |
749 if not force and hasattr(self, '_logging_initialized'): |
750 return |
750 return |
751 self._logging_initialized = True |
751 self._logging_initialized = True |
767 for path in glob(join(self.apphome, 'i18n', |
767 for path in glob(join(self.apphome, 'i18n', |
768 '*', 'LC_MESSAGES', 'cubicweb.mo')): |
768 '*', 'LC_MESSAGES', 'cubicweb.mo')): |
769 lang = path.split(os.sep)[-3] |
769 lang = path.split(os.sep)[-3] |
770 if lang != 'en': |
770 if lang != 'en': |
771 yield lang |
771 yield lang |
772 |
772 |
773 def _set_language(self): |
773 def _set_language(self): |
774 """set language for gettext""" |
774 """set language for gettext""" |
775 from gettext import translation |
775 from gettext import translation |
776 path = join(self.apphome, 'i18n') |
776 path = join(self.apphome, 'i18n') |
777 for language in self.available_languages(): |
777 for language in self.available_languages(): |
779 try: |
779 try: |
780 tr = translation('cubicweb', path, languages=[language]) |
780 tr = translation('cubicweb', path, languages=[language]) |
781 self.translations[language] = tr.ugettext |
781 self.translations[language] = tr.ugettext |
782 except (ImportError, AttributeError, IOError): |
782 except (ImportError, AttributeError, IOError): |
783 self.exception('localisation support error for language %s', |
783 self.exception('localisation support error for language %s', |
784 language) |
784 language) |
785 |
785 |
786 def vregistry_path(self): |
786 def vregistry_path(self): |
787 """return a list of files or directories where the registry will look |
787 """return a list of files or directories where the registry will look |
788 for application objects |
788 for application objects |
789 """ |
789 """ |
790 templpath = list(reversed(self.cubes_path())) |
790 templpath = list(reversed(self.cubes_path())) |
794 |
794 |
795 def set_sources_mode(self, sources): |
795 def set_sources_mode(self, sources): |
796 if not 'all' in sources: |
796 if not 'all' in sources: |
797 print 'warning: ignoring specified sources, requires a repository '\ |
797 print 'warning: ignoring specified sources, requires a repository '\ |
798 'configuration' |
798 'configuration' |
799 |
799 |
800 def migration_handler(self): |
800 def migration_handler(self): |
801 """return a migration handler instance""" |
801 """return a migration handler instance""" |
802 from cubicweb.common.migration import MigrationHelper |
802 from cubicweb.common.migration import MigrationHelper |
803 return MigrationHelper(self, verbosity=self.verbosity) |
803 return MigrationHelper(self, verbosity=self.verbosity) |
804 |
804 |
812 sourcedirs = [join(path, 'i18n') for path in self.cubes_path()] |
812 sourcedirs = [join(path, 'i18n') for path in self.cubes_path()] |
813 sourcedirs.append(self.i18n_lib_dir()) |
813 sourcedirs.append(self.i18n_lib_dir()) |
814 return i18n.compile_i18n_catalogs(sourcedirs, i18ndir, langs) |
814 return i18n.compile_i18n_catalogs(sourcedirs, i18ndir, langs) |
815 |
815 |
816 set_log_methods(CubicWebConfiguration, logging.getLogger('cubicweb.configuration')) |
816 set_log_methods(CubicWebConfiguration, logging.getLogger('cubicweb.configuration')) |
817 |
817 |
818 # alias to get a configuration instance from an application id |
818 # alias to get a configuration instance from an application id |
819 application_configuration = CubicWebConfiguration.config_for |
819 application_configuration = CubicWebConfiguration.config_for |
820 |
820 |