mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	gh-99203: shutil.make_archive(): restore select CPython <= 3.10.5 behavior (GH-99802)
Restore following CPython <= 3.10.5 behavior of shutil.make_archive() that went away as part of gh-93160: Do not create an empty archive if root_dir is not a directory, and, in that case, raise FileNotFoundError or NotADirectoryError regardless of format choice. Beyond the brought-back behavior, the function may now also raise these exceptions in dry_run mode.
This commit is contained in:
		
							parent
							
								
									a794ebeb02
								
							
						
					
					
						commit
						a86df298df
					
				
					 3 changed files with 52 additions and 0 deletions
				
			
		|  | @ -1156,6 +1156,10 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, | |||
|     supports_root_dir = getattr(func, 'supports_root_dir', False) | ||||
|     save_cwd = None | ||||
|     if root_dir is not None: | ||||
|         stmd = os.stat(root_dir).st_mode | ||||
|         if not stat.S_ISDIR(stmd): | ||||
|             raise NotADirectoryError(errno.ENOTDIR, 'Not a directory', root_dir) | ||||
| 
 | ||||
|         if supports_root_dir: | ||||
|             # Support path-like base_name here for backwards-compatibility. | ||||
|             base_name = os.fspath(base_name) | ||||
|  |  | |||
|  | @ -1839,6 +1839,49 @@ def test_register_archive_format(self): | |||
|         formats = [name for name, params in get_archive_formats()] | ||||
|         self.assertNotIn('xxx', formats) | ||||
| 
 | ||||
|     def test_make_tarfile_rootdir_nodir(self): | ||||
|         # GH-99203 | ||||
|         self.addCleanup(os_helper.unlink, f'{TESTFN}.tar') | ||||
|         for dry_run in (False, True): | ||||
|             with self.subTest(dry_run=dry_run): | ||||
|                 tmp_dir = self.mkdtemp() | ||||
|                 nonexisting_file = os.path.join(tmp_dir, 'nonexisting') | ||||
|                 with self.assertRaises(FileNotFoundError) as cm: | ||||
|                     make_archive(TESTFN, 'tar', nonexisting_file, dry_run=dry_run) | ||||
|                 self.assertEqual(cm.exception.errno, errno.ENOENT) | ||||
|                 self.assertEqual(cm.exception.filename, nonexisting_file) | ||||
|                 self.assertFalse(os.path.exists(f'{TESTFN}.tar')) | ||||
| 
 | ||||
|                 tmp_fd, tmp_file = tempfile.mkstemp(dir=tmp_dir) | ||||
|                 os.close(tmp_fd) | ||||
|                 with self.assertRaises(NotADirectoryError) as cm: | ||||
|                     make_archive(TESTFN, 'tar', tmp_file, dry_run=dry_run) | ||||
|                 self.assertEqual(cm.exception.errno, errno.ENOTDIR) | ||||
|                 self.assertEqual(cm.exception.filename, tmp_file) | ||||
|                 self.assertFalse(os.path.exists(f'{TESTFN}.tar')) | ||||
| 
 | ||||
|     @support.requires_zlib() | ||||
|     def test_make_zipfile_rootdir_nodir(self): | ||||
|         # GH-99203 | ||||
|         self.addCleanup(os_helper.unlink, f'{TESTFN}.zip') | ||||
|         for dry_run in (False, True): | ||||
|             with self.subTest(dry_run=dry_run): | ||||
|                 tmp_dir = self.mkdtemp() | ||||
|                 nonexisting_file = os.path.join(tmp_dir, 'nonexisting') | ||||
|                 with self.assertRaises(FileNotFoundError) as cm: | ||||
|                     make_archive(TESTFN, 'zip', nonexisting_file, dry_run=dry_run) | ||||
|                 self.assertEqual(cm.exception.errno, errno.ENOENT) | ||||
|                 self.assertEqual(cm.exception.filename, nonexisting_file) | ||||
|                 self.assertFalse(os.path.exists(f'{TESTFN}.zip')) | ||||
| 
 | ||||
|                 tmp_fd, tmp_file = tempfile.mkstemp(dir=tmp_dir) | ||||
|                 os.close(tmp_fd) | ||||
|                 with self.assertRaises(NotADirectoryError) as cm: | ||||
|                     make_archive(TESTFN, 'zip', tmp_file, dry_run=dry_run) | ||||
|                 self.assertEqual(cm.exception.errno, errno.ENOTDIR) | ||||
|                 self.assertEqual(cm.exception.filename, tmp_file) | ||||
|                 self.assertFalse(os.path.exists(f'{TESTFN}.zip')) | ||||
| 
 | ||||
|     ### shutil.unpack_archive | ||||
| 
 | ||||
|     def check_unpack_archive(self, format, **kwargs): | ||||
|  |  | |||
|  | @ -0,0 +1,5 @@ | |||
| Restore following CPython <= 3.10.5 behavior of :func:`shutil.make_archive`: | ||||
| do not create an empty archive if ``root_dir`` is not a directory, and, in that | ||||
| case, raise :class:`FileNotFoundError` or :class:`NotADirectoryError` | ||||
| regardless of ``format`` choice. Beyond the brought-back behavior, the function | ||||
| may now also raise these exceptions in ``dry_run`` mode. | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 6t8k
						6t8k