diff --git a/setup.py b/setup.py index 0b804f1fc4..5719afc044 100644 --- a/setup.py +++ b/setup.py @@ -13,6 +13,8 @@ setup(name=PACKAGE, author='B2CK', author_email='info@b2ck.com', url=WEBSITE, + download_url="http://downloads.tryton.org/" + \ + VERSION.rsplit('.', 1)[0] + '/', packages=find_packages(exclude=['*.modules.*', 'modules.*', 'modules']), package_data={ 'trytond': ['init.sql'], @@ -23,9 +25,6 @@ setup(name=PACKAGE, 'trytond.webdav': ['*.xml', '*.csv'], 'trytond.workflow': ['*.xml', '*.csv'], }, - data_files=[ - ('/etc', ['etc/trytond.conf']), - ], scripts=['bin/trytond'], classifiers=[ 'Development Status :: 5 - Production/Stable', @@ -54,4 +53,5 @@ setup(name=PACKAGE, 'graphviz': ['pydot'], 'timezone': ['pytz'], }, + zip_safe = False, ) diff --git a/trytond/config.py b/trytond/config.py index c0300c629d..febacf7cd8 100644 --- a/trytond/config.py +++ b/trytond/config.py @@ -73,6 +73,8 @@ class ConfigManager(object): configdir = os.path.abspath(os.path.normpath(os.path.join( os.path.dirname(__file__), '..'))) self.configfile = os.path.join(configdir, 'etc', 'trytond.conf') + if not os.path.isfile(self.configfile): + self.configfile = None self.load() # Verify that we want to log or not, if not the output will go to stdout @@ -113,6 +115,8 @@ class ConfigManager(object): def load(self): parser = ConfigParser.ConfigParser() + if not self.configfile: + return try: parser.read([self.configfile]) for (name, value) in parser.items('options'): diff --git a/trytond/ir/module/module.py b/trytond/ir/module/module.py index 4990dca01e..686743a251 100644 --- a/trytond/ir/module/module.py +++ b/trytond/ir/module/module.py @@ -175,11 +175,9 @@ class Module(OSV): "Return the content of the __tryton__.py" try: if name in ['ir', 'workflow', 'res', 'webdav']: - file_p = tools.file_open(os.path.join( - os.path.dirname(MODULES_PATH), name, '__tryton__.py')) + file_p = tools.file_open(os.path.join(name, '__tryton__.py')) else: - file_p = tools.file_open(os.path.join(MODULES_PATH, name, - '__tryton__.py')) + file_p = tools.file_open(os.path.join(name, '__tryton__.py')) data = file_p.read() info = eval(data) file_p.close() @@ -336,9 +334,7 @@ class Module(OSV): lang_codes = [x.code for x in lang_obj.browse(cursor, user, lang_ids, context=context)] - module_names = ['ir', 'workflow', 'res', 'webdav'] - if os.path.isdir(MODULES_PATH): - module_names += os.listdir(MODULES_PATH) + module_names = get_module_list() module_ids = self.search(cursor, user, [], context=context) modules = self.browse(cursor, user, module_ids, context=context) @@ -396,37 +392,36 @@ class Module(OSV): self._update_dependencies(cursor, user, mod, tryton.get('depends', []), context=context) continue + if name in ['ir', 'workflow', 'res', 'webdav']: mod_path = os.path.join( os.path.dirname(MODULES_PATH), name) else: mod_path = os.path.join(MODULES_PATH, name) - if os.path.isdir(mod_path) \ - or os.path.islink(mod_path) \ - or zipfile.is_zipfile(mod_path): - tryton = Module.get_module_info(mod_name) - if not tryton: - continue - new_id = self.create(cursor, user, { - 'name': mod_name, - 'state': 'uninstalled', - 'description': tryton.get('description', ''), - 'shortdesc': tryton.get('name', ''), - 'author': tryton.get('author', 'Unknown'), - 'website': tryton.get('website', ''), - }, context=context) - for code in lang_codes: - ctx = context.copy() - ctx['language'] = code - self.write(cursor, user, new_id, { - 'description': tryton.get('description_' + code, ''), - 'shortdesc': tryton.get('name_' + code, ''), - }, context=ctx) - res += 1 - name2module[mod_name] = self.browse(cursor, user, new_id, - context=context) - self._update_dependencies(cursor, user, name2module[mod_name], - tryton.get('depends', []), context=context) + + tryton = Module.get_module_info(mod_name) + if not tryton: + continue + new_id = self.create(cursor, user, { + 'name': mod_name, + 'state': 'uninstalled', + 'description': tryton.get('description', ''), + 'shortdesc': tryton.get('name', ''), + 'author': tryton.get('author', 'Unknown'), + 'website': tryton.get('website', ''), + }, context=context) + for code in lang_codes: + ctx = context.copy() + ctx['language'] = code + self.write(cursor, user, new_id, { + 'description': tryton.get('description_' + code, ''), + 'shortdesc': tryton.get('name_' + code, ''), + }, context=ctx) + res += 1 + name2module[mod_name] = self.browse(cursor, user, new_id, + context=context) + self._update_dependencies(cursor, user, name2module[mod_name], + tryton.get('depends', []), context=context) return res def _update_dependencies(self, cursor, user, module, depends=None, diff --git a/trytond/modules/__init__.py b/trytond/modules/__init__.py index 9c8614940d..040d81e943 100644 --- a/trytond/modules/__init__.py +++ b/trytond/modules/__init__.py @@ -16,6 +16,15 @@ sys.path.insert(1, MODULES_PATH) MODULES = [] +EGG_MODULES = {} +try: + import pkg_resources + for ep in pkg_resources.iter_entry_points('trytond.modules'): + mod_name = ep.module_name.split('.')[-1] + EGG_MODULES[mod_name] = ep +except ImportError: + pass + class Graph(dict): @@ -126,9 +135,14 @@ def create_graph(module_list, force=None): root_path = os.path.dirname(os.path.dirname(__file__)) tryton_file = OPJ(root_path, module, '__tryton__.py') mod_path = OPJ(root_path, module) + elif module in EGG_MODULES: + ep = EGG_MODULES[module] + tryton_file = OPJ(ep.dist.location, 'trytond', 'modules', module, + '__tryton__.py') + mod_path = OPJ(ep.dist.location, 'trytond', 'modules', module) if os.path.isfile(tryton_file) or zipfile.is_zipfile(mod_path+'.zip'): try: - info = eval(tools.file_open(tryton_file).read()) + info = eval(tools.file_open(tryton_file, subdir='').read()) except: logging.getLogger('init').error( 'module:%s:eval file %s' % (module, tryton_file)) @@ -272,6 +286,9 @@ def get_module_list(): module_list.append(file) elif file[-4:] == '.zip': module_list.append(file) + for ep in pkg_resources.iter_entry_points('trytond.modules'): + mod_name = ep.module_name.split('.')[-1] + module_list.append(mod_name) module_list.append('ir') module_list.append('workflow') module_list.append('res') @@ -283,6 +300,7 @@ def register_classes(): import trytond.workflow import trytond.res import trytond.webdav + for package in create_graph(get_module_list())[0]: module = package.name logging.getLogger('init').info( @@ -292,29 +310,8 @@ def register_classes(): MODULES.append(module) continue - if not os.path.isfile(OPJ(MODULES_PATH, module+'.zip')): - try: - imp.load_module(module, *imp.find_module(module, - [MODULES_PATH])) - except ImportError: - tb_s = '' - for line in traceback.format_exception(*sys.exc_info()): - try: - line = line.encode('utf-8', 'ignore') - except: - continue - tb_s += line - for path in sys.path: - tb_s = tb_s.replace(path, '') - if CONFIG['debug_mode']: - import pdb - traceb = sys.exc_info()[2] - pdb.post_mortem(traceb) - logging.getLogger('init').error( - 'Couldn\'t import module %s:\n%s' % (module, tb_s)) - break - else: - mod_path = OPJ(MODULES_PATH, module+'.zip') + if os.path.isfile(OPJ(MODULES_PATH, module + '.zip')): + mod_path = OPJ(MODULES_PATH, module + '.zip') try: zimp = zipimport.zipimporter(mod_path) zimp.load_module(module) @@ -335,6 +332,36 @@ def register_classes(): logging.getLogger('init').error( 'Couldn\'t import module %s:\n%s' % (module, tb_s)) break + elif os.path.isdir(OPJ(MODULES_PATH, module)): + try: + imp.load_module(module, *imp.find_module(module, + [MODULES_PATH])) + except ImportError: + tb_s = '' + for line in traceback.format_exception(*sys.exc_info()): + try: + line = line.encode('utf-8', 'ignore') + except: + continue + tb_s += line + for path in sys.path: + tb_s = tb_s.replace(path, '') + if CONFIG['debug_mode']: + import pdb + traceb = sys.exc_info()[2] + pdb.post_mortem(traceb) + logging.getLogger('init').error( + 'Couldn\'t import module %s:\n%s' % (module, tb_s)) + break + elif module in EGG_MODULES: + ep = EGG_MODULES[module] + mod_path = os.path.join(ep.dist.location, + *ep.module_name.split('.')[:-1]) + imp.load_module(module, *imp.find_module(module, [mod_path])) + else: + logging.getLogger('init').error( + 'Couldn\'t find module %s' % module) + break MODULES.append(module) def load_modules(database, pool, pool_wizard, pool_report, update_module=False, diff --git a/trytond/server.py b/trytond/server.py index 74a43be95c..c614afeeb5 100644 --- a/trytond/server.py +++ b/trytond/server.py @@ -62,7 +62,9 @@ class TrytonServer(object): self.logger = logging.getLogger("init") - self.logger.info('using %s as configuration file' % CONFIG.configfile) + if CONFIG.configfile: + self.logger.info('using %s as configuration file' % \ + CONFIG.configfile) self.logger.info('initialising distributed objects services') self.dispatcher = netsvc.Dispatcher() diff --git a/trytond/tools/misc.py b/trytond/tools/misc.py index e7fe6941ec..56da2906f2 100644 --- a/trytond/tools/misc.py +++ b/trytond/tools/misc.py @@ -64,7 +64,18 @@ def exec_command_pipe(name, *args): def file_open(name, mode="r", subdir='modules'): """Open a file from the root dir, using a subdir folder.""" + from trytond.modules import EGG_MODULES root_path = os.path.dirname(os.path.dirname(__file__)) + + name3 = False + if subdir == 'modules': + module_name = name.split(os.sep)[0] + if module_name in EGG_MODULES: + ep = EGG_MODULES[module_name] + mod_path = os.path.join(ep.dist.location, + *ep.module_name.split('.')[:-1]) + name3 = os.path.join(mod_path, name) + if subdir: if subdir == 'modules'\ and (name.startswith('ir' + os.sep) \ @@ -97,7 +108,7 @@ def file_open(name, mode="r", subdir='modules'): os.sep, '/'))) except: name2 = os.path.normpath(os.path.join(head + '.zip', zipname)) - for i in (name2, name): + for i in (name2, name, name3): if i and os.path.isfile(i): return file(i, mode)