mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Update zipapp.py from 3.13.5 (#6075)
This commit is contained in:
1 parent
cac4948afe
commit
93eacdac20
2 files changed
+71
-5
No files matched your search
Vendored
+47
-4
@@ -9,6 +9,7 @@ import unittest
|
||||
import zipapp
|
||||
import zipfile
|
||||
from test.support import requires_zlib
|
||||
from test.support import os_helper
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
@@ -54,6 +55,22 @@ class ZipAppTest(unittest.TestCase):
|
||||
self.assertIn('foo/', z.namelist())
|
||||
self.assertIn('bar/', z.namelist())
|
||||
|
||||
def test_create_sorted_archive(self):
|
||||
# Test that zipapps order their files by name
|
||||
source = self.tmpdir / 'source'
|
||||
source.mkdir()
|
||||
(source / 'zed.py').touch()
|
||||
(source / 'bin').mkdir()
|
||||
(source / 'bin' / 'qux').touch()
|
||||
(source / 'bin' / 'baz').touch()
|
||||
(source / '__main__.py').touch()
|
||||
target = io.BytesIO()
|
||||
zipapp.create_archive(str(source), target)
|
||||
target.seek(0)
|
||||
with zipfile.ZipFile(target, 'r') as zf:
|
||||
self.assertEqual(zf.namelist(),
|
||||
["__main__.py", "bin/", "bin/baz", "bin/qux", "zed.py"])
|
||||
|
||||
def test_create_archive_with_filter(self):
|
||||
# Test packing a directory and using filter to specify
|
||||
# which files to include.
|
||||
@@ -72,6 +89,30 @@ class ZipAppTest(unittest.TestCase):
|
||||
self.assertIn('test.py', z.namelist())
|
||||
self.assertNotIn('test.pyc', z.namelist())
|
||||
|
||||
def test_create_archive_self_insertion(self):
|
||||
# When creating an archive, we shouldn't
|
||||
# include the archive in the list of files to add.
|
||||
source = self.tmpdir
|
||||
(source / '__main__.py').touch()
|
||||
(source / 'test.py').touch()
|
||||
target = self.tmpdir / 'target.pyz'
|
||||
|
||||
zipapp.create_archive(source, target)
|
||||
with zipfile.ZipFile(target, 'r') as z:
|
||||
self.assertEqual(len(z.namelist()), 2)
|
||||
self.assertIn('__main__.py', z.namelist())
|
||||
self.assertIn('test.py', z.namelist())
|
||||
|
||||
def test_target_overwrites_source_file(self):
|
||||
# The target cannot be one of the files to add.
|
||||
source = self.tmpdir
|
||||
(source / '__main__.py').touch()
|
||||
target = source / 'target.pyz'
|
||||
target.touch()
|
||||
|
||||
with self.assertRaises(zipapp.ZipAppError):
|
||||
zipapp.create_archive(source, target)
|
||||
|
||||
def test_create_archive_filter_exclude_dir(self):
|
||||
# Test packing a directory and using a filter to exclude a
|
||||
# subdirectory (ensures that the path supplied to include
|
||||
@@ -248,14 +289,15 @@ class ZipAppTest(unittest.TestCase):
|
||||
zipapp.create_archive(str(target), new_target, interpreter='python2.7')
|
||||
self.assertTrue(new_target.getvalue().startswith(b'#!python2.7\n'))
|
||||
|
||||
def test_read_from_pathobj(self):
|
||||
# Test that we can copy an archive using a pathlib.Path object
|
||||
def test_read_from_pathlike_obj(self):
|
||||
# Test that we can copy an archive using a path-like object
|
||||
# for the source.
|
||||
source = self.tmpdir / 'source'
|
||||
source.mkdir()
|
||||
(source / '__main__.py').touch()
|
||||
target1 = self.tmpdir / 'target1.pyz'
|
||||
target2 = self.tmpdir / 'target2.pyz'
|
||||
source = os_helper.FakePath(str(source))
|
||||
target1 = os_helper.FakePath(str(self.tmpdir / 'target1.pyz'))
|
||||
target2 = os_helper.FakePath(str(self.tmpdir / 'target2.pyz'))
|
||||
zipapp.create_archive(source, target1, interpreter='python')
|
||||
zipapp.create_archive(target1, target2, interpreter='python2.7')
|
||||
self.assertEqual(zipapp.get_interpreter(target2), 'python2.7')
|
||||
@@ -301,6 +343,7 @@ class ZipAppTest(unittest.TestCase):
|
||||
# (Unix only) tests that archives with shebang lines are made executable
|
||||
@unittest.skipIf(sys.platform == 'win32',
|
||||
'Windows does not support an executable bit')
|
||||
@os_helper.skip_unless_working_chmod
|
||||
def test_shebang_is_executable(self):
|
||||
# Test that an archive with a shebang line is made executable.
|
||||
source = self.tmpdir / 'source'
|
||||
|
||||
Vendored
+24
-1
@@ -131,12 +131,35 @@ def create_archive(source, target=None, interpreter=None, main=None,
|
||||
elif not hasattr(target, 'write'):
|
||||
target = pathlib.Path(target)
|
||||
|
||||
# Create the list of files to add to the archive now, in case
|
||||
# the target is being created in the source directory - we
|
||||
# don't want the target being added to itself
|
||||
files_to_add = sorted(source.rglob('*'))
|
||||
|
||||
# The target cannot be in the list of files to add. If it were, we'd
|
||||
# end up overwriting the source file and writing the archive into
|
||||
# itself, which is an error. We therefore check for that case and
|
||||
# provide a helpful message for the user.
|
||||
|
||||
# Note that we only do a simple path equality check. This won't
|
||||
# catch every case, but it will catch the common case where the
|
||||
# source is the CWD and the target is a file in the CWD. More
|
||||
# thorough checks don't provide enough value to justify the extra
|
||||
# cost.
|
||||
|
||||
# If target is a file-like object, it will simply fail to compare
|
||||
# equal to any of the entries in files_to_add, so there's no need
|
||||
# to add a special check for that.
|
||||
if target in files_to_add:
|
||||
raise ZipAppError(
|
||||
f"The target archive {target} overwrites one of the source files.")
|
||||
|
||||
with _maybe_open(target, 'wb') as fd:
|
||||
_write_file_prefix(fd, interpreter)
|
||||
compression = (zipfile.ZIP_DEFLATED if compressed else
|
||||
zipfile.ZIP_STORED)
|
||||
with zipfile.ZipFile(fd, 'w', compression=compression) as z:
|
||||
for child in source.rglob('*'):
|
||||
for child in files_to_add:
|
||||
arcname = child.relative_to(source)
|
||||
if filter is None or filter(arcname):
|
||||
z.write(child, arcname.as_posix())
|
||||
|
||||
Reference in new issue
Block a user