[Python-checkins] cpython (2.7): Adding regression test for issue6727

jason.coombs python-checkins at python.org
Thu Mar 8 15:40:46 CET 2012


http://hg.python.org/cpython/rev/92f4d4eebed1
changeset:   75493:92f4d4eebed1
branch:      2.7
user:        Jason R. Coombs <jaraco at jaraco.com>
date:        Sun Jan 15 11:45:27 2012 -0500
summary:
  Adding regression test for issue6727

files:
  Lib/test/test_import.py |  118 +++++++++++++++++++++++++++-
  1 files changed, 116 insertions(+), 2 deletions(-)


diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -7,9 +7,11 @@
 import stat
 import sys
 import unittest
+import textwrap
+import shutil
+
 from test.test_support import (unlink, TESTFN, unload, run_unittest, rmtree,
                                is_jython, check_warnings, EnvironmentVarGuard)
-import textwrap
 from test import script_helper
 
 def remove_files(name):
@@ -488,8 +490,120 @@
                       "implicit absolute import")
 
 
+class TestSymbolicallyLinkedPackage(unittest.TestCase):
+    package_name = 'sample'
+
+    def setUp(self):
+        if os.path.exists('sample-tagged'): shutil.rmtree('sample-tagged')
+        self.orig_sys_path = sys.path[:]
+
+        symlink = getattr(os, 'symlink', None) or self._symlink_win32
+
+        # create a sample package; imagine you have a package with a tag and
+        #  you want to symbolically link it from its untagged name.
+        os.mkdir(self.tagged)
+        init_file = os.path.join(self.tagged, '__init__.py')
+        open(init_file, 'w').close()
+        assert os.path.exists(init_file)
+
+        # now create a symlink to the tagged package
+        # sample -> sample-tagged
+        symlink(self.tagged, self.package_name)
+
+        assert os.path.isdir(self.package_name)
+        assert os.path.isfile(os.path.join(self.package_name, '__init__.py'))
+
+    @property
+    def tagged(self):
+        return self.package_name + '-tagged'
+
+    @classmethod
+    def _symlink_win32(cls, target, link, target_is_directory=False):
+        """
+        Ctypes symlink implementation since Python doesn't support
+        symlinks in windows yet. Borrowed from jaraco.windows project.
+        """
+        import ctypes.wintypes
+        CreateSymbolicLink = ctypes.windll.kernel32.CreateSymbolicLinkW
+        CreateSymbolicLink.argtypes = (
+            ctypes.wintypes.LPWSTR,
+            ctypes.wintypes.LPWSTR,
+            ctypes.wintypes.DWORD,
+            )
+        CreateSymbolicLink.restype = ctypes.wintypes.BOOLEAN
+
+        def format_system_message(errno):
+            """
+            Call FormatMessage with a system error number to retrieve
+            the descriptive error message.
+            """
+            # first some flags used by FormatMessageW
+            ALLOCATE_BUFFER = 0x100
+            ARGUMENT_ARRAY = 0x2000
+            FROM_HMODULE = 0x800
+            FROM_STRING = 0x400
+            FROM_SYSTEM = 0x1000
+            IGNORE_INSERTS = 0x200
+
+            # Let FormatMessageW allocate the buffer (we'll free it below)
+            # Also, let it know we want a system error message.
+            flags = ALLOCATE_BUFFER | FROM_SYSTEM
+            source = None
+            message_id = errno
+            language_id = 0
+            result_buffer = ctypes.wintypes.LPWSTR()
+            buffer_size = 0
+            arguments = None
+            bytes = ctypes.windll.kernel32.FormatMessageW(
+                flags,
+                source,
+                message_id,
+                language_id,
+                ctypes.byref(result_buffer),
+                buffer_size,
+                arguments,
+                )
+            # note the following will cause an infinite loop if GetLastError
+            #  repeatedly returns an error that cannot be formatted, although
+            #  this should not happen.
+            handle_nonzero_success(bytes)
+            message = result_buffer.value
+            ctypes.windll.kernel32.LocalFree(result_buffer)
+            return message
+
+        def handle_nonzero_success(result):
+            if result == 0:
+                value = ctypes.windll.kernel32.GetLastError()
+                strerror = format_system_message(value)
+                raise WindowsError(value, strerror)
+
+        target_is_directory = target_is_directory or os.path.isdir(target)
+        handle_nonzero_success(CreateSymbolicLink(link, target, target_is_directory))
+
+    # regression test for issue6727
+    @unittest.skipUnless(
+        not hasattr(sys, 'getwindowsversion')
+        or sys.getwindowsversion() >= (6,0),
+        "Windows Vista or later required")
+    def test_symlinked_dir_importable(self):
+        # make sure sample can only be imported from the current directory.
+        sys.path[:] = ['.']
+
+        # and try to import the package
+        pkg = __import__(self.package_name)
+
+    def tearDown(self):
+        # now cleanup
+        if os.path.exists(self.package_name):
+            os.rmdir(self.package_name)
+        if os.path.exists(self.tagged):
+            shutil.rmtree(self.tagged)
+        sys.path[:] = self.orig_sys_path
+
+
 def test_main(verbose=None):
-    run_unittest(ImportTests, PycRewritingTests, PathsTests, RelativeImportTests)
+    run_unittest(ImportTests, PycRewritingTests, PathsTests,
+        RelativeImportTests, TestSymbolicallyLinkedPackage)
 
 if __name__ == '__main__':
     # Test needs to be a package, so we can do relative imports.

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list