diff runtime/doc/if_pyth.txt @ 4851:96e154e825a7 v7.3.1172

updated for version 7.3.1172 Problem: Python 2: loading modules doesn't work well. Solution: Fix the code. Add more tests. (ZyX)
author Bram Moolenaar <bram@vim.org>
date Wed, 12 Jun 2013 14:20:36 +0200
parents 70b1178dec79
children 52850ef928f8
line wrap: on
line diff
--- a/runtime/doc/if_pyth.txt
+++ b/runtime/doc/if_pyth.txt
@@ -315,52 +315,53 @@ vim.path_hooks in sys.path_hooks python 
 {rtp}/python2 (or python3) and {rtp}/pythonx (for both python versions) for 
 each {rtp} found in 'runtimepath'.
 
-Implementation for python 2 is the following: usual importing code with empty 
-lists in place of sys.path_hooks and sys.meta_path. Code is similar to the 
-below, but written in C: >
+Implementation for python 2 is similar to the following, but written in C: >
 
-    # Assuming vim variable is already accessible and is set to the current 
-    # module
+    from imp import find_module, load_module
+    import vim
     import sys
 
-    def find_module(fullname):
-        return vim
+    class VimModuleLoader(object):
+        def __init__(self, module):
+            self.module = module
 
-    def load_module(fullname):
-        # see vim._get_paths below
-        new_path = _get_paths()
+        def load_module(self, fullname, path=None):
+            return self.module
 
-        try:         old_path = sys.path
-        except: pass
-        try:         old_meta_path = sys.meta_path
-        except: pass
-        try:         old_path_hooks = sys.path_hooks
-        except: pass
-
-        sys.meta_path = []
-        sys.path_hooks = sys.meta_path
-        sys.path = new_path
+    def _find_module(fullname, oldtail, path):
+        idx = oldtail.find('.')
+        if idx > 0:
+            name = oldtail[:idx]
+            tail = oldtail[idx+1:]
+            fmr = find_module(name, path)
+            module = load_module(fullname[:-len(oldtail)] + name, *fmr)
+            return _find_module(fullname, tail, module.__path__)
+        else:
+            fmr = find_module(fullname, path)
+            return load_module(fullname, *fmr)
 
-        try:
-            exec ('import ' + fullname + ' as m')  # No actual exec in C code
-            return m
-        finally:
-            e = None
-            try:                        sys.path = old_path
-            except Exception as e: pass
-            try:                        sys.meta_path = old_meta_path
-            except Exception as e: pass
-            try:                        sys.path_hooks = old_path_hooks
-            except Exception as e: pass
-            if e:
-                raise e
+    # It uses vim module itself in place of VimPathFinder class: it does not 
+    # matter for python which object has find_module function attached to as 
+    # an attribute.
+    class VimPathFinder(object):
+        def find_module(cls, fullname, path=None):
+            try:
+                return VimModuleLoader(_find_module(fullname, fullname, path or vim._get_paths()))
+            except ImportError:
+                return None
+        find_module = classmethod(find_module)
 
-    def path_hook(d):
-        if d == VIM_SPECIAL_PATH:
-            return vim
-        raise ImportError
+        def load_module(cls, fullname, path=None):
+            return _find_module(fullname, fullname, path or vim._get_paths())
+        load_module = classmethod(load_module)
 
-    sys.path_hooks.append(path_hook)
+    def hook(path):
+        if path == vim.VIM_SPECIAL_PATH:
+            return VimPathFinder
+        else:
+            raise ImportError
+
+    sys.path_hooks.append(hook)
 
 Implementation for python 3 is cleaner: code is similar to the following, but, 
 again, written in C: >
@@ -395,14 +396,13 @@ vim.VIM_SPECIAL_PATH					*python-VIM_SPE
 	Note: you must not use value of this constant directly, always use 
 	      vim.VIM_SPECIAL_PATH object.
 
-vim.load_module(name)					*python-load_module*
 vim.find_module(...)					*python-find_module*
 vim.path_hook(path)					*python-path_hook*
 	Methods or objects used to implement path loading as described above. 
 	You should not be using any of these directly except for vim.path_hook 
 	in case you need to do something with sys.meta_path. It is not 
 	guaranteed that any of the objects will exist in the future vim 
-	versions. In fact, load_module and find_module methods do not exists 
+	versions. In fact, find_module methods do not exists 
 	in python3.
 
 vim._get_paths						*python-_get_paths*