From d348a0de79139db57e5d736e36b44ef7fa35d494 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 9 Jan 2012 13:52:43 +0100 Subject: [PATCH] [IMP] import hook: moved to a proper location (openerp.modules.module instead of openerp-server). bzr revid: vmt@openerp.com-20120109125243-qhtr070dvtc3akb5 --- openerp-server | 84 ------------------------------------- openerp/modules/module.py | 87 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 85 deletions(-) diff --git a/openerp-server b/openerp-server index c44e6909687..87e75a5cf7b 100755 --- a/openerp-server +++ b/openerp-server @@ -217,90 +217,6 @@ if __name__ == "__main__": check_root_user() openerp.tools.config.parse_config(sys.argv[1:]) - - class ImportHook(object): - """ - Import hook to load OpenERP addons from multiple paths. - - OpenERP implements its own import-hook to load its addons. OpenERP - addons are Python modules. Originally, they were each living in their - own top-level namespace, e.g. the sale module, or the hr module. For - backward compatibility, `import ` is still supported. Now they - are living in `openerp.addons`. The good way to import such modules is - thus `import openerp.addons.module`. - - For backward compatibility, loading an addons puts it in `sys.modules` - under both the legacy (short) name, and the new (longer) name. This - ensures that - import hr - import openerp.addons.hr - loads the hr addons only once. - - When an OpenERP addons name clashes with some other installed Python - module (for instance this is the case of the `resource` addons), - obtaining the OpenERP addons is only possible with the long name. The - short name will give the expected Python module. - """ - - def find_module(self, module_name, package_path): - module_parts = module_name.split('.') - if len(module_parts) == 3 and module_name.startswith('openerp.addons.'): - return self # We act as a loader too. - - # TODO list of loadable modules can be cached instead of always - # calling get_module_path(). - if len(module_parts) == 1 and \ - openerp.modules.module.get_module_path(module_parts[0], - display_warning=False): - try: - # Check if the bare module name clashes with another module. - f, path, descr = imp.find_module(module_parts[0]) - logger = logging.getLogger('init') - logger.warning(""" - Ambiguous import: the OpenERP module `%s` is shadowed by another - module (available at %s). - To import it, use `import openerp.addons..`.""" % (module_name, path)) - return - except ImportError, e: - # Using `import ` instead of - # `import openerp.addons.` is ugly but not harmful - # and kept for backward compatibility. - return self # We act as a loader too. - - def load_module(self, module_name): - - module_parts = module_name.split('.') - if len(module_parts) == 3 and module_name.startswith('openerp.addons.'): - module_part = module_parts[2] - if module_name in sys.modules: - return sys.modules[module_name] - - if len(module_parts) == 1: - module_part = module_parts[0] - if module_part in sys.modules: - return sys.modules[module_part] - - try: - # Check if the bare module name shadows another module. - f, path, descr = imp.find_module(module_part) - is_shadowing = True - except ImportError, e: - # Using `import ` instead of - # `import openerp.addons.` is ugly but not harmful - # and kept for backward compatibility. - is_shadowing = False - - # Note: we don't support circular import. - f, path, descr = imp.find_module(module_part, openerp.modules.module.ad_paths) - mod = imp.load_module(module_name, f, path, descr) - if not is_shadowing: - sys.modules[module_part] = mod - sys.modules['openerp.addons.' + module_part] = mod - return mod - - openerp.modules.module.initialize_sys_path() - sys.meta_path.append(ImportHook()) - check_postgres_user() openerp.netsvc.init_logger() report_configuration() diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 5c50384c2bc..1e46d3c8478 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -56,6 +56,91 @@ loaded = [] logger = netsvc.Logger() +class AddonsImportHook(object): + """ + Import hook to load OpenERP addons from multiple paths. + + OpenERP implements its own import-hook to load its addons. OpenERP + addons are Python modules. Originally, they were each living in their + own top-level namespace, e.g. the sale module, or the hr module. For + backward compatibility, `import ` is still supported. Now they + are living in `openerp.addons`. The good way to import such modules is + thus `import openerp.addons.module`. + + For backward compatibility, loading an addons puts it in `sys.modules` + under both the legacy (short) name, and the new (longer) name. This + ensures that + import hr + import openerp.addons.hr + loads the hr addons only once. + + When an OpenERP addons name clashes with some other installed Python + module (for instance this is the case of the `resource` addons), + obtaining the OpenERP addons is only possible with the long name. The + short name will give the expected Python module. + + Instead of relying on some addons path, an alternative approach would be + to use pkg_resources entry points from already installed Python libraries + (and install our addons as such). Even when implemented, we would still + have to support the addons path approach for backward compatibility. + """ + + def find_module(self, module_name, package_path): + module_parts = module_name.split('.') + if len(module_parts) == 3 and module_name.startswith('openerp.addons.'): + return self # We act as a loader too. + + # TODO list of loadable modules can be cached instead of always + # calling get_module_path(). + if len(module_parts) == 1 and \ + get_module_path(module_parts[0], + display_warning=False): + try: + # Check if the bare module name clashes with another module. + f, path, descr = imp.find_module(module_parts[0]) + logger = logging.getLogger('init') + logger.warning(""" +Ambiguous import: the OpenERP module `%s` is shadowed by another +module (available at %s). +To import it, use `import openerp.addons..`.""" % (module_name, path)) + return + except ImportError, e: + # Using `import ` instead of + # `import openerp.addons.` is ugly but not harmful + # and kept for backward compatibility. + return self # We act as a loader too. + + def load_module(self, module_name): + + module_parts = module_name.split('.') + if len(module_parts) == 3 and module_name.startswith('openerp.addons.'): + module_part = module_parts[2] + if module_name in sys.modules: + return sys.modules[module_name] + + if len(module_parts) == 1: + module_part = module_parts[0] + if module_part in sys.modules: + return sys.modules[module_part] + + try: + # Check if the bare module name shadows another module. + f, path, descr = imp.find_module(module_part) + is_shadowing = True + except ImportError, e: + # Using `import ` instead of + # `import openerp.addons.` is ugly but not harmful + # and kept for backward compatibility. + is_shadowing = False + + # Note: we don't support circular import. + f, path, descr = imp.find_module(module_part, ad_paths) + mod = imp.load_module(module_name, f, path, descr) + if not is_shadowing: + sys.modules[module_part] = mod + sys.modules['openerp.addons.' + module_part] = mod + return mod + def initialize_sys_path(): """ Add all addons paths in sys.path. @@ -68,7 +153,7 @@ def initialize_sys_path(): ad_paths = map(lambda m: os.path.abspath(tools.ustr(m.strip())), tools.config['addons_path'].split(',')) ad_paths.append(_ad) # for get_module_path - + sys.meta_path.append(AddonsImportHook()) def get_module_path(module, downloaded=False, display_warning=True): """Return the path of the given module.