Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite3ef400

Browse files
gh-74696: Pass root_dir to custom archivers which support it (GH-94251)
Co-authored-by: Éric <merwok@netwok.org>
1 parent4b83cd0 commite3ef400

File tree

5 files changed

+77
-17
lines changed

5 files changed

+77
-17
lines changed

‎Doc/library/shutil.rst

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,9 +575,10 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules.
575575
..note::
576576

577577
This function is not thread-safe when custom archivers registered
578-
with:func:`register_archive_format` are used. In this case it
578+
with:func:`register_archive_format` do not support the *root_dir*
579+
argument. In this case it
579580
temporarily changes the current working directory of the process
580-
to perform archiving.
581+
to*root_dir* toperform archiving.
581582

582583
..versionchanged::3.8
583584
The modern pax (POSIX.1-2001) format is now used instead of
@@ -614,12 +615,21 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules.
614615
Further arguments are passed as keyword arguments: *owner*, *group*,
615616
*dry_run* and *logger* (as passed in:func:`make_archive`).
616617

618+
If *function* has the custom attribute ``function.supports_root_dir`` set to ``True``,
619+
the *root_dir* argument is passed as a keyword argument.
620+
Otherwise the current working directory of the process is temporarily
621+
changed to *root_dir* before calling *function*.
622+
In this case:func:`make_archive` is not thread-safe.
623+
617624
If given, *extra_args* is a sequence of ``(name, value)`` pairs that will be
618625
used as extra keywords arguments when the archiver callable is used.
619626

620627
*description* is used by:func:`get_archive_formats` which returns the
621628
list of archivers. Defaults to an empty string.
622629

630+
..versionchanged::3.12
631+
Added support for functions supporting the *root_dir* argument.
632+
623633

624634
..function::unregister_archive_format(name)
625635

‎Doc/whatsnew/3.12.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@ os
127127
for a process with:func:`os.pidfd_open` in non-blocking mode.
128128
(Contributed by Kumar Aditya in:gh:`93312`.)
129129

130+
shutil
131+
------
132+
133+
*:func:`shutil.make_archive` now passes the *root_dir* argument to custom
134+
archivers which support it.
135+
In this case it no longer temporarily changes the current working directory
136+
of the process to *root_dir* to perform archiving.
137+
(Contributed by Serhiy Storchaka in:gh:`74696`.)
138+
130139

131140
sqlite3
132141
-------

‎Lib/shutil.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,28 +1023,30 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0,
10231023
zip_filename=os.path.abspath(zip_filename)
10241024
returnzip_filename
10251025

1026+
_make_tarball.supports_root_dir=True
1027+
_make_zipfile.supports_root_dir=True
1028+
10261029
# Maps the name of the archive format to a tuple containing:
10271030
# * the archiving function
10281031
# * extra keyword arguments
10291032
# * description
1030-
# * does it support the root_dir argument?
10311033
_ARCHIVE_FORMATS= {
10321034
'tar': (_make_tarball, [('compress',None)],
1033-
"uncompressed tar file",True),
1035+
"uncompressed tar file"),
10341036
}
10351037

10361038
if_ZLIB_SUPPORTED:
10371039
_ARCHIVE_FORMATS['gztar']= (_make_tarball, [('compress','gzip')],
1038-
"gzip'ed tar-file",True)
1039-
_ARCHIVE_FORMATS['zip']= (_make_zipfile, [],"ZIP file",True)
1040+
"gzip'ed tar-file")
1041+
_ARCHIVE_FORMATS['zip']= (_make_zipfile, [],"ZIP file")
10401042

10411043
if_BZ2_SUPPORTED:
10421044
_ARCHIVE_FORMATS['bztar']= (_make_tarball, [('compress','bzip2')],
1043-
"bzip2'ed tar-file",True)
1045+
"bzip2'ed tar-file")
10441046

10451047
if_LZMA_SUPPORTED:
10461048
_ARCHIVE_FORMATS['xztar']= (_make_tarball, [('compress','xz')],
1047-
"xz'ed tar-file",True)
1049+
"xz'ed tar-file")
10481050

10491051
defget_archive_formats():
10501052
"""Returns a list of supported formats for archiving and unarchiving.
@@ -1075,7 +1077,7 @@ def register_archive_format(name, function, extra_args=None, description=''):
10751077
ifnotisinstance(element, (tuple,list))orlen(element)!=2:
10761078
raiseTypeError('extra_args elements are : (arg_name, value)')
10771079

1078-
_ARCHIVE_FORMATS[name]= (function,extra_args,description,False)
1080+
_ARCHIVE_FORMATS[name]= (function,extra_args,description)
10791081

10801082
defunregister_archive_format(name):
10811083
del_ARCHIVE_FORMATS[name]
@@ -1114,10 +1116,10 @@ def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
11141116
ifbase_dirisNone:
11151117
base_dir=os.curdir
11161118

1117-
support_root_dir=format_info[3]
1119+
supports_root_dir=getattr(func,'supports_root_dir',False)
11181120
save_cwd=None
11191121
ifroot_dirisnotNone:
1120-
ifsupport_root_dir:
1122+
ifsupports_root_dir:
11211123
# Support path-like base_name here for backwards-compatibility.
11221124
base_name=os.fspath(base_name)
11231125
kwargs['root_dir']=root_dir

‎Lib/test/test_shutil.py

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,28 +1568,65 @@ def test_tarfile_root_owner(self):
15681568
finally:
15691569
archive.close()
15701570

1571+
deftest_make_archive_cwd_default(self):
1572+
current_dir=os.getcwd()
1573+
defarchiver(base_name,base_dir,**kw):
1574+
self.assertNotIn('root_dir',kw)
1575+
self.assertEqual(base_name,'basename')
1576+
self.assertEqual(os.getcwd(),current_dir)
1577+
raiseRuntimeError()
1578+
1579+
register_archive_format('xxx',archiver, [],'xxx file')
1580+
try:
1581+
withno_chdir:
1582+
withself.assertRaises(RuntimeError):
1583+
make_archive('basename','xxx')
1584+
self.assertEqual(os.getcwd(),current_dir)
1585+
finally:
1586+
unregister_archive_format('xxx')
1587+
15711588
deftest_make_archive_cwd(self):
15721589
current_dir=os.getcwd()
15731590
root_dir=self.mkdtemp()
1574-
def_breaks(*args,**kw):
1591+
defarchiver(base_name,base_dir,**kw):
1592+
self.assertNotIn('root_dir',kw)
1593+
self.assertEqual(base_name,os.path.join(current_dir,'basename'))
1594+
self.assertEqual(os.getcwd(),root_dir)
15751595
raiseRuntimeError()
15761596
dirs= []
15771597
def_chdir(path):
15781598
dirs.append(path)
15791599
orig_chdir(path)
15801600

1581-
register_archive_format('xxx',_breaks, [],'xxx file')
1601+
register_archive_format('xxx',archiver, [],'xxx file')
15821602
try:
15831603
withsupport.swap_attr(os,'chdir',_chdir)asorig_chdir:
1584-
try:
1585-
make_archive('xxx','xxx',root_dir=root_dir)
1586-
exceptException:
1587-
pass
1604+
withself.assertRaises(RuntimeError):
1605+
make_archive('basename','xxx',root_dir=root_dir)
15881606
self.assertEqual(os.getcwd(),current_dir)
15891607
self.assertEqual(dirs, [root_dir,current_dir])
15901608
finally:
15911609
unregister_archive_format('xxx')
15921610

1611+
deftest_make_archive_cwd_supports_root_dir(self):
1612+
current_dir=os.getcwd()
1613+
root_dir=self.mkdtemp()
1614+
defarchiver(base_name,base_dir,**kw):
1615+
self.assertEqual(base_name,'basename')
1616+
self.assertEqual(kw['root_dir'],root_dir)
1617+
self.assertEqual(os.getcwd(),current_dir)
1618+
raiseRuntimeError()
1619+
archiver.supports_root_dir=True
1620+
1621+
register_archive_format('xxx',archiver, [],'xxx file')
1622+
try:
1623+
withno_chdir:
1624+
withself.assertRaises(RuntimeError):
1625+
make_archive('basename','xxx',root_dir=root_dir)
1626+
self.assertEqual(os.getcwd(),current_dir)
1627+
finally:
1628+
unregister_archive_format('xxx')
1629+
15931630
deftest_make_tarfile_in_curdir(self):
15941631
# Issue #21280
15951632
root_dir=self.mkdtemp()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`shutil.make_archive` now passes the *root_dir* argument to custom
2+
archivers which support it.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp