blob: dbbe1570c9b3c39be101efc14ad3082fa866c863 [file] [log] [blame]
Vinay Sajip42211422012-05-26 20:36:12 +01001"""
2Test harness for the venv module.
Vinay Sajip7ded1f02012-05-26 03:45:29 +01003
Vinay Sajip42211422012-05-26 20:36:12 +01004Copyright (C) 2011-2012 Vinay Sajip.
Vinay Sajip28952442012-06-25 00:47:46 +01005Licensed to the PSF under a contributor agreement.
Vinay Sajip7ded1f02012-05-26 03:45:29 +01006"""
7
8import os
9import os.path
10import shutil
Vinay Sajip3874e542012-07-03 16:56:40 +010011import subprocess
Vinay Sajip7ded1f02012-05-26 03:45:29 +010012import sys
13import tempfile
14from test.support import (captured_stdout, captured_stderr, run_unittest,
15 can_symlink)
16import unittest
17import venv
18
19class BaseTest(unittest.TestCase):
20 """Base class for venv tests."""
21
22 def setUp(self):
Ned Deily045bd532012-07-13 15:48:04 -070023 self.env_dir = os.path.realpath(tempfile.mkdtemp())
Vinay Sajip7ded1f02012-05-26 03:45:29 +010024 if os.name == 'nt':
25 self.bindir = 'Scripts'
Vinay Sajip7ded1f02012-05-26 03:45:29 +010026 self.lib = ('Lib',)
27 self.include = 'Include'
Vinay Sajip7ded1f02012-05-26 03:45:29 +010028 else:
29 self.bindir = 'bin'
Vinay Sajip7ded1f02012-05-26 03:45:29 +010030 self.lib = ('lib', 'python%s' % sys.version[:3])
31 self.include = 'include'
Vinay Sajip28952442012-06-25 00:47:46 +010032 if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in os.environ:
33 executable = os.environ['__PYVENV_LAUNCHER__']
Vinay Sajip382a7c02012-05-28 16:34:47 +010034 else:
35 executable = sys.executable
36 self.exe = os.path.split(executable)[-1]
Vinay Sajip7ded1f02012-05-26 03:45:29 +010037
38 def tearDown(self):
39 shutil.rmtree(self.env_dir)
40
41 def run_with_capture(self, func, *args, **kwargs):
42 with captured_stdout() as output:
43 with captured_stderr() as error:
44 func(*args, **kwargs)
45 return output.getvalue(), error.getvalue()
46
47 def get_env_file(self, *args):
48 return os.path.join(self.env_dir, *args)
49
50 def get_text_file_contents(self, *args):
51 with open(self.get_env_file(*args), 'r') as f:
52 result = f.read()
53 return result
54
55class BasicTest(BaseTest):
56 """Test venv module functionality."""
57
Vinay Sajipb3b49cd2012-05-27 18:39:22 +010058 def isdir(self, *args):
59 fn = self.get_env_file(*args)
60 self.assertTrue(os.path.isdir(fn))
61
Vinay Sajip7ded1f02012-05-26 03:45:29 +010062 def test_defaults(self):
63 """
64 Test the create function with default arguments.
65 """
Vinay Sajip7ded1f02012-05-26 03:45:29 +010066 shutil.rmtree(self.env_dir)
67 self.run_with_capture(venv.create, self.env_dir)
Vinay Sajipb3b49cd2012-05-27 18:39:22 +010068 self.isdir(self.bindir)
69 self.isdir(self.include)
70 self.isdir(*self.lib)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010071 data = self.get_text_file_contents('pyvenv.cfg')
Vinay Sajip28952442012-06-25 00:47:46 +010072 if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__'
Vinay Sajip7ded1f02012-05-26 03:45:29 +010073 in os.environ):
Vinay Sajip28952442012-06-25 00:47:46 +010074 executable = os.environ['__PYVENV_LAUNCHER__']
Vinay Sajip7ded1f02012-05-26 03:45:29 +010075 else:
76 executable = sys.executable
77 path = os.path.dirname(executable)
78 self.assertIn('home = %s' % path, data)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010079 fn = self.get_env_file(self.bindir, self.exe)
Vinay Sajip7e203492012-05-27 17:30:09 +010080 if not os.path.exists(fn): # diagnostics for Windows buildbot failures
Vinay Sajipb3b49cd2012-05-27 18:39:22 +010081 bd = self.get_env_file(self.bindir)
82 print('Contents of %r:' % bd)
83 print(' %r' % os.listdir(bd))
Vinay Sajip7e203492012-05-27 17:30:09 +010084 self.assertTrue(os.path.exists(fn), 'File %r should exist.' % fn)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010085
Vinay Sajip509d87d2012-07-15 16:12:54 +010086 @unittest.skipIf(sys.prefix != sys.base_prefix, 'Test not appropriate '
87 'in a venv')
Vinay Sajip3874e542012-07-03 16:56:40 +010088 def test_prefixes(self):
89 """
90 Test that the prefix values are as expected.
91 """
92 #check our prefixes
93 self.assertEqual(sys.base_prefix, sys.prefix)
94 self.assertEqual(sys.base_exec_prefix, sys.exec_prefix)
95
96 # check a venv's prefixes
97 shutil.rmtree(self.env_dir)
98 self.run_with_capture(venv.create, self.env_dir)
99 envpy = os.path.join(self.env_dir, self.bindir, self.exe)
100 cmd = [envpy, '-c', None]
101 for prefix, expected in (
102 ('prefix', self.env_dir),
103 ('prefix', self.env_dir),
104 ('base_prefix', sys.prefix),
105 ('base_exec_prefix', sys.exec_prefix)):
106 cmd[2] = 'import sys; print(sys.%s)' % prefix
107 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
108 stderr=subprocess.PIPE)
109 out, err = p.communicate()
Antoine Pitrou9c92a692012-08-05 00:33:10 +0200110 self.assertEqual(out.strip(), expected.encode())
Vinay Sajip3874e542012-07-03 16:56:40 +0100111
Vinay Sajipbd40d3e2012-10-11 17:22:45 +0100112 if sys.platform == 'win32':
113 ENV_SUBDIRS = (
114 ('Scripts',),
115 ('Include',),
116 ('Lib',),
117 ('Lib', 'site-packages'),
118 )
119 else:
120 ENV_SUBDIRS = (
121 ('bin',),
122 ('include',),
123 ('lib',),
124 ('lib', 'python%d.%d' % sys.version_info[:2]),
125 ('lib', 'python%d.%d' % sys.version_info[:2], 'site-packages'),
126 )
127
128 def create_contents(self, paths, filename):
129 """
130 Create some files in the environment which are unrelated
131 to the virtual environment.
132 """
133 for subdirs in paths:
134 d = os.path.join(self.env_dir, *subdirs)
135 os.mkdir(d)
136 fn = os.path.join(d, filename)
137 with open(fn, 'wb') as f:
138 f.write(b'Still here?')
139
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100140 def test_overwrite_existing(self):
141 """
Vinay Sajipbd40d3e2012-10-11 17:22:45 +0100142 Test creating environment in an existing directory.
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100143 """
Vinay Sajipbd40d3e2012-10-11 17:22:45 +0100144 self.create_contents(self.ENV_SUBDIRS, 'foo')
145 venv.create(self.env_dir)
146 for subdirs in self.ENV_SUBDIRS:
147 fn = os.path.join(self.env_dir, *(subdirs + ('foo',)))
148 self.assertTrue(os.path.exists(fn))
149 with open(fn, 'rb') as f:
150 self.assertEqual(f.read(), b'Still here?')
151
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100152 builder = venv.EnvBuilder(clear=True)
153 builder.create(self.env_dir)
Vinay Sajipbd40d3e2012-10-11 17:22:45 +0100154 for subdirs in self.ENV_SUBDIRS:
155 fn = os.path.join(self.env_dir, *(subdirs + ('foo',)))
156 self.assertFalse(os.path.exists(fn))
157
158 def clear_directory(self, path):
159 for fn in os.listdir(path):
160 fn = os.path.join(path, fn)
161 if os.path.islink(fn) or os.path.isfile(fn):
162 os.remove(fn)
163 elif os.path.isdir(fn):
164 shutil.rmtree(fn)
165
166 def test_unoverwritable_fails(self):
167 #create a file clashing with directories in the env dir
168 for paths in self.ENV_SUBDIRS[:3]:
169 fn = os.path.join(self.env_dir, *paths)
170 with open(fn, 'wb') as f:
171 f.write(b'')
172 self.assertRaises((ValueError, OSError), venv.create, self.env_dir)
173 self.clear_directory(self.env_dir)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100174
Vinay Sajipb3b49cd2012-05-27 18:39:22 +0100175 def test_upgrade(self):
176 """
177 Test upgrading an existing environment directory.
178 """
179 builder = venv.EnvBuilder(upgrade=True)
180 self.run_with_capture(builder.create, self.env_dir)
181 self.isdir(self.bindir)
182 self.isdir(self.include)
183 self.isdir(*self.lib)
184 fn = self.get_env_file(self.bindir, self.exe)
185 if not os.path.exists(fn): # diagnostics for Windows buildbot failures
186 bd = self.get_env_file(self.bindir)
187 print('Contents of %r:' % bd)
188 print(' %r' % os.listdir(bd))
189 self.assertTrue(os.path.exists(fn), 'File %r should exist.' % fn)
190
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100191 def test_isolation(self):
192 """
193 Test isolation from system site-packages
194 """
195 for ssp, s in ((True, 'true'), (False, 'false')):
196 builder = venv.EnvBuilder(clear=True, system_site_packages=ssp)
197 builder.create(self.env_dir)
198 data = self.get_text_file_contents('pyvenv.cfg')
199 self.assertIn('include-system-site-packages = %s\n' % s, data)
200
201 @unittest.skipUnless(can_symlink(), 'Needs symlinks')
202 def test_symlinking(self):
203 """
204 Test symlinking works as expected
205 """
206 for usl in (False, True):
207 builder = venv.EnvBuilder(clear=True, symlinks=usl)
Vinay Sajip90db6612012-07-17 17:33:46 +0100208 builder.create(self.env_dir)
209 fn = self.get_env_file(self.bindir, self.exe)
210 # Don't test when False, because e.g. 'python' is always
211 # symlinked to 'python3.3' in the env, even when symlinking in
212 # general isn't wanted.
213 if usl:
214 self.assertTrue(os.path.islink(fn))
215
216 # If a venv is created from a source build and that venv is used to
217 # run the test, the pyvenv.cfg in the venv created in the test will
218 # point to the venv being used to run the test, and we lose the link
219 # to the source build - so Python can't initialise properly.
220 @unittest.skipIf(sys.prefix != sys.base_prefix, 'Test not appropriate '
221 'in a venv')
222 def test_executable(self):
223 """
224 Test that the sys.executable value is as expected.
225 """
226 shutil.rmtree(self.env_dir)
227 self.run_with_capture(venv.create, self.env_dir)
228 envpy = os.path.join(os.path.realpath(self.env_dir), self.bindir, self.exe)
229 cmd = [envpy, '-c', 'import sys; print(sys.executable)']
230 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
231 stderr=subprocess.PIPE)
232 out, err = p.communicate()
Antoine Pitrou9c92a692012-08-05 00:33:10 +0200233 self.assertEqual(out.strip(), envpy.encode())
Vinay Sajip90db6612012-07-17 17:33:46 +0100234
235 @unittest.skipUnless(can_symlink(), 'Needs symlinks')
236 def test_executable_symlinks(self):
237 """
238 Test that the sys.executable value is as expected.
239 """
240 shutil.rmtree(self.env_dir)
241 builder = venv.EnvBuilder(clear=True, symlinks=True)
242 builder.create(self.env_dir)
243 envpy = os.path.join(os.path.realpath(self.env_dir), self.bindir, self.exe)
244 cmd = [envpy, '-c', 'import sys; print(sys.executable)']
245 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
246 stderr=subprocess.PIPE)
247 out, err = p.communicate()
Antoine Pitrou9c92a692012-08-05 00:33:10 +0200248 self.assertEqual(out.strip(), envpy.encode())
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100249
250def test_main():
251 run_unittest(BasicTest)
252
253if __name__ == "__main__":
254 test_main()