|
1 | 1 | """Test harness for the zipapp module.""" |
2 | 2 |
|
3 | 3 | import io |
| 4 | +import os |
4 | 5 | import pathlib |
5 | 6 | import stat |
6 | 7 | import sys |
@@ -366,6 +367,38 @@ def test_shebang_is_executable(self): |
366 | 367 | zipapp.create_archive(str(source), str(target), interpreter='python') |
367 | 368 | self.assertTrue(target.stat().st_mode & stat.S_IEXEC) |
368 | 369 |
|
| 370 | + @unittest.skipIf(sys.platform == 'win32', |
| 371 | + 'Windows does not support an executable bit') |
| 372 | + @unittest.skipUnless(hasattr(os, 'umask'), 'test needs os.umask()') |
| 373 | + @os_helper.skip_unless_working_chmod |
| 374 | + def test_shebang_executable_bits_match_readable_bits(self): |
| 375 | + source = self.tmpdir / 'source' |
| 376 | + source.mkdir() |
| 377 | + (source / '__main__.py').touch() |
| 378 | + for umask, expected_mode in ((0o022, 0o755), (0o077, 0o700)): |
| 379 | + with self.subTest(umask=umask): |
| 380 | + target = self.tmpdir / f'source-{umask:o}.pyz' |
| 381 | + with os_helper.temp_umask(umask): |
| 382 | + zipapp.create_archive(str(source), str(target), interpreter='python') |
| 383 | + self.assertEqual(stat.S_IMODE(target.stat().st_mode), expected_mode) |
| 384 | + |
| 385 | + @unittest.skipIf(sys.platform == 'win32', |
| 386 | + 'Windows does not support an executable bit') |
| 387 | + @unittest.skipUnless(hasattr(os, 'umask'), 'test needs os.umask()') |
| 388 | + @os_helper.skip_unless_working_chmod |
| 389 | + def test_copied_shebang_executable_bits_match_readable_bits(self): |
| 390 | + source = self.tmpdir / 'source' |
| 391 | + source.mkdir() |
| 392 | + (source / '__main__.py').touch() |
| 393 | + archive = self.tmpdir / 'source.pyz' |
| 394 | + zipapp.create_archive(str(source), str(archive)) |
| 395 | + for umask, expected_mode in ((0o022, 0o755), (0o077, 0o700)): |
| 396 | + with self.subTest(umask=umask): |
| 397 | + target = self.tmpdir / f'target-{umask:o}.pyz' |
| 398 | + with os_helper.temp_umask(umask): |
| 399 | + zipapp.create_archive(str(archive), str(target), interpreter='python') |
| 400 | + self.assertEqual(stat.S_IMODE(target.stat().st_mode), expected_mode) |
| 401 | + |
369 | 402 | @unittest.skipIf(sys.platform == 'win32', |
370 | 403 | 'Windows does not support an executable bit') |
371 | 404 | def test_no_shebang_is_not_executable(self): |
|
0 commit comments