environment.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import os
  2. import zipfile
  3. import sys
  4. import tempfile
  5. import unittest
  6. import shutil
  7. import stat
  8. import unicodedata
  9. from subprocess import Popen as _Popen, PIPE as _PIPE
  10. def _extract(self, member, path=None, pwd=None):
  11. """for zipfile py2.5 borrowed from cpython"""
  12. if not isinstance(member, zipfile.ZipInfo):
  13. member = self.getinfo(member)
  14. if path is None:
  15. path = os.getcwd()
  16. return _extract_member(self, member, path, pwd)
  17. def _extract_from_zip(self, name, dest_path):
  18. dest_file = open(dest_path, 'wb')
  19. try:
  20. dest_file.write(self.read(name))
  21. finally:
  22. dest_file.close()
  23. def _extract_member(self, member, targetpath, pwd):
  24. """for zipfile py2.5 borrowed from cpython"""
  25. # build the destination pathname, replacing
  26. # forward slashes to platform specific separators.
  27. # Strip trailing path separator, unless it represents the root.
  28. if (targetpath[-1:] in (os.path.sep, os.path.altsep)
  29. and len(os.path.splitdrive(targetpath)[1]) > 1):
  30. targetpath = targetpath[:-1]
  31. # don't include leading "/" from file name if present
  32. if member.filename[0] == '/':
  33. targetpath = os.path.join(targetpath, member.filename[1:])
  34. else:
  35. targetpath = os.path.join(targetpath, member.filename)
  36. targetpath = os.path.normpath(targetpath)
  37. # Create all upper directories if necessary.
  38. upperdirs = os.path.dirname(targetpath)
  39. if upperdirs and not os.path.exists(upperdirs):
  40. os.makedirs(upperdirs)
  41. if member.filename[-1] == '/':
  42. if not os.path.isdir(targetpath):
  43. os.mkdir(targetpath)
  44. return targetpath
  45. _extract_from_zip(self, member.filename, targetpath)
  46. return targetpath
  47. def _remove_dir(target):
  48. #on windows this seems to a problem
  49. for dir_path, dirs, files in os.walk(target):
  50. os.chmod(dir_path, stat.S_IWRITE)
  51. for filename in files:
  52. os.chmod(os.path.join(dir_path, filename), stat.S_IWRITE)
  53. shutil.rmtree(target)
  54. class ZippedEnvironment(unittest.TestCase):
  55. datafile = None
  56. dataname = None
  57. old_cwd = None
  58. def setUp(self):
  59. if self.datafile is None or self.dataname is None:
  60. return
  61. if not os.path.isfile(self.datafile):
  62. self.old_cwd = None
  63. return
  64. self.old_cwd = os.getcwd()
  65. self.temp_dir = tempfile.mkdtemp()
  66. zip_file, source, target = [None, None, None]
  67. try:
  68. zip_file = zipfile.ZipFile(self.datafile)
  69. for files in zip_file.namelist():
  70. _extract(zip_file, files, self.temp_dir)
  71. finally:
  72. if zip_file:
  73. zip_file.close()
  74. del zip_file
  75. os.chdir(os.path.join(self.temp_dir, self.dataname))
  76. def tearDown(self):
  77. #Assume setUp was never completed
  78. if self.dataname is None or self.datafile is None:
  79. return
  80. try:
  81. if self.old_cwd:
  82. os.chdir(self.old_cwd)
  83. _remove_dir(self.temp_dir)
  84. except OSError:
  85. #sigh?
  86. pass
  87. def _which_dirs(cmd):
  88. result = set()
  89. for path in os.environ.get('PATH', '').split(os.pathsep):
  90. filename = os.path.join(path, cmd)
  91. if os.access(filename, os.X_OK):
  92. result.add(path)
  93. return result
  94. def run_setup_py(cmd, pypath=None, path=None,
  95. data_stream=0, env=None):
  96. """
  97. Execution command for tests, separate from those used by the
  98. code directly to prevent accidental behavior issues
  99. """
  100. if env is None:
  101. env = dict()
  102. for envname in os.environ:
  103. env[envname] = os.environ[envname]
  104. #override the python path if needed
  105. if pypath is not None:
  106. env["PYTHONPATH"] = pypath
  107. #overide the execution path if needed
  108. if path is not None:
  109. env["PATH"] = path
  110. if not env.get("PATH", ""):
  111. env["PATH"] = _which_dirs("tar").union(_which_dirs("gzip"))
  112. env["PATH"] = os.pathsep.join(env["PATH"])
  113. cmd = [sys.executable, "setup.py"] + list(cmd)
  114. #regarding the shell argument, see: http://bugs.python.org/issue8557
  115. try:
  116. proc = _Popen(cmd, stdout=_PIPE, stderr=_PIPE,
  117. shell=(sys.platform == 'win32'), env=env)
  118. data = proc.communicate()[data_stream]
  119. except OSError:
  120. return 1, ''
  121. #decode the console string if needed
  122. if hasattr(data, "decode"):
  123. data = data.decode() # should use the preffered encoding
  124. data = unicodedata.normalize('NFC', data)
  125. #communciate calls wait()
  126. return proc.returncode, data