]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | """Tests for 'site'.\r |
2 | \r | |
3 | Tests assume the initial paths in sys.path once the interpreter has begun\r | |
4 | executing have not been removed.\r | |
5 | \r | |
6 | """\r | |
7 | import unittest\r | |
8 | from test.test_support import run_unittest, TESTFN, EnvironmentVarGuard\r | |
9 | from test.test_support import captured_output\r | |
10 | import __builtin__\r | |
11 | import os\r | |
12 | import sys\r | |
13 | import re\r | |
14 | import encodings\r | |
15 | import subprocess\r | |
16 | import sysconfig\r | |
17 | from copy import copy\r | |
18 | \r | |
19 | # Need to make sure to not import 'site' if someone specified ``-S`` at the\r | |
20 | # command-line. Detect this by just making sure 'site' has not been imported\r | |
21 | # already.\r | |
22 | if "site" in sys.modules:\r | |
23 | import site\r | |
24 | else:\r | |
25 | raise unittest.SkipTest("importation of site.py suppressed")\r | |
26 | \r | |
27 | if not os.path.isdir(site.USER_SITE):\r | |
28 | # need to add user site directory for tests\r | |
29 | os.makedirs(site.USER_SITE)\r | |
30 | site.addsitedir(site.USER_SITE)\r | |
31 | \r | |
32 | class HelperFunctionsTests(unittest.TestCase):\r | |
33 | """Tests for helper functions.\r | |
34 | \r | |
35 | The setting of the encoding (set using sys.setdefaultencoding) used by\r | |
36 | the Unicode implementation is not tested.\r | |
37 | \r | |
38 | """\r | |
39 | \r | |
40 | def setUp(self):\r | |
41 | """Save a copy of sys.path"""\r | |
42 | self.sys_path = sys.path[:]\r | |
43 | self.old_base = site.USER_BASE\r | |
44 | self.old_site = site.USER_SITE\r | |
45 | self.old_prefixes = site.PREFIXES\r | |
46 | self.old_vars = copy(sysconfig._CONFIG_VARS)\r | |
47 | \r | |
48 | def tearDown(self):\r | |
49 | """Restore sys.path"""\r | |
50 | sys.path[:] = self.sys_path\r | |
51 | site.USER_BASE = self.old_base\r | |
52 | site.USER_SITE = self.old_site\r | |
53 | site.PREFIXES = self.old_prefixes\r | |
54 | sysconfig._CONFIG_VARS = self.old_vars\r | |
55 | \r | |
56 | def test_makepath(self):\r | |
57 | # Test makepath() have an absolute path for its first return value\r | |
58 | # and a case-normalized version of the absolute path for its\r | |
59 | # second value.\r | |
60 | path_parts = ("Beginning", "End")\r | |
61 | original_dir = os.path.join(*path_parts)\r | |
62 | abs_dir, norm_dir = site.makepath(*path_parts)\r | |
63 | self.assertEqual(os.path.abspath(original_dir), abs_dir)\r | |
64 | if original_dir == os.path.normcase(original_dir):\r | |
65 | self.assertEqual(abs_dir, norm_dir)\r | |
66 | else:\r | |
67 | self.assertEqual(os.path.normcase(abs_dir), norm_dir)\r | |
68 | \r | |
69 | def test_init_pathinfo(self):\r | |
70 | dir_set = site._init_pathinfo()\r | |
71 | for entry in [site.makepath(path)[1] for path in sys.path\r | |
72 | if path and os.path.isdir(path)]:\r | |
73 | self.assertIn(entry, dir_set,\r | |
74 | "%s from sys.path not found in set returned "\r | |
75 | "by _init_pathinfo(): %s" % (entry, dir_set))\r | |
76 | \r | |
77 | def pth_file_tests(self, pth_file):\r | |
78 | """Contain common code for testing results of reading a .pth file"""\r | |
79 | self.assertIn(pth_file.imported, sys.modules,\r | |
80 | "%s not in sys.modules" % pth_file.imported)\r | |
81 | self.assertIn(site.makepath(pth_file.good_dir_path)[0], sys.path)\r | |
82 | self.assertFalse(os.path.exists(pth_file.bad_dir_path))\r | |
83 | \r | |
84 | def test_addpackage(self):\r | |
85 | # Make sure addpackage() imports if the line starts with 'import',\r | |
86 | # adds directories to sys.path for any line in the file that is not a\r | |
87 | # comment or import that is a valid directory name for where the .pth\r | |
88 | # file resides; invalid directories are not added\r | |
89 | pth_file = PthFile()\r | |
90 | pth_file.cleanup(prep=True) # to make sure that nothing is\r | |
91 | # pre-existing that shouldn't be\r | |
92 | try:\r | |
93 | pth_file.create()\r | |
94 | site.addpackage(pth_file.base_dir, pth_file.filename, set())\r | |
95 | self.pth_file_tests(pth_file)\r | |
96 | finally:\r | |
97 | pth_file.cleanup()\r | |
98 | \r | |
99 | def make_pth(self, contents, pth_dir='.', pth_name=TESTFN):\r | |
100 | # Create a .pth file and return its (abspath, basename).\r | |
101 | pth_dir = os.path.abspath(pth_dir)\r | |
102 | pth_basename = pth_name + '.pth'\r | |
103 | pth_fn = os.path.join(pth_dir, pth_basename)\r | |
104 | pth_file = open(pth_fn, 'w')\r | |
105 | self.addCleanup(lambda: os.remove(pth_fn))\r | |
106 | pth_file.write(contents)\r | |
107 | pth_file.close()\r | |
108 | return pth_dir, pth_basename\r | |
109 | \r | |
110 | def test_addpackage_import_bad_syntax(self):\r | |
111 | # Issue 10642\r | |
112 | pth_dir, pth_fn = self.make_pth("import bad)syntax\n")\r | |
113 | with captured_output("stderr") as err_out:\r | |
114 | site.addpackage(pth_dir, pth_fn, set())\r | |
115 | self.assertRegexpMatches(err_out.getvalue(), "line 1")\r | |
116 | self.assertRegexpMatches(err_out.getvalue(),\r | |
117 | re.escape(os.path.join(pth_dir, pth_fn)))\r | |
118 | # XXX: the previous two should be independent checks so that the\r | |
119 | # order doesn't matter. The next three could be a single check\r | |
120 | # but my regex foo isn't good enough to write it.\r | |
121 | self.assertRegexpMatches(err_out.getvalue(), 'Traceback')\r | |
122 | self.assertRegexpMatches(err_out.getvalue(), r'import bad\)syntax')\r | |
123 | self.assertRegexpMatches(err_out.getvalue(), 'SyntaxError')\r | |
124 | \r | |
125 | def test_addpackage_import_bad_exec(self):\r | |
126 | # Issue 10642\r | |
127 | pth_dir, pth_fn = self.make_pth("randompath\nimport nosuchmodule\n")\r | |
128 | with captured_output("stderr") as err_out:\r | |
129 | site.addpackage(pth_dir, pth_fn, set())\r | |
130 | self.assertRegexpMatches(err_out.getvalue(), "line 2")\r | |
131 | self.assertRegexpMatches(err_out.getvalue(),\r | |
132 | re.escape(os.path.join(pth_dir, pth_fn)))\r | |
133 | # XXX: ditto previous XXX comment.\r | |
134 | self.assertRegexpMatches(err_out.getvalue(), 'Traceback')\r | |
135 | self.assertRegexpMatches(err_out.getvalue(), 'ImportError')\r | |
136 | \r | |
137 | @unittest.skipIf(sys.platform == "win32", "Windows does not raise an "\r | |
138 | "error for file paths containing null characters")\r | |
139 | def test_addpackage_import_bad_pth_file(self):\r | |
140 | # Issue 5258\r | |
141 | pth_dir, pth_fn = self.make_pth("abc\x00def\n")\r | |
142 | with captured_output("stderr") as err_out:\r | |
143 | site.addpackage(pth_dir, pth_fn, set())\r | |
144 | self.assertRegexpMatches(err_out.getvalue(), "line 1")\r | |
145 | self.assertRegexpMatches(err_out.getvalue(),\r | |
146 | re.escape(os.path.join(pth_dir, pth_fn)))\r | |
147 | # XXX: ditto previous XXX comment.\r | |
148 | self.assertRegexpMatches(err_out.getvalue(), 'Traceback')\r | |
149 | self.assertRegexpMatches(err_out.getvalue(), 'TypeError')\r | |
150 | \r | |
151 | def test_addsitedir(self):\r | |
152 | # Same tests for test_addpackage since addsitedir() essentially just\r | |
153 | # calls addpackage() for every .pth file in the directory\r | |
154 | pth_file = PthFile()\r | |
155 | pth_file.cleanup(prep=True) # Make sure that nothing is pre-existing\r | |
156 | # that is tested for\r | |
157 | try:\r | |
158 | pth_file.create()\r | |
159 | site.addsitedir(pth_file.base_dir, set())\r | |
160 | self.pth_file_tests(pth_file)\r | |
161 | finally:\r | |
162 | pth_file.cleanup()\r | |
163 | \r | |
164 | def test_s_option(self):\r | |
165 | usersite = site.USER_SITE\r | |
166 | self.assertIn(usersite, sys.path)\r | |
167 | \r | |
168 | env = os.environ.copy()\r | |
169 | rc = subprocess.call([sys.executable, '-c',\r | |
170 | 'import sys; sys.exit(%r in sys.path)' % usersite],\r | |
171 | env=env)\r | |
172 | self.assertEqual(rc, 1, "%r is not in sys.path (sys.exit returned %r)"\r | |
173 | % (usersite, rc))\r | |
174 | \r | |
175 | env = os.environ.copy()\r | |
176 | rc = subprocess.call([sys.executable, '-s', '-c',\r | |
177 | 'import sys; sys.exit(%r in sys.path)' % usersite],\r | |
178 | env=env)\r | |
179 | self.assertEqual(rc, 0)\r | |
180 | \r | |
181 | env = os.environ.copy()\r | |
182 | env["PYTHONNOUSERSITE"] = "1"\r | |
183 | rc = subprocess.call([sys.executable, '-c',\r | |
184 | 'import sys; sys.exit(%r in sys.path)' % usersite],\r | |
185 | env=env)\r | |
186 | self.assertEqual(rc, 0)\r | |
187 | \r | |
188 | env = os.environ.copy()\r | |
189 | env["PYTHONUSERBASE"] = "/tmp"\r | |
190 | rc = subprocess.call([sys.executable, '-c',\r | |
191 | 'import sys, site; sys.exit(site.USER_BASE.startswith("/tmp"))'],\r | |
192 | env=env)\r | |
193 | self.assertEqual(rc, 1)\r | |
194 | \r | |
195 | def test_getuserbase(self):\r | |
196 | site.USER_BASE = None\r | |
197 | user_base = site.getuserbase()\r | |
198 | \r | |
199 | # the call sets site.USER_BASE\r | |
200 | self.assertEqual(site.USER_BASE, user_base)\r | |
201 | \r | |
202 | # let's set PYTHONUSERBASE and see if it uses it\r | |
203 | site.USER_BASE = None\r | |
204 | import sysconfig\r | |
205 | sysconfig._CONFIG_VARS = None\r | |
206 | \r | |
207 | with EnvironmentVarGuard() as environ:\r | |
208 | environ['PYTHONUSERBASE'] = 'xoxo'\r | |
209 | self.assertTrue(site.getuserbase().startswith('xoxo'),\r | |
210 | site.getuserbase())\r | |
211 | \r | |
212 | def test_getusersitepackages(self):\r | |
213 | site.USER_SITE = None\r | |
214 | site.USER_BASE = None\r | |
215 | user_site = site.getusersitepackages()\r | |
216 | \r | |
217 | # the call sets USER_BASE *and* USER_SITE\r | |
218 | self.assertEqual(site.USER_SITE, user_site)\r | |
219 | self.assertTrue(user_site.startswith(site.USER_BASE), user_site)\r | |
220 | \r | |
221 | def test_getsitepackages(self):\r | |
222 | site.PREFIXES = ['xoxo']\r | |
223 | dirs = site.getsitepackages()\r | |
224 | \r | |
225 | if sys.platform in ('os2emx', 'riscos'):\r | |
226 | self.assertEqual(len(dirs), 1)\r | |
227 | wanted = os.path.join('xoxo', 'Lib', 'site-packages')\r | |
228 | self.assertEqual(dirs[0], wanted)\r | |
229 | elif os.sep == '/':\r | |
230 | self.assertEqual(len(dirs), 2)\r | |
231 | wanted = os.path.join('xoxo', 'lib', 'python' + sys.version[:3],\r | |
232 | 'site-packages')\r | |
233 | self.assertEqual(dirs[0], wanted)\r | |
234 | wanted = os.path.join('xoxo', 'lib', 'site-python')\r | |
235 | self.assertEqual(dirs[1], wanted)\r | |
236 | else:\r | |
237 | self.assertEqual(len(dirs), 2)\r | |
238 | self.assertEqual(dirs[0], 'xoxo')\r | |
239 | wanted = os.path.join('xoxo', 'lib', 'site-packages')\r | |
240 | self.assertEqual(dirs[1], wanted)\r | |
241 | \r | |
242 | # let's try the specific Apple location\r | |
243 | if (sys.platform == "darwin" and\r | |
244 | sysconfig.get_config_var("PYTHONFRAMEWORK")):\r | |
245 | site.PREFIXES = ['Python.framework']\r | |
246 | dirs = site.getsitepackages()\r | |
247 | self.assertEqual(len(dirs), 4)\r | |
248 | wanted = os.path.join('~', 'Library', 'Python',\r | |
249 | sys.version[:3], 'site-packages')\r | |
250 | self.assertEqual(dirs[2], os.path.expanduser(wanted))\r | |
251 | wanted = os.path.join('/Library', 'Python', sys.version[:3],\r | |
252 | 'site-packages')\r | |
253 | self.assertEqual(dirs[3], wanted)\r | |
254 | \r | |
255 | class PthFile(object):\r | |
256 | """Helper class for handling testing of .pth files"""\r | |
257 | \r | |
258 | def __init__(self, filename_base=TESTFN, imported="time",\r | |
259 | good_dirname="__testdir__", bad_dirname="__bad"):\r | |
260 | """Initialize instance variables"""\r | |
261 | self.filename = filename_base + ".pth"\r | |
262 | self.base_dir = os.path.abspath('')\r | |
263 | self.file_path = os.path.join(self.base_dir, self.filename)\r | |
264 | self.imported = imported\r | |
265 | self.good_dirname = good_dirname\r | |
266 | self.bad_dirname = bad_dirname\r | |
267 | self.good_dir_path = os.path.join(self.base_dir, self.good_dirname)\r | |
268 | self.bad_dir_path = os.path.join(self.base_dir, self.bad_dirname)\r | |
269 | \r | |
270 | def create(self):\r | |
271 | """Create a .pth file with a comment, blank lines, an ``import\r | |
272 | <self.imported>``, a line with self.good_dirname, and a line with\r | |
273 | self.bad_dirname.\r | |
274 | \r | |
275 | Creation of the directory for self.good_dir_path (based off of\r | |
276 | self.good_dirname) is also performed.\r | |
277 | \r | |
278 | Make sure to call self.cleanup() to undo anything done by this method.\r | |
279 | \r | |
280 | """\r | |
281 | FILE = open(self.file_path, 'w')\r | |
282 | try:\r | |
283 | print>>FILE, "#import @bad module name"\r | |
284 | print>>FILE, "\n"\r | |
285 | print>>FILE, "import %s" % self.imported\r | |
286 | print>>FILE, self.good_dirname\r | |
287 | print>>FILE, self.bad_dirname\r | |
288 | finally:\r | |
289 | FILE.close()\r | |
290 | os.mkdir(self.good_dir_path)\r | |
291 | \r | |
292 | def cleanup(self, prep=False):\r | |
293 | """Make sure that the .pth file is deleted, self.imported is not in\r | |
294 | sys.modules, and that both self.good_dirname and self.bad_dirname are\r | |
295 | not existing directories."""\r | |
296 | if os.path.exists(self.file_path):\r | |
297 | os.remove(self.file_path)\r | |
298 | if prep:\r | |
299 | self.imported_module = sys.modules.get(self.imported)\r | |
300 | if self.imported_module:\r | |
301 | del sys.modules[self.imported]\r | |
302 | else:\r | |
303 | if self.imported_module:\r | |
304 | sys.modules[self.imported] = self.imported_module\r | |
305 | if os.path.exists(self.good_dir_path):\r | |
306 | os.rmdir(self.good_dir_path)\r | |
307 | if os.path.exists(self.bad_dir_path):\r | |
308 | os.rmdir(self.bad_dir_path)\r | |
309 | \r | |
310 | class ImportSideEffectTests(unittest.TestCase):\r | |
311 | """Test side-effects from importing 'site'."""\r | |
312 | \r | |
313 | def setUp(self):\r | |
314 | """Make a copy of sys.path"""\r | |
315 | self.sys_path = sys.path[:]\r | |
316 | \r | |
317 | def tearDown(self):\r | |
318 | """Restore sys.path"""\r | |
319 | sys.path[:] = self.sys_path\r | |
320 | \r | |
321 | def test_abs__file__(self):\r | |
322 | # Make sure all imported modules have their __file__ attribute\r | |
323 | # as an absolute path.\r | |
324 | # Handled by abs__file__()\r | |
325 | site.abs__file__()\r | |
326 | for module in (sys, os, __builtin__):\r | |
327 | try:\r | |
328 | self.assertTrue(os.path.isabs(module.__file__), repr(module))\r | |
329 | except AttributeError:\r | |
330 | continue\r | |
331 | # We could try everything in sys.modules; however, when regrtest.py\r | |
332 | # runs something like test_frozen before test_site, then we will\r | |
333 | # be testing things loaded *after* test_site did path normalization\r | |
334 | \r | |
335 | def test_no_duplicate_paths(self):\r | |
336 | # No duplicate paths should exist in sys.path\r | |
337 | # Handled by removeduppaths()\r | |
338 | site.removeduppaths()\r | |
339 | seen_paths = set()\r | |
340 | for path in sys.path:\r | |
341 | self.assertNotIn(path, seen_paths)\r | |
342 | seen_paths.add(path)\r | |
343 | \r | |
344 | def test_add_build_dir(self):\r | |
345 | # Test that the build directory's Modules directory is used when it\r | |
346 | # should be.\r | |
347 | # XXX: implement\r | |
348 | pass\r | |
349 | \r | |
350 | def test_setting_quit(self):\r | |
351 | # 'quit' and 'exit' should be injected into __builtin__\r | |
352 | self.assertTrue(hasattr(__builtin__, "quit"))\r | |
353 | self.assertTrue(hasattr(__builtin__, "exit"))\r | |
354 | \r | |
355 | def test_setting_copyright(self):\r | |
356 | # 'copyright' and 'credits' should be in __builtin__\r | |
357 | self.assertTrue(hasattr(__builtin__, "copyright"))\r | |
358 | self.assertTrue(hasattr(__builtin__, "credits"))\r | |
359 | \r | |
360 | def test_setting_help(self):\r | |
361 | # 'help' should be set in __builtin__\r | |
362 | self.assertTrue(hasattr(__builtin__, "help"))\r | |
363 | \r | |
364 | def test_aliasing_mbcs(self):\r | |
365 | if sys.platform == "win32":\r | |
366 | import locale\r | |
367 | if locale.getdefaultlocale()[1].startswith('cp'):\r | |
368 | for value in encodings.aliases.aliases.itervalues():\r | |
369 | if value == "mbcs":\r | |
370 | break\r | |
371 | else:\r | |
372 | self.fail("did not alias mbcs")\r | |
373 | \r | |
374 | def test_setdefaultencoding_removed(self):\r | |
375 | # Make sure sys.setdefaultencoding is gone\r | |
376 | self.assertTrue(not hasattr(sys, "setdefaultencoding"))\r | |
377 | \r | |
378 | def test_sitecustomize_executed(self):\r | |
379 | # If sitecustomize is available, it should have been imported.\r | |
380 | if "sitecustomize" not in sys.modules:\r | |
381 | try:\r | |
382 | import sitecustomize\r | |
383 | except ImportError:\r | |
384 | pass\r | |
385 | else:\r | |
386 | self.fail("sitecustomize not imported automatically")\r | |
387 | \r | |
388 | def test_main():\r | |
389 | run_unittest(HelperFunctionsTests, ImportSideEffectTests)\r | |
390 | \r | |
391 | if __name__ == "__main__":\r | |
392 | test_main()\r |