From b0729370ee7353482e01b682a7ab7e669dc6b490 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Tue, 7 Oct 2025 18:01:57 +0100 Subject: [PATCH 01/16] Add followlinks=True parameter to _make_zipfile() This causes symbolic links to both files and directories to be resolved and the link targets included in the resulting zipfile. This matches the default behaviour of command-line zip on Linux/UNIX systems (i.e. systems where filesystems supporting symbolic linking are likely to be present). --- Lib/shutil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index 8d8fe145567822..fb7f7fd9f44ac6 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1094,7 +1094,7 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, zf.write(base_dir, arcname) if logger is not None: logger.info("adding '%s'", base_dir) - for dirpath, dirnames, filenames in os.walk(base_dir): + for dirpath, dirnames, filenames in os.walk(base_dir, followlinks=True): arcdirpath = dirpath if root_dir is not None: arcdirpath = os.path.relpath(arcdirpath, root_dir) From 3fa1d476f15ef3819c4c464dd74420255246d5eb Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Tue, 7 Oct 2025 18:16:05 +0100 Subject: [PATCH 02/16] Update docstring for _make_zipfile() Docstring now describes the behaviour when symbolic links to files and directories are encountered. --- Lib/shutil.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index fb7f7fd9f44ac6..c3f2c3ee4f9038 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1063,10 +1063,17 @@ def _set_uid_gid(tarinfo): def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None, owner=None, group=None, root_dir=None): - """Create a zip file from all the files under 'base_dir'. - - The output zip file will be named 'base_name' + ".zip". Returns the - name of the output zip file. + """Create a zip file. Returns the name of the zip file. + - `base_name` is used as the name for the zip file, with a suffix + of '.zip'. + - `base_dir` is the directory containing the files to be included + in the zip file. The zip file is created at the same level in the + directory structure as `base_dir`. + + Symbolic links to files and directories are followed and the + targets of the links included in the zip file. This matches the + default behaviour of command-line zip utilities on Linux/UNIX + systems. """ import zipfile # late import for breaking circular dependency From 40770d7f8f268863b39b559302413c383df2cad5 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Tue, 7 Oct 2025 18:20:27 +0100 Subject: [PATCH 03/16] Update to docstring for _make_zipfile() Docstring now describes behaviour when hard links to files are encountered. --- Lib/shutil.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/shutil.py b/Lib/shutil.py index c3f2c3ee4f9038..7b7cb143a04698 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1074,6 +1074,11 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, targets of the links included in the zip file. This matches the default behaviour of command-line zip utilities on Linux/UNIX systems. + + Hard links to files are followed and the targets of the links + included in the zip file. There is no de-duplication of multiple + hard links to the same file that is provided by other formats, + e.g. tar. """ import zipfile # late import for breaking circular dependency From 6f9dea0df16f5a99346364a3fff969db7ca3e776 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Tue, 7 Oct 2025 18:21:38 +0100 Subject: [PATCH 04/16] Add a blank line for readability --- Lib/shutil.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/shutil.py b/Lib/shutil.py index 7b7cb143a04698..cec0fe2e845f1b 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1064,6 +1064,7 @@ def _set_uid_gid(tarinfo): def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None, owner=None, group=None, root_dir=None): """Create a zip file. Returns the name of the zip file. + - `base_name` is used as the name for the zip file, with a suffix of '.zip'. - `base_dir` is the directory containing the files to be included From f36fe947cbbca5a8c1c565a22b4d95676c1e59ce Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Wed, 8 Oct 2025 11:01:41 +0100 Subject: [PATCH 05/16] Add reference to Windows systems in docstring --- Lib/shutil.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index cec0fe2e845f1b..7274fcd43eba66 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1073,8 +1073,8 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, Symbolic links to files and directories are followed and the targets of the links included in the zip file. This matches the - default behaviour of command-line zip utilities on Linux/UNIX - systems. + default behaviour of command-line zip utilities on + Linux/UNIX/Windows systems. Hard links to files are followed and the targets of the links included in the zip file. There is no de-duplication of multiple From 4b4c1e3b6c5543b1b83b398bebeae8cec47e75a4 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Wed, 8 Oct 2025 12:33:50 +0100 Subject: [PATCH 06/16] Add _create_files_symlinks() --- Lib/test/test_shutil.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index ebb6cf88336249..bee1c43ac9c171 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1636,6 +1636,33 @@ def _create_files(self, base_dir='dist'): create_file((root_dir, 'outer'), 'xxx') return root_dir, base_dir + def _create_files_symlinks(self, base_dir="symlinks"): + # Create a test structure containing symbolic links. + root_dir = self.mkdtemp() + dist = os.path.join(root_dir, base_dir) + os.mkdir(dist) + create_file( + (dist, 'real_file1'), + 'This is a real file.' + ) + # Symbolic link to a file. + os.symlink( + os.path.join(dist, 'real_file1'), + os.path.join(dist, 'link_file1'), + ) + os.mkdir(os.path.join(dist, 'sub')) + create_file( + (dist, 'sub', 'real_file2'), + 'This is a real file too.' + ) + # Symbolic link to a directory. + os.symlink( + os.path.join(dist, 'sub'), + os.path.join(dist, 'sub2'), + target_is_directory=True, + ) + return root_dir, base_dir + @support.requires_zlib() def test_make_tarfile(self): root_dir, base_dir = self._create_files() From 89fd4b896d12a282ae94456e77390c9784d4cc69 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Wed, 8 Oct 2025 15:33:52 +0100 Subject: [PATCH 07/16] Add symlinks tests for _make_zipfile() --- Lib/test/test_shutil.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index bee1c43ac9c171..c110e14acd0211 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1909,6 +1909,35 @@ def test_zipfile_vs_zip(self): names2 = zf.namelist() self.assertEqual(sorted(names), sorted(names2)) + @os_helper.skip_unless_symlink + def test_make_zipfile_symlink_behaviour(self): + # Test that symbolic links are not preserved as links when + # shutil.make_archive() is used to make a zip file. + root_dir, base_dir = self._create_files_symlinks() + name = os.path.join(root_dir, 'z') + archive = shutil.make_archive( + name, "zip", root_dir=root_dir, base_dir=base_dir + ) + # Check we have a zip file. + self.assertTrue(zipfile.is_zipfile(archive)) + with zipfile.ZipFile(archive) as zf: + extract_dir = os.path.join(root_dir, base_dir, 'extract') + zf.extractall(extract_dir) + # If directory symlink sub2 that points to sub1 was + # preserved then sub2/real_file2 will not exist. + self.assertTrue( + os.path.exists( + os.path.join(extract_dir, base_dir, 'sub2/real_file2') + ) + ) + # If link_file1 was preserved then it will be a symbolic + # link. + self.assertFalse( + os.path.islink( + os.path.join(extract_dir, base_dir, 'link_file1') + ) + ) + @support.requires_zlib() @unittest.skipUnless(shutil.which('unzip'), 'Need the unzip command to run') From a1858f8fbcd58ff407f6bff75640251ed433e3f6 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Thu, 9 Oct 2025 15:06:57 +0100 Subject: [PATCH 08/16] Update tests for zip files with make_archive() Improved readability and added comments to _create_files_symlinks() for making a test directory structure. Expanded docstring for test_make_zipfile_symlink_behaviour to explain purpose of test and reasons why the test might be skipped in a Windows environment. Updated test with try-finally for proper clean up of files after the test. --- Lib/test/test_shutil.py | 60 ++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index c110e14acd0211..ff9634a75991e5 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1637,28 +1637,32 @@ def _create_files(self, base_dir='dist'): return root_dir, base_dir def _create_files_symlinks(self, base_dir="symlinks"): - # Create a test structure containing symbolic links. + # Create a test structure containing symbolic links to files and + # directories. root_dir = self.mkdtemp() - dist = os.path.join(root_dir, base_dir) - os.mkdir(dist) + wd = os.path.join(root_dir, base_dir) + os.mkdir(wd) + # Create a regular file. create_file( - (dist, 'real_file1'), - 'This is a real file.' + (wd, 'file1'), + 'This is file1.' ) - # Symbolic link to a file. + # Create a symbolic link to the file. os.symlink( - os.path.join(dist, 'real_file1'), - os.path.join(dist, 'link_file1'), + os.path.join(wd, 'file1'), + os.path.join(wd, 'link1'), ) - os.mkdir(os.path.join(dist, 'sub')) + # Create a sub-directory. + os.mkdir(os.path.join(wd, 'sub')) + # Create a regular file in the sub-directory. create_file( - (dist, 'sub', 'real_file2'), - 'This is a real file too.' + (wd, 'sub', 'file2'), + 'This is a file2.' ) - # Symbolic link to a directory. + # Create a symbolic link to the sub-directory. os.symlink( - os.path.join(dist, 'sub'), - os.path.join(dist, 'sub2'), + os.path.join(wd, 'sub'), + os.path.join(wd, 'sub2'), target_is_directory=True, ) return root_dir, base_dir @@ -1911,8 +1915,16 @@ def test_zipfile_vs_zip(self): @os_helper.skip_unless_symlink def test_make_zipfile_symlink_behaviour(self): - # Test that symbolic links are not preserved as links when - # shutil.make_archive() is used to make a zip file. + """Test that symbolic links for both file and directories are resolved + to their targets when shutil.make_archive() is used to make a zip file, + to match default command-line zip behaviour on Linux/UNIX/Windows. + + If this test is being skipped, it is because either the operating + environment does not support symbolic links, or you do not have the + necessary permissions to create them. For Windows (10 and above) the + test must be invoked from an elevated command prompt or with + Developer Mode turned on. + """ root_dir, base_dir = self._create_files_symlinks() name = os.path.join(root_dir, 'z') archive = shutil.make_archive( @@ -1923,20 +1935,24 @@ def test_make_zipfile_symlink_behaviour(self): with zipfile.ZipFile(archive) as zf: extract_dir = os.path.join(root_dir, base_dir, 'extract') zf.extractall(extract_dir) - # If directory symlink sub2 that points to sub1 was - # preserved then sub2/real_file2 will not exist. + try: + # If symbolic link sub2 that targets directory sub1 was + # preserved as a link then sub2/file2 will not exist. self.assertTrue( os.path.exists( - os.path.join(extract_dir, base_dir, 'sub2/real_file2') + os.path.join(extract_dir, base_dir, 'sub2/file2') ) ) - # If link_file1 was preserved then it will be a symbolic - # link. + # If symbolic link link1 that targets file1 was preserved then + # it will be a symbolic link. self.assertFalse( os.path.islink( - os.path.join(extract_dir, base_dir, 'link_file1') + os.path.join(extract_dir, base_dir, 'link1') ) ) + finally: + # Clean up + shutil.rmtree(root_dir) @support.requires_zlib() @unittest.skipUnless(shutil.which('unzip'), From d8dd82ab11be63a955d51e0fccfcca0c445d83b7 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Thu, 9 Oct 2025 15:14:09 +0100 Subject: [PATCH 09/16] Change docstring to comments First line of docstring within a test gets printed out when test runs. No other tests appear to be doing that so switched to commented lines instead. --- Lib/test/test_shutil.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index ff9634a75991e5..ada3c08f192e4e 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1915,16 +1915,17 @@ def test_zipfile_vs_zip(self): @os_helper.skip_unless_symlink def test_make_zipfile_symlink_behaviour(self): - """Test that symbolic links for both file and directories are resolved - to their targets when shutil.make_archive() is used to make a zip file, - to match default command-line zip behaviour on Linux/UNIX/Windows. - - If this test is being skipped, it is because either the operating - environment does not support symbolic links, or you do not have the - necessary permissions to create them. For Windows (10 and above) the - test must be invoked from an elevated command prompt or with - Developer Mode turned on. - """ + # Test that symbolic links for both file and directories are resolved + # to their targets when shutil.make_archive() is used to make a zip + # file, to match default command-line zip behaviour in + # Linux/UNIX/Windows. + + # If this test is being skipped, it is because either the operating + # environment does not support symbolic links, or you do not have the + # necessary permissions to create them. For Windows (10 and above) the + # test must be invoked from an elevated command prompt or with + # Developer Mode turned on. + root_dir, base_dir = self._create_files_symlinks() name = os.path.join(root_dir, 'z') archive = shutil.make_archive( @@ -1951,7 +1952,7 @@ def test_make_zipfile_symlink_behaviour(self): ) ) finally: - # Clean up + # Clean up. shutil.rmtree(root_dir) @support.requires_zlib() From c4ec596790c5a46c088b8144015e626319ceaf4e Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Thu, 9 Oct 2025 15:32:50 +0100 Subject: [PATCH 10/16] Add warning about os.walk() behaviour to docstring of _make_zipfile() --- Lib/shutil.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/shutil.py b/Lib/shutil.py index 7274fcd43eba66..7f6b934b314a80 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1080,6 +1080,11 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, included in the zip file. There is no de-duplication of multiple hard links to the same file that is provided by other formats, e.g. tar. + + CAUTION: This function uses os.walk() to prepare the list of files to be + included in the zip file. os.walk() does not keep track of which + directories have already been visited. A symbolic link to a directory that + is a parent of itself will lead to infinite recursion. """ import zipfile # late import for breaking circular dependency From 01c77419e3e70fe56db22399c2f788d35dff6cc3 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Thu, 9 Oct 2025 15:34:09 +0100 Subject: [PATCH 11/16] Fix small typos --- Lib/shutil.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index 7f6b934b314a80..e1e6e1d0ec4aa1 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1201,16 +1201,16 @@ def unregister_archive_format(name): def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, dry_run=0, owner=None, group=None, logger=None): - """Create an archive file (eg. zip or tar). + """Create an archive file (e.g. zip or tar). 'base_name' is the name of the file to create, minus any format-specific extension; 'format' is the archive format: one of "zip", "tar", "gztar", "bztar", "xztar", or "zstdtar". Or any other registered format. 'root_dir' is a directory that will be the root directory of the - archive; ie. we typically chdir into 'root_dir' before creating the + archive; i.e. we typically chdir into 'root_dir' before creating the archive. 'base_dir' is the directory where we start archiving from; - ie. 'base_dir' will be the common prefix of all files and + i.e. 'base_dir' will be the common prefix of all files and directories in the archive. 'root_dir' and 'base_dir' both default to the current directory. Returns the name of the archive file. From 55e17736940e66200c975752daddfce3c73bb330 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Thu, 9 Oct 2025 15:54:33 +0100 Subject: [PATCH 12/16] Add self to ACKS --- Misc/ACKS | 1 + 1 file changed, 1 insertion(+) diff --git a/Misc/ACKS b/Misc/ACKS index 0812b229e0ada4..c56800990a68b8 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -498,6 +498,7 @@ Eugene Dvurechenski Karmen Dykstra Josip Dzolonga Maxim Dzumanenko +Thomas Earp Hans Eckardt Rodolpho Eckhardt Ulrich Eckhardt From b4e035b74c06c1c3dc00c3ead3e877f31f591770 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 9 Oct 2025 15:50:13 +0000 Subject: [PATCH 13/16] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2025-10-09-15-50-12.gh-issue-139679.saib2u.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2025-10-09-15-50-12.gh-issue-139679.saib2u.rst diff --git a/Misc/NEWS.d/next/Library/2025-10-09-15-50-12.gh-issue-139679.saib2u.rst b/Misc/NEWS.d/next/Library/2025-10-09-15-50-12.gh-issue-139679.saib2u.rst new file mode 100644 index 00000000000000..f0ee197077083a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-10-09-15-50-12.gh-issue-139679.saib2u.rst @@ -0,0 +1 @@ +The default behaviour of shutil.make_archive(), in relation to handling of symbolic links when creating zip files, now matches the default behaviour of command-line zip utilities on Linux/UNIX/Windows: symbolic links to both files and directories are resolved to their targets and included in the zip file. From 7313e11e5b763f56acc4a9c161a08fbdb745f5d2 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Thu, 9 Oct 2025 20:55:22 +0100 Subject: [PATCH 14/16] Remove trailing whitespace --- Lib/shutil.py | 10 +++++----- Lib/test/test_shutil.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index e1e6e1d0ec4aa1..64a652a0f1ff95 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1071,14 +1071,14 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, in the zip file. The zip file is created at the same level in the directory structure as `base_dir`. - Symbolic links to files and directories are followed and the - targets of the links included in the zip file. This matches the + Symbolic links to files and directories are followed and the + targets of the links included in the zip file. This matches the default behaviour of command-line zip utilities on Linux/UNIX/Windows systems. - Hard links to files are followed and the targets of the links - included in the zip file. There is no de-duplication of multiple - hard links to the same file that is provided by other formats, + Hard links to files are followed and the targets of the links + included in the zip file. There is no de-duplication of multiple + hard links to the same file that is provided by other formats, e.g. tar. CAUTION: This function uses os.walk() to prepare the list of files to be diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index ada3c08f192e4e..ed31302b92e094 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1637,7 +1637,7 @@ def _create_files(self, base_dir='dist'): return root_dir, base_dir def _create_files_symlinks(self, base_dir="symlinks"): - # Create a test structure containing symbolic links to files and + # Create a test structure containing symbolic links to files and # directories. root_dir = self.mkdtemp() wd = os.path.join(root_dir, base_dir) @@ -1916,8 +1916,8 @@ def test_zipfile_vs_zip(self): @os_helper.skip_unless_symlink def test_make_zipfile_symlink_behaviour(self): # Test that symbolic links for both file and directories are resolved - # to their targets when shutil.make_archive() is used to make a zip - # file, to match default command-line zip behaviour in + # to their targets when shutil.make_archive() is used to make a zip + # file, to match default command-line zip behaviour in # Linux/UNIX/Windows. # If this test is being skipped, it is because either the operating @@ -1937,14 +1937,14 @@ def test_make_zipfile_symlink_behaviour(self): extract_dir = os.path.join(root_dir, base_dir, 'extract') zf.extractall(extract_dir) try: - # If symbolic link sub2 that targets directory sub1 was + # If symbolic link sub2 that targets directory sub1 was # preserved as a link then sub2/file2 will not exist. self.assertTrue( os.path.exists( os.path.join(extract_dir, base_dir, 'sub2/file2') ) ) - # If symbolic link link1 that targets file1 was preserved then + # If symbolic link link1 that targets file1 was preserved then # it will be a symbolic link. self.assertFalse( os.path.islink( From 4c0cd2a7255e7d01ae08bc2b741bbe2fc05e2773 Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Thu, 9 Oct 2025 20:59:01 +0100 Subject: [PATCH 15/16] Remove more whitespace --- Lib/test/test_shutil.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index ed31302b92e094..0e00109203be03 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1919,13 +1919,12 @@ def test_make_zipfile_symlink_behaviour(self): # to their targets when shutil.make_archive() is used to make a zip # file, to match default command-line zip behaviour in # Linux/UNIX/Windows. - + # # If this test is being skipped, it is because either the operating # environment does not support symbolic links, or you do not have the # necessary permissions to create them. For Windows (10 and above) the # test must be invoked from an elevated command prompt or with # Developer Mode turned on. - root_dir, base_dir = self._create_files_symlinks() name = os.path.join(root_dir, 'z') archive = shutil.make_archive( From 3532775294d8251349f7e5b05e9db717f1e91a7e Mon Sep 17 00:00:00 2001 From: cowgoesmoo69 Date: Thu, 9 Oct 2025 21:01:31 +0100 Subject: [PATCH 16/16] Remove whitespace --- Lib/shutil.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index 64a652a0f1ff95..fea2fe0b405a6a 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1064,13 +1064,13 @@ def _set_uid_gid(tarinfo): def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None, owner=None, group=None, root_dir=None): """Create a zip file. Returns the name of the zip file. - + - `base_name` is used as the name for the zip file, with a suffix of '.zip'. - `base_dir` is the directory containing the files to be included in the zip file. The zip file is created at the same level in the directory structure as `base_dir`. - + Symbolic links to files and directories are followed and the targets of the links included in the zip file. This matches the default behaviour of command-line zip utilities on