[IMP] modules: began to replace sys.path appending with an import hook.
authorVo Minh Thu <vmt@openerp.com>
Mon, 9 Jan 2012 08:12:06 +0000 (09:12 +0100)
committerVo Minh Thu <vmt@openerp.com>
Mon, 9 Jan 2012 08:12:06 +0000 (09:12 +0100)
bzr revid: vmt@openerp.com-20120109081206-p10yack8lhip11gt

openerp-server
openerp/modules/module.py

index 71a52d5..9a4a04f 100755 (executable)
@@ -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.<module_name>` instead of
+                    # `import <module_name>` 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()
index 7f93427..2282067 100644 (file)
@@ -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.