99import zipapp
1010import zipfile
1111from test .support import requires_zlib
12+ from test .support import os_helper
1213
1314from unittest .mock import patch
1415
@@ -54,6 +55,22 @@ def test_create_archive_with_subdirs(self):
5455 self .assertIn ('foo/' , z .namelist ())
5556 self .assertIn ('bar/' , z .namelist ())
5657
58+ def test_create_sorted_archive (self ):
59+ # Test that zipapps order their files by name
60+ source = self .tmpdir / 'source'
61+ source .mkdir ()
62+ (source / 'zed.py' ).touch ()
63+ (source / 'bin' ).mkdir ()
64+ (source / 'bin' / 'qux' ).touch ()
65+ (source / 'bin' / 'baz' ).touch ()
66+ (source / '__main__.py' ).touch ()
67+ target = io .BytesIO ()
68+ zipapp .create_archive (str (source ), target )
69+ target .seek (0 )
70+ with zipfile .ZipFile (target , 'r' ) as zf :
71+ self .assertEqual (zf .namelist (),
72+ ["__main__.py" , "bin/" , "bin/baz" , "bin/qux" , "zed.py" ])
73+
5774 def test_create_archive_with_filter (self ):
5875 # Test packing a directory and using filter to specify
5976 # which files to include.
@@ -72,6 +89,30 @@ def skip_pyc_files(path):
7289 self .assertIn ('test.py' , z .namelist ())
7390 self .assertNotIn ('test.pyc' , z .namelist ())
7491
92+ def test_create_archive_self_insertion (self ):
93+ # When creating an archive, we shouldn't
94+ # include the archive in the list of files to add.
95+ source = self .tmpdir
96+ (source / '__main__.py' ).touch ()
97+ (source / 'test.py' ).touch ()
98+ target = self .tmpdir / 'target.pyz'
99+
100+ zipapp .create_archive (source , target )
101+ with zipfile .ZipFile (target , 'r' ) as z :
102+ self .assertEqual (len (z .namelist ()), 2 )
103+ self .assertIn ('__main__.py' , z .namelist ())
104+ self .assertIn ('test.py' , z .namelist ())
105+
106+ def test_target_overwrites_source_file (self ):
107+ # The target cannot be one of the files to add.
108+ source = self .tmpdir
109+ (source / '__main__.py' ).touch ()
110+ target = source / 'target.pyz'
111+ target .touch ()
112+
113+ with self .assertRaises (zipapp .ZipAppError ):
114+ zipapp .create_archive (source , target )
115+
75116 def test_create_archive_filter_exclude_dir (self ):
76117 # Test packing a directory and using a filter to exclude a
77118 # subdirectory (ensures that the path supplied to include
@@ -248,14 +289,15 @@ def test_write_shebang_to_fileobj(self):
248289 zipapp .create_archive (str (target ), new_target , interpreter = 'python2.7' )
249290 self .assertTrue (new_target .getvalue ().startswith (b'#!python2.7\n ' ))
250291
251- def test_read_from_pathobj (self ):
252- # Test that we can copy an archive using a pathlib.Path object
292+ def test_read_from_pathlike_obj (self ):
293+ # Test that we can copy an archive using a path-like object
253294 # for the source.
254295 source = self .tmpdir / 'source'
255296 source .mkdir ()
256297 (source / '__main__.py' ).touch ()
257- target1 = self .tmpdir / 'target1.pyz'
258- target2 = self .tmpdir / 'target2.pyz'
298+ source = os_helper .FakePath (str (source ))
299+ target1 = os_helper .FakePath (str (self .tmpdir / 'target1.pyz' ))
300+ target2 = os_helper .FakePath (str (self .tmpdir / 'target2.pyz' ))
259301 zipapp .create_archive (source , target1 , interpreter = 'python' )
260302 zipapp .create_archive (target1 , target2 , interpreter = 'python2.7' )
261303 self .assertEqual (zipapp .get_interpreter (target2 ), 'python2.7' )
@@ -301,6 +343,7 @@ def test_content_of_copied_archive(self):
301343 # (Unix only) tests that archives with shebang lines are made executable
302344 @unittest .skipIf (sys .platform == 'win32' ,
303345 'Windows does not support an executable bit' )
346+ @os_helper .skip_unless_working_chmod
304347 def test_shebang_is_executable (self ):
305348 # Test that an archive with a shebang line is made executable.
306349 source = self .tmpdir / 'source'
0 commit comments