Adding regression test for issue6727
This commit is contained in:
parent
0737b7281e
commit
4a24283272
|
@ -7,9 +7,11 @@ import random
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
import textwrap
|
||||||
|
import shutil
|
||||||
|
|
||||||
from test.test_support import (unlink, TESTFN, unload, run_unittest, rmtree,
|
from test.test_support import (unlink, TESTFN, unload, run_unittest, rmtree,
|
||||||
is_jython, check_warnings, EnvironmentVarGuard)
|
is_jython, check_warnings, EnvironmentVarGuard)
|
||||||
import textwrap
|
|
||||||
from test import script_helper
|
from test import script_helper
|
||||||
|
|
||||||
def remove_files(name):
|
def remove_files(name):
|
||||||
|
@ -488,8 +490,120 @@ class RelativeImportTests(unittest.TestCase):
|
||||||
"implicit absolute import")
|
"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):
|
def test_main(verbose=None):
|
||||||
run_unittest(ImportTests, PycRewritingTests, PathsTests, RelativeImportTests)
|
run_unittest(ImportTests, PycRewritingTests, PathsTests,
|
||||||
|
RelativeImportTests, TestSymbolicallyLinkedPackage)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Test needs to be a package, so we can do relative imports.
|
# Test needs to be a package, so we can do relative imports.
|
||||||
|
|
Loading…
Reference in New Issue