20 from smtplib import SMTP |
20 from smtplib import SMTP |
21 from threading import Lock |
21 from threading import Lock |
22 from os.path import exists, join, expanduser, abspath, normpath, basename, isdir |
22 from os.path import exists, join, expanduser, abspath, normpath, basename, isdir |
23 |
23 |
24 from logilab.common.decorators import cached |
24 from logilab.common.decorators import cached |
|
25 from logilab.common.deprecation import deprecated_function |
25 from logilab.common.logging_ext import set_log_methods, init_log |
26 from logilab.common.logging_ext import set_log_methods, init_log |
26 from logilab.common.configuration import (Configuration, Method, |
27 from logilab.common.configuration import (Configuration, Method, |
27 ConfigurationMixIn, merge_options) |
28 ConfigurationMixIn, merge_options) |
28 |
29 |
29 from cubicweb import CW_SOFTWARE_ROOT, CW_MIGRATION_MAP, ConfigurationError |
30 from cubicweb import CW_SOFTWARE_ROOT, CW_MIGRATION_MAP, ConfigurationError |
219 {'type' : 'csv', 'default': (), |
220 {'type' : 'csv', 'default': (), |
220 'help': 'comma separated list of identifiers of application objects (<registry>.<oid>) to disable', |
221 'help': 'comma separated list of identifiers of application objects (<registry>.<oid>) to disable', |
221 'group': 'appobjects', 'inputlevel': 2, |
222 'group': 'appobjects', 'inputlevel': 2, |
222 }), |
223 }), |
223 ) |
224 ) |
224 # static and class methods used to get application independant resources ## |
225 # static and class methods used to get instance independant resources ## |
225 |
226 |
226 @staticmethod |
227 @staticmethod |
227 def cubicweb_version(): |
228 def cubicweb_version(): |
228 """return installed cubicweb version""" |
229 """return installed cubicweb version""" |
229 from logilab.common.changelog import Version |
230 from logilab.common.changelog import Version |
245 return join(CW_SOFTWARE_ROOT, 'web') |
246 return join(CW_SOFTWARE_ROOT, 'web') |
246 return cls.cube_dir('shared') |
247 return cls.cube_dir('shared') |
247 |
248 |
248 @classmethod |
249 @classmethod |
249 def i18n_lib_dir(cls): |
250 def i18n_lib_dir(cls): |
250 """return application's i18n directory""" |
251 """return instance's i18n directory""" |
251 if cls.mode in ('dev', 'test') and not os.environ.get('APYCOT_ROOT'): |
252 if cls.mode in ('dev', 'test') and not os.environ.get('APYCOT_ROOT'): |
252 return join(CW_SOFTWARE_ROOT, 'i18n') |
253 return join(CW_SOFTWARE_ROOT, 'i18n') |
253 return join(cls.shared_dir(), 'i18n') |
254 return join(cls.shared_dir(), 'i18n') |
254 |
255 |
255 @classmethod |
256 @classmethod |
422 cube_vobject_path = set(['entities']) |
423 cube_vobject_path = set(['entities']) |
423 |
424 |
424 @classmethod |
425 @classmethod |
425 def build_vregistry_path(cls, templpath, evobjpath=None, tvobjpath=None): |
426 def build_vregistry_path(cls, templpath, evobjpath=None, tvobjpath=None): |
426 """given a list of directories, return a list of sub files and |
427 """given a list of directories, return a list of sub files and |
427 directories that should be loaded by the application objects registry. |
428 directories that should be loaded by the instance objects registry. |
428 |
429 |
429 :param evobjpath: |
430 :param evobjpath: |
430 optional list of sub-directories (or files without the .py ext) of |
431 optional list of sub-directories (or files without the .py ext) of |
431 the cubicweb library that should be tested and added to the output list |
432 the cubicweb library that should be tested and added to the output list |
432 if they exists. If not give, default to `cubicweb_vobject_path` class |
433 if they exists. If not give, default to `cubicweb_vobject_path` class |
537 RUNTIME_DIR = '/var/run/cubicweb/' |
538 RUNTIME_DIR = '/var/run/cubicweb/' |
538 MIGRATION_DIR = '/usr/share/cubicweb/migration/' |
539 MIGRATION_DIR = '/usr/share/cubicweb/migration/' |
539 |
540 |
540 # for some commands (creation...) we don't want to initialize gettext |
541 # for some commands (creation...) we don't want to initialize gettext |
541 set_language = True |
542 set_language = True |
542 # set this to true to avoid false error message while creating an application |
543 # set this to true to avoid false error message while creating an instance |
543 creating = False |
544 creating = False |
544 # set this to true to allow somethings which would'nt be possible |
545 # set this to true to allow somethings which would'nt be possible |
545 repairing = False |
546 repairing = False |
546 |
547 |
547 options = CubicWebNoAppConfiguration.options + ( |
548 options = CubicWebNoAppConfiguration.options + ( |
564 'help': 'listening port of the SMTP mail server', |
565 'help': 'listening port of the SMTP mail server', |
565 'group': 'email', 'inputlevel': 1, |
566 'group': 'email', 'inputlevel': 1, |
566 }), |
567 }), |
567 ('sender-name', |
568 ('sender-name', |
568 {'type' : 'string', |
569 {'type' : 'string', |
569 'default': Method('default_application_id'), |
570 'default': Method('default_instance_id'), |
570 'help': 'name used as HELO name for outgoing emails from the \ |
571 'help': 'name used as HELO name for outgoing emails from the \ |
571 repository.', |
572 repository.', |
572 'group': 'email', 'inputlevel': 2, |
573 'group': 'email', 'inputlevel': 2, |
573 }), |
574 }), |
574 ('sender-addr', |
575 ('sender-addr', |
602 """cubicweb migration scripts directory""" |
603 """cubicweb migration scripts directory""" |
603 return env_path('CW_MIGRATION_DIR', cls.MIGRATION_DIR, 'migration') |
604 return env_path('CW_MIGRATION_DIR', cls.MIGRATION_DIR, 'migration') |
604 |
605 |
605 @classmethod |
606 @classmethod |
606 def config_for(cls, appid, config=None): |
607 def config_for(cls, appid, config=None): |
607 """return a configuration instance for the given application identifier |
608 """return a configuration instance for the given instance identifier |
608 """ |
609 """ |
609 config = config or guess_configuration(cls.application_home(appid)) |
610 config = config or guess_configuration(cls.instance_home(appid)) |
610 configcls = configuration_cls(config) |
611 configcls = configuration_cls(config) |
611 return configcls(appid) |
612 return configcls(appid) |
612 |
613 |
613 @classmethod |
614 @classmethod |
614 def possible_configurations(cls, appid): |
615 def possible_configurations(cls, appid): |
615 """return the name of possible configurations for the given |
616 """return the name of possible configurations for the given |
616 application id |
617 instance id |
617 """ |
618 """ |
618 home = cls.application_home(appid) |
619 home = cls.instance_home(appid) |
619 return possible_configurations(home) |
620 return possible_configurations(home) |
620 |
621 |
621 @classmethod |
622 @classmethod |
622 def application_home(cls, appid): |
623 def instance_home(cls, appid): |
623 """return the home directory of the application with the given |
624 """return the home directory of the instance with the given |
624 application id |
625 instance id |
625 """ |
626 """ |
626 home = join(cls.registry_dir(), appid) |
627 home = join(cls.registry_dir(), appid) |
627 if not exists(home): |
628 if not exists(home): |
628 raise ConfigurationError('no such application %s (check it exists with "cubicweb-ctl list")' % appid) |
629 raise ConfigurationError('no such instance %s (check it exists with "cubicweb-ctl list")' % appid) |
629 return home |
630 return home |
630 |
631 |
631 MODES = ('common', 'repository', 'Any', 'web') |
632 MODES = ('common', 'repository', 'Any', 'web') |
632 MCOMPAT = {'all-in-one': MODES, |
633 MCOMPAT = {'all-in-one': MODES, |
633 'repository': ('common', 'repository', 'Any'), |
634 'repository': ('common', 'repository', 'Any'), |
637 #assert mode in cls.MODES, mode |
638 #assert mode in cls.MODES, mode |
638 return mode in cls.MCOMPAT[cls.name] |
639 return mode in cls.MCOMPAT[cls.name] |
639 |
640 |
640 # default configuration methods ########################################### |
641 # default configuration methods ########################################### |
641 |
642 |
642 def default_application_id(self): |
643 def default_instance_id(self): |
643 """return the application identifier, useful for option which need this |
644 """return the instance identifier, useful for option which need this |
644 as default value |
645 as default value |
645 """ |
646 """ |
646 return self.appid |
647 return self.appid |
647 |
648 |
648 def default_log_file(self): |
649 def default_log_file(self): |
649 """return default path to the log file of the application'server""" |
650 """return default path to the log file of the instance'server""" |
650 if self.mode == 'dev': |
651 if self.mode == 'dev': |
651 basepath = '/tmp/%s-%s' % (basename(self.appid), self.name) |
652 basepath = '/tmp/%s-%s' % (basename(self.appid), self.name) |
652 path = basepath + '.log' |
653 path = basepath + '.log' |
653 i = 1 |
654 i = 1 |
654 while exists(path) and i < 100: # arbitrary limit to avoid infinite loop |
655 while exists(path) and i < 100: # arbitrary limit to avoid infinite loop |
660 i += 1 |
661 i += 1 |
661 return path |
662 return path |
662 return '/var/log/cubicweb/%s-%s.log' % (self.appid, self.name) |
663 return '/var/log/cubicweb/%s-%s.log' % (self.appid, self.name) |
663 |
664 |
664 def default_pid_file(self): |
665 def default_pid_file(self): |
665 """return default path to the pid file of the application'server""" |
666 """return default path to the pid file of the instance'server""" |
666 return join(self.runtime_dir(), '%s-%s.pid' % (self.appid, self.name)) |
667 return join(self.runtime_dir(), '%s-%s.pid' % (self.appid, self.name)) |
667 |
668 |
668 # instance methods used to get application specific resources ############# |
669 # instance methods used to get instance specific resources ############# |
669 |
670 |
670 def __init__(self, appid): |
671 def __init__(self, appid): |
671 self.appid = appid |
672 self.appid = appid |
672 CubicWebNoAppConfiguration.__init__(self) |
673 CubicWebNoAppConfiguration.__init__(self) |
673 self._cubes = None |
674 self._cubes = None |
722 if not isinstance(cubes, list): |
723 if not isinstance(cubes, list): |
723 cubes = list(cubes) |
724 cubes = list(cubes) |
724 self._cubes = self.reorder_cubes(list(self._cubes) + cubes) |
725 self._cubes = self.reorder_cubes(list(self._cubes) + cubes) |
725 |
726 |
726 def main_config_file(self): |
727 def main_config_file(self): |
727 """return application's control configuration file""" |
728 """return instance's control configuration file""" |
728 return join(self.apphome, '%s.conf' % self.name) |
729 return join(self.apphome, '%s.conf' % self.name) |
729 |
730 |
730 def save(self): |
731 def save(self): |
731 """write down current configuration""" |
732 """write down current configuration""" |
732 self.generate_config(open(self.main_config_file(), 'w')) |
733 self.generate_config(open(self.main_config_file(), 'w')) |
739 version = self.cube_version(pkg) |
740 version = self.cube_version(pkg) |
740 infos.append('%s-%s' % (pkg, version)) |
741 infos.append('%s-%s' % (pkg, version)) |
741 return md5.new(';'.join(infos)).hexdigest() |
742 return md5.new(';'.join(infos)).hexdigest() |
742 |
743 |
743 def load_site_cubicweb(self): |
744 def load_site_cubicweb(self): |
744 """load (web?) application's specific site_cubicweb file""" |
745 """load instance's specific site_cubicweb file""" |
745 for path in reversed([self.apphome] + self.cubes_path()): |
746 for path in reversed([self.apphome] + self.cubes_path()): |
746 sitefile = join(path, 'site_cubicweb.py') |
747 sitefile = join(path, 'site_cubicweb.py') |
747 if exists(sitefile) and not sitefile in self._site_loaded: |
748 if exists(sitefile) and not sitefile in self._site_loaded: |
748 self._load_site_cubicweb(sitefile) |
749 self._load_site_cubicweb(sitefile) |
749 self._site_loaded.add(sitefile) |
750 self._site_loaded.add(sitefile) |
762 if context.get('options'): |
763 if context.get('options'): |
763 self.register_options(context['options']) |
764 self.register_options(context['options']) |
764 self.load_defaults() |
765 self.load_defaults() |
765 |
766 |
766 def load_configuration(self): |
767 def load_configuration(self): |
767 """load application's configuration files""" |
768 """load instance's configuration files""" |
768 super(CubicWebConfiguration, self).load_configuration() |
769 super(CubicWebConfiguration, self).load_configuration() |
769 if self.apphome and self.set_language: |
770 if self.apphome and self.set_language: |
770 # init gettext |
771 # init gettext |
771 self._set_language() |
772 self._set_language() |
772 |
773 |
781 logconfig = join(self.apphome, 'logging.conf') |
782 logconfig = join(self.apphome, 'logging.conf') |
782 if exists(logconfig): |
783 if exists(logconfig): |
783 logging.fileConfig(logconfig) |
784 logging.fileConfig(logconfig) |
784 |
785 |
785 def available_languages(self, *args): |
786 def available_languages(self, *args): |
786 """return available translation for an application, by looking for |
787 """return available translation for an instance, by looking for |
787 compiled catalog |
788 compiled catalog |
788 |
789 |
789 take *args to be usable as a vocabulary method |
790 take *args to be usable as a vocabulary method |
790 """ |
791 """ |
791 from glob import glob |
792 from glob import glob |