blob: 1abea278a2b087003f077a284f67f28a250762d2 [file] [log] [blame]
Brett Cannondf960682013-06-15 14:07:21 -04001import importlib.util
Meador Inge6f166602011-11-25 23:36:48 -06002import os
3import py_compile
4import shutil
Brett Cannonedfd6ae2013-04-14 12:48:15 -04005import stat
Barry Warsaw9d98c9b2014-12-01 18:15:26 -05006import sys
Meador Inge6f166602011-11-25 23:36:48 -06007import tempfile
8import unittest
9
Berker Peksaga42ad6b2014-09-01 12:33:12 +030010from test import support
11
Meador Inge6f166602011-11-25 23:36:48 -060012
13class PyCompileTests(unittest.TestCase):
14
15 def setUp(self):
16 self.directory = tempfile.mkdtemp()
17 self.source_path = os.path.join(self.directory, '_test.py')
18 self.pyc_path = self.source_path + 'c'
Brett Cannondf960682013-06-15 14:07:21 -040019 self.cache_path = importlib.util.cache_from_source(self.source_path)
Meador Ingefb36b3f2011-11-26 11:37:02 -060020 self.cwd_drive = os.path.splitdrive(os.getcwd())[0]
21 # In these tests we compute relative paths. When using Windows, the
22 # current working directory path and the 'self.source_path' might be
23 # on different drives. Therefore we need to switch to the drive where
24 # the temporary source file lives.
25 drive = os.path.splitdrive(self.source_path)[0]
26 if drive:
27 os.chdir(drive)
Meador Inge6f166602011-11-25 23:36:48 -060028 with open(self.source_path, 'w') as file:
29 file.write('x = 123\n')
30
31 def tearDown(self):
32 shutil.rmtree(self.directory)
Meador Ingefb36b3f2011-11-26 11:37:02 -060033 if self.cwd_drive:
34 os.chdir(self.cwd_drive)
Meador Inge6f166602011-11-25 23:36:48 -060035
36 def test_absolute_path(self):
37 py_compile.compile(self.source_path, self.pyc_path)
38 self.assertTrue(os.path.exists(self.pyc_path))
39 self.assertFalse(os.path.exists(self.cache_path))
40
Brett Cannon33915eb2013-06-14 18:33:00 -040041 def test_do_not_overwrite_symlinks(self):
42 # In the face of a cfile argument being a symlink, bail out.
43 # Issue #17222
44 try:
45 os.symlink(self.pyc_path + '.actual', self.pyc_path)
Brett Cannon0b16b0d2013-06-14 22:50:57 -040046 except (NotImplementedError, OSError):
Brett Cannon33915eb2013-06-14 18:33:00 -040047 self.skipTest('need to be able to create a symlink for a file')
48 else:
49 assert os.path.islink(self.pyc_path)
50 with self.assertRaises(FileExistsError):
51 py_compile.compile(self.source_path, self.pyc_path)
52
53 @unittest.skipIf(not os.path.exists(os.devnull) or os.path.isfile(os.devnull),
54 'requires os.devnull and for it to be a non-regular file')
55 def test_do_not_overwrite_nonregular_files(self):
56 # In the face of a cfile argument being a non-regular file, bail out.
57 # Issue #17222
58 with self.assertRaises(FileExistsError):
59 py_compile.compile(self.source_path, os.devnull)
60
Meador Inge6f166602011-11-25 23:36:48 -060061 def test_cache_path(self):
62 py_compile.compile(self.source_path)
63 self.assertTrue(os.path.exists(self.cache_path))
64
Meador Inge22b9b372011-11-28 09:27:32 -060065 def test_cwd(self):
66 cwd = os.getcwd()
67 os.chdir(self.directory)
68 py_compile.compile(os.path.basename(self.source_path),
69 os.path.basename(self.pyc_path))
70 os.chdir(cwd)
71 self.assertTrue(os.path.exists(self.pyc_path))
72 self.assertFalse(os.path.exists(self.cache_path))
73
Meador Inge6f166602011-11-25 23:36:48 -060074 def test_relative_path(self):
75 py_compile.compile(os.path.relpath(self.source_path),
76 os.path.relpath(self.pyc_path))
77 self.assertTrue(os.path.exists(self.pyc_path))
78 self.assertFalse(os.path.exists(self.cache_path))
79
Christian Heimes349b04e2013-10-25 09:21:51 +020080 @unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0,
81 'non-root user required')
Brett Cannon51460cc2013-04-24 16:34:07 -040082 @unittest.skipIf(os.name == 'nt',
83 'cannot control directory permissions on Windows')
Brett Cannonedfd6ae2013-04-14 12:48:15 -040084 def test_exceptions_propagate(self):
85 # Make sure that exceptions raised thanks to issues with writing
86 # bytecode.
87 # http://bugs.python.org/issue17244
88 mode = os.stat(self.directory)
89 os.chmod(self.directory, stat.S_IREAD)
90 try:
91 with self.assertRaises(IOError):
92 py_compile.compile(self.source_path, self.pyc_path)
93 finally:
94 os.chmod(self.directory, mode.st_mode)
95
Berker Peksag31f8a672014-08-22 20:17:32 +030096 def test_bad_coding(self):
97 bad_coding = os.path.join(os.path.dirname(__file__), 'bad_coding2.py')
Berker Peksaga7614d02014-09-01 12:29:53 +030098 with support.captured_stderr():
99 self.assertIsNone(py_compile.compile(bad_coding, doraise=False))
Berker Peksag0242f792014-08-22 20:52:15 +0300100 self.assertFalse(os.path.exists(
101 importlib.util.cache_from_source(bad_coding)))
Meador Inge6f166602011-11-25 23:36:48 -0600102
Barry Warsaw2a413852014-12-01 17:10:10 -0500103 def test_double_dot_no_clobber(self):
104 # http://bugs.python.org/issue22966
105 # py_compile foo.bar.py -> __pycache__/foo.cpython-34.pyc
106 weird_path = os.path.join(self.directory, 'foo.bar.py')
107 cache_path = importlib.util.cache_from_source(weird_path)
108 pyc_path = weird_path + 'c'
Barry Warsaweb2763d2014-12-02 11:30:43 -0500109 head, tail = os.path.split(cache_path)
110 penultimate_tail = os.path.basename(head)
Barry Warsaw2a413852014-12-01 17:10:10 -0500111 self.assertEqual(
Barry Warsaweb2763d2014-12-02 11:30:43 -0500112 os.path.join(penultimate_tail, tail),
113 os.path.join(
114 '__pycache__',
115 'foo.bar.{}.pyc'.format(sys.implementation.cache_tag)))
Barry Warsaw2a413852014-12-01 17:10:10 -0500116 with open(weird_path, 'w') as file:
117 file.write('x = 123\n')
118 py_compile.compile(weird_path)
119 self.assertTrue(os.path.exists(cache_path))
120 self.assertFalse(os.path.exists(pyc_path))
121
122
Meador Inge6f166602011-11-25 23:36:48 -0600123if __name__ == "__main__":
Brett Cannon255fb3e2013-04-14 12:51:36 -0400124 unittest.main()