From 64ec5f36dfaaf100a7fe802065fce3f288746846 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 9 Jan 2012 09:12:06 +0100 Subject: [PATCH 1/7] [IMP] modules: began to replace sys.path appending with an import hook. bzr revid: vmt@openerp.com-20120109081206-p10yack8lhip11gt --- openerp-server | 53 +++++++++++++++++++++++++++++++++++++++ openerp/modules/module.py | 23 +---------------- 2 files changed, 54 insertions(+), 22 deletions(-) diff --git a/openerp-server b/openerp-server index 71a52d5f06b..9a4a04f2970 100755 --- a/openerp-server +++ b/openerp-server @@ -42,6 +42,9 @@ import openerp __author__ = openerp.release.author __version__ = openerp.release.version +import sys +import imp + def check_root_user(): """ Exit if the process's user is 'root' (on POSIX system).""" if os.name == 'posix': @@ -213,6 +216,56 @@ if __name__ == "__main__": check_root_user() openerp.tools.config.parse_config(sys.argv[1:]) + + + class ImportHook(object): + + 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]): + 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 clashes with another module. + f, path, descr = imp.find_module(module_part) + print "Warning: ambiguous import:", module_name, f, path, descr + except ImportError, e: + # Using `import openerp.addons.` instead of + # `import ` is ugly but not harmful. + pass + + f, path, descr = imp.find_module(module_part, openerp.modules.module.ad_paths) + mod = imp.load_module(module_name, f, path, descr) + 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()) + + import openerp.addons.hr + print sys.modules.get('openerp.addons.hr') + print sys.modules.get('hr') + check_postgres_user() openerp.netsvc.init_logger() report_configuration() diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 7f934275894..2282067c3b6 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -63,21 +63,11 @@ def initialize_sys_path(): not in the PYTHONPATH. """ global ad_paths - if ad_paths: return ad_paths = map(lambda m: os.path.abspath(tools.ustr(m.strip())), tools.config['addons_path'].split(',')) - - sys.path.insert(1, _ad) - - ad_cnt=1 - for adp in ad_paths: - if adp != _ad: - sys.path.insert(ad_cnt, adp) - ad_cnt+=1 - - ad_paths.append(_ad) # for get_module_path + ad_paths.append(_ad) # for get_module_path def get_module_path(module, downloaded=False): @@ -298,17 +288,6 @@ def init_module_models(cr, module_name, obj_list): t[1](cr, *t[2]) cr.commit() -# Import hook to write a addon m in both sys.modules['m'] and -# sys.modules['openerp.addons.m']. Otherwise it could be loaded twice -# if imported twice using different names. -#class MyImportHook(object): -# def find_module(self, module_name, package_path): -# print ">>>", module_name, package_path -# def load_module(self, module_name): -# raise ImportError("Restricted") - -#sys.meta_path.append(MyImportHook()) - def register_module_classes(m): """ Register module named m, if not already registered. From e50025945aa7ba328bed87db5a69fcea411d19e6 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 9 Jan 2012 10:03:33 +0100 Subject: [PATCH 2/7] [FIX] modules: removed temporary line/print. bzr revid: vmt@openerp.com-20120109090333-8ptsvj3yokjd59rm --- openerp-server | 4 ---- 1 file changed, 4 deletions(-) diff --git a/openerp-server b/openerp-server index 9a4a04f2970..8d710141500 100755 --- a/openerp-server +++ b/openerp-server @@ -262,10 +262,6 @@ if __name__ == "__main__": openerp.modules.module.initialize_sys_path() sys.meta_path.append(ImportHook()) - import openerp.addons.hr - print sys.modules.get('openerp.addons.hr') - print sys.modules.get('hr') - check_postgres_user() openerp.netsvc.init_logger() report_configuration() From f24a29717ebf506e310cca40638db6ccdf17d4b6 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 9 Jan 2012 11:16:47 +0100 Subject: [PATCH 3/7] [FIX] orm: correctly set the module name on the model, even when imported with `import openerp.modules.`. bzr revid: vmt@openerp.com-20120109101647-4hvy3n6eifzeozzq --- openerp-server | 18 +++++++++++------- openerp/addons/__init__.py | 6 +++--- openerp/modules/module.py | 5 +++-- openerp/osv/orm.py | 11 ++++++++++- openerp/tools/config.py | 3 --- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/openerp-server b/openerp-server index 8d710141500..641bc7e97e2 100755 --- a/openerp-server +++ b/openerp-server @@ -222,19 +222,20 @@ if __name__ == "__main__": def find_module(self, module_name, package_path): module_parts = module_name.split('.') - if len(module_parts) == 3 and module_name.startswith('openerp.addons.'): + if len(module_parts) == 3 and module_name.startswith('openerp.modules.'): 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]): + openerp.modules.module.get_module_path(module_parts[0], + display_warning=False): 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.'): + if len(module_parts) == 3 and module_name.startswith('openerp.modules.'): module_part = module_parts[2] if module_name in sys.modules: return sys.modules[module_name] @@ -247,16 +248,19 @@ if __name__ == "__main__": try: # Check if the bare module name clashes with another module. f, path, descr = imp.find_module(module_part) - print "Warning: ambiguous import:", module_name, f, path, descr + logger = logging.getLogger('init') + logger.warning(""" + Ambiguous import: the OpenERP module `%s` is shadowing another module + (available at %s).""" % (module_name, path)) except ImportError, e: - # Using `import openerp.addons.` instead of - # `import ` is ugly but not harmful. + # Using `import ` instead of + # `import openerp.modules.` is ugly but not harmful. pass f, path, descr = imp.find_module(module_part, openerp.modules.module.ad_paths) mod = imp.load_module(module_name, f, path, descr) sys.modules[module_part] = mod - sys.modules['openerp.addons.' + module_part] = mod + sys.modules['openerp.modules.' + module_part] = mod return mod openerp.modules.module.initialize_sys_path() diff --git a/openerp/addons/__init__.py b/openerp/addons/__init__.py index 1f863eca509..02a5c9aa0a7 100644 --- a/openerp/addons/__init__.py +++ b/openerp/addons/__init__.py @@ -25,9 +25,9 @@ This module serves to contain all OpenERP addons, across all configured addons paths. For the code to manage those addons, see openerp.modules. -Addons are made available here (i.e. under openerp.addons) after -openerp.tools.config.parse_config() is called (so that the addons paths -are known). +Addons are made available under `openerp.modules` after +openerp.tools.config.parse_config() is called (so that the addons paths are +known). This module also conveniently reexports some symbols from openerp.modules. Importing them from here is deprecated. diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 43b11b0d1b0..936c798767a 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -70,7 +70,7 @@ def initialize_sys_path(): ad_paths.append(_ad) # for get_module_path -def get_module_path(module, downloaded=False): +def get_module_path(module, downloaded=False, display_warning=True): """Return the path of the given module. Search the addons paths and return the first path where the given @@ -85,7 +85,8 @@ def get_module_path(module, downloaded=False): if downloaded: return opj(_ad, module) - logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: module not found' % (module,)) + if display_warning: + logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: module not found' % (module,)) return False diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 8236f096abf..23cc040af47 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -608,7 +608,16 @@ class MetaModel(type): super(MetaModel, self).__init__(name, bases, attrs) return - module_name = self.__module__.split('.')[0] + # The (OpenERP) module name can be in the `openerp.modules` namespace + # or not. For instance module `sale` can be imported as + # `openerp.modules.sale` (the good way) or `sale` (for backward + # compatibility). + module_parts = self.__module__.split('.') + if len(module_parts) > 2 and module_parts[0] == 'openerp' and \ + module_parts[1] == 'modules': + module_name = self.__module__.split('.')[2] + else: + module_name = self.__module__.split('.')[0] if not hasattr(self, '_module'): self._module = module_name diff --git a/openerp/tools/config.py b/openerp/tools/config.py index 00815ed2055..8c980447f52 100644 --- a/openerp/tools/config.py +++ b/openerp/tools/config.py @@ -461,9 +461,6 @@ class configmanager(object): if complete: openerp.modules.module.initialize_sys_path() openerp.modules.loading.open_openerp_namespace() - # openerp.addons.__path__.extend(openerp.conf.addons_paths) # This - # is not compatible with initialize_sys_path(): import crm and - # import openerp.addons.crm load twice the module. def _generate_pgpassfile(self): """ From 1560538f8a336e9e44c35bc8fd9b48b7bc2a2d82 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 9 Jan 2012 13:31:23 +0100 Subject: [PATCH 4/7] [IMP] module: use the `openerp.addons.` namespace to load addons. (openerp.modules will be changed in openerp.addons in the next commit). bzr revid: vmt@openerp.com-20120109123123-jt3canjbg0ozs05j --- openerp-server | 61 ++++++++++++++++++++++++++++++--------- openerp/modules/module.py | 2 +- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/openerp-server b/openerp-server index 641bc7e97e2..44ba179830d 100755 --- a/openerp-server +++ b/openerp-server @@ -219,6 +219,28 @@ if __name__ == "__main__": 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('.') @@ -230,7 +252,20 @@ if __name__ == "__main__": if len(module_parts) == 1 and \ openerp.modules.module.get_module_path(module_parts[0], display_warning=False): - return self # We act as a loader too. + 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.modules..`.""" % (module_name, path)) + return + except ImportError, e: + # Using `import ` instead of + # `import openerp.modules.` is ugly but not harmful + # and kept for backward compatibility. + return self # We act as a loader too. def load_module(self, module_name): @@ -245,21 +280,21 @@ if __name__ == "__main__": if module_part in sys.modules: return sys.modules[module_part] - try: - # Check if the bare module name clashes with another module. - f, path, descr = imp.find_module(module_part) - logger = logging.getLogger('init') - logger.warning(""" - Ambiguous import: the OpenERP module `%s` is shadowing another module - (available at %s).""" % (module_name, path)) - except ImportError, e: - # Using `import ` instead of - # `import openerp.modules.` is ugly but not harmful. - pass + 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.modules.` 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) - sys.modules[module_part] = mod + if not is_shadowing: + sys.modules[module_part] = mod sys.modules['openerp.modules.' + module_part] = mod return mod diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 936c798767a..a5c432722ea 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -314,7 +314,7 @@ def register_module_classes(m): try: zip_mod_path = mod_path + '.zip' if not os.path.isfile(zip_mod_path): - __import__(m) + __import__('openerp.modules.' + m) else: zimp = zipimport.zipimporter(zip_mod_path) zimp.load_module(m) From 455e47e5e83bbf70203f7513b876c420bd6abb06 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 9 Jan 2012 13:41:20 +0100 Subject: [PATCH 5/7] [IMP] openerp.addons: openerp.addons is used instead of openerp.modules as the namespace of the OpenERP addons. bzr revid: vmt@openerp.com-20120109124120-06gguu3lzxv49i3j --- openerp-server | 12 ++++++------ openerp/addons/__init__.py | 2 +- openerp/modules/module.py | 2 +- openerp/osv/orm.py | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/openerp-server b/openerp-server index 44ba179830d..c44e6909687 100755 --- a/openerp-server +++ b/openerp-server @@ -244,7 +244,7 @@ if __name__ == "__main__": def find_module(self, module_name, package_path): module_parts = module_name.split('.') - if len(module_parts) == 3 and module_name.startswith('openerp.modules.'): + 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 @@ -259,18 +259,18 @@ if __name__ == "__main__": logger.warning(""" Ambiguous import: the OpenERP module `%s` is shadowed by another module (available at %s). - To import it, use `import openerp.modules..`.""" % (module_name, path)) + To import it, use `import openerp.addons..`.""" % (module_name, path)) return except ImportError, e: # Using `import ` instead of - # `import openerp.modules.` is ugly but not harmful + # `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.modules.'): + 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] @@ -286,7 +286,7 @@ if __name__ == "__main__": is_shadowing = True except ImportError, e: # Using `import ` instead of - # `import openerp.modules.` is ugly but not harmful + # `import openerp.addons.` is ugly but not harmful # and kept for backward compatibility. is_shadowing = False @@ -295,7 +295,7 @@ if __name__ == "__main__": mod = imp.load_module(module_name, f, path, descr) if not is_shadowing: sys.modules[module_part] = mod - sys.modules['openerp.modules.' + module_part] = mod + sys.modules['openerp.addons.' + module_part] = mod return mod openerp.modules.module.initialize_sys_path() diff --git a/openerp/addons/__init__.py b/openerp/addons/__init__.py index 02a5c9aa0a7..9554e9bd850 100644 --- a/openerp/addons/__init__.py +++ b/openerp/addons/__init__.py @@ -25,7 +25,7 @@ This module serves to contain all OpenERP addons, across all configured addons paths. For the code to manage those addons, see openerp.modules. -Addons are made available under `openerp.modules` after +Addons are made available under `openerp.addons` after openerp.tools.config.parse_config() is called (so that the addons paths are known). diff --git a/openerp/modules/module.py b/openerp/modules/module.py index a5c432722ea..5c50384c2bc 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -314,7 +314,7 @@ def register_module_classes(m): try: zip_mod_path = mod_path + '.zip' if not os.path.isfile(zip_mod_path): - __import__('openerp.modules.' + m) + __import__('openerp.addons.' + m) else: zimp = zipimport.zipimporter(zip_mod_path) zimp.load_module(m) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 23cc040af47..05da35a5aeb 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -608,13 +608,13 @@ class MetaModel(type): super(MetaModel, self).__init__(name, bases, attrs) return - # The (OpenERP) module name can be in the `openerp.modules` namespace + # The (OpenERP) module name can be in the `openerp.addons` namespace # or not. For instance module `sale` can be imported as - # `openerp.modules.sale` (the good way) or `sale` (for backward + # `openerp.addons.sale` (the good way) or `sale` (for backward # compatibility). module_parts = self.__module__.split('.') if len(module_parts) > 2 and module_parts[0] == 'openerp' and \ - module_parts[1] == 'modules': + module_parts[1] == 'addons': module_name = self.__module__.split('.')[2] else: module_name = self.__module__.split('.')[0] From d348a0de79139db57e5d736e36b44ef7fa35d494 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Mon, 9 Jan 2012 13:52:43 +0100 Subject: [PATCH 6/7] [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. From 6c1ad196bf39563d62159ef1b988af39360849aa Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Tue, 10 Jan 2012 10:27:30 +0100 Subject: [PATCH 7/7] [IMP] openerp.modules: updated initialize_sys_path() docstring (although its name is now inaccurate). bzr revid: vmt@openerp.com-20120110092730-rqewzuo1wa5wy2q5 --- openerp/modules/module.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 1e46d3c8478..b82597d656d 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -142,10 +142,13 @@ To import it, use `import openerp.addons..`.""" % (module_name, path)) return mod def initialize_sys_path(): - """ Add all addons paths in sys.path. + """ + Setup an import-hook to be able to import OpenERP addons from the different + addons paths. - This ensures something like ``import crm`` works even if the addons are - not in the PYTHONPATH. + This ensures something like ``import crm`` (or even + ``import openerp.addons.crm``) works even if the addons are not in the + PYTHONPATH. """ global ad_paths if ad_paths: