def test_write_symlink_directory(self): # Given zipfile = os.path.join(self.tempdir, "foo.zip") real_file = os.path.join(self.tempdir, "include", "foo.h") symlink = os.path.join(self.tempdir, "HEADERS") os.makedirs(os.path.dirname(real_file)) with open(real_file, "wb") as fp: fp.write(b"/* header */") os.symlink(os.path.dirname(real_file), symlink) extract_dir = os.path.join(self.tempdir, "to") os.makedirs(extract_dir) r_real_file = os.path.join(extract_dir, "include", "foo.h") r_symlink = os.path.join(extract_dir, "HEADERS") # When with ZipFile(zipfile, "w") as zp: zp.write(symlink, "HEADERS") zp.write(real_file, "include/foo.h") with ZipFile(zipfile) as zp: zp.extractall(extract_dir) # Then with ZipFile(zipfile) as zp: self.assertEqual(len(zp.namelist()), 2) self.assertCountEqual(zp.namelist(), ("include/foo.h", "HEADERS")) self.assertFalse(os.path.islink(r_real_file)) self.assertTrue(os.path.islink(r_symlink)) self.assertTrue(os.path.isdir(r_symlink)) self.assertTrue(os.readlink(r_symlink), r_real_file)
def test_write_symlink_file(self): # Given zipfile = os.path.join(self.tempdir, "foo.zip") real_file = os.path.join(self.tempdir, "foo.txt") symlink = os.path.join(self.tempdir, "symlink") with open(real_file, "wb") as fp: fp.write(b"data") os.symlink(real_file, symlink) extract_dir = os.path.join(self.tempdir, "to") os.makedirs(extract_dir) r_real_file = os.path.join(extract_dir, "foo.txt") r_symlink = os.path.join(extract_dir, "symlink") # When with ZipFile(zipfile, "w") as zp: zp.write(symlink, "symlink") zp.write(real_file, "foo.txt") with ZipFile(zipfile) as zp: zp.extractall(extract_dir) # Then with ZipFile(zipfile) as zp: self.assertEqual(len(zp.namelist()), 2) self.assertCountEqual(zp.namelist(), ("foo.txt", "symlink")) self.assertFalse(os.path.islink(r_real_file)) self.assertTrue(os.path.islink(r_symlink)) self.assertTrue(os.readlink(r_symlink), r_real_file)
def test_extractall_preserve_all(self): with ZipFile(self.filename, 'r') as zipfp: zipfp.extractall(self.tempdir, preserve_permissions=PERMS_PRESERVE_ALL) for filename, mode in self.files: self.assertTrue(os.path.exists(filename)) self.assertEqual(os.stat(filename).st_mode & 0xFFF, mode)
def test_multiple_archives_write(self): # Given zipfile = os.path.join(self.tempdir, "foo.zip") to = os.path.join(self.tempdir, "to") # When with ZipFile(zipfile, "w") as zp: zp.write(__file__, "file.py") with self.assertRaises(ValueError): zp.write(__file__, "file.py") with ZipFile(zipfile) as zp: zp.extractall(to) # Then self.assertTrue(os.path.exists(zipfile)) self.assertTrue(os.path.exists(os.path.join(to, "file.py")))
def test_multiple_archives_read(self): # Given zipfile = os.path.join(self.tempdir, "foo.zip") # When with ZipFile(zipfile, "w", low_level=True) as zp: zp.writestr("file.py", b"data") zp.writestr("file.py", b"dato") # Then # ensure we have indeed two members with archive name file.py with ZipFile(zipfile, low_level=True) as zp: self.assertEqual(len(zp.namelist()), 2) # ensure we raise an error if duplicates with self.assertRaises(ValueError): with ZipFile(zipfile) as zp: pass
def test_extract(self): # Given path = NOSE_EGG arcname = "EGG-INFO/PKG-INFO" # When with ZipFile(path) as zp: zp.extract(arcname, self.tempdir) self.assertTrue(os.path.exists(os.path.join(self.tempdir, arcname)))
def test_extractall_preserve_none(self): umask = os.umask(0) os.umask(umask) with ZipFile(self.filename, 'r') as zipfp: zipfp.extractall(self.tempdir) for path, mode in self.files: expected_mode = 0o666 & ~umask self.assertTrue(os.path.exists(path)) self.assertEqual(os.stat(path).st_mode & 0xFFF, expected_mode)
def test_multiple_archives_writestr_write(self): # Given zipfile = os.path.join(self.tempdir, "foo.zip") to = os.path.join(self.tempdir, "to") filename = os.path.relpath(__file__, os.getcwd()) arcname = filename # When with ZipFile(zipfile, "w") as zp: zp.write(filename, arcname) with self.assertRaises(ValueError): zp.writestr(arcname, b"data") with ZipFile(zipfile) as zp: zp.extractall(to) # Then self.assertTrue(os.path.exists(zipfile)) self.assertTrue(os.path.exists(os.path.join(to, filename)))
def test_multiple_archives_writestr(self): # Given zipfile = os.path.join(self.tempdir, "foo.zip") target = os.path.join(self.tempdir, "file.py") # When with ZipFile(zipfile, "w") as zp: zp.writestr("file.py", b"data") with self.assertRaises(ValueError): zp.writestr("file.py", b"dato") with ZipFile(zipfile) as zp: new_path = zp.extract("file.py", self.tempdir) data = zp.read("file.py") # Then self.assertTrue(os.path.exists(zipfile)) self.assertTrue(os.path.exists(target)) self.assertEqual(data, b"data") self.assertEqual(new_path, target)
def test_context_manager(self): # Given path = NOSE_EGG # When/Then with ZipFile(path) as zp: self.assertIsNotNone(zp.fp) # Then self.assertIsNone(zp.fp) # When/Then try: with ZipFile(path) as zp: raise ValueError("I am failing !") except ValueError: pass # Then self.assertIsNone(zp.fp)
def test_extract_preserve_safe(self): with ZipFile(self.filename, 'r') as zipfp: for filename, mode in self.files: arcname = os.path.basename(filename) zipfp.extract(arcname, path=self.tempdir, preserve_permissions=PERMS_PRESERVE_SAFE) expected_mode = mode & 0x1FF self.assertTrue(os.path.exists(filename)) self.assertEqual( os.stat(filename).st_mode & 0xFFF, expected_mode)
def test_extract_preserve_none(self): umask = os.umask(0) os.umask(umask) with ZipFile(self.filename, 'r') as zipfp: for filename, mode in self.files: arcname = os.path.basename(filename) zipfp.extract(arcname, path=self.tempdir) expected_mode = 0o666 & ~umask self.assertTrue(os.path.exists(filename)) self.assertEqual( os.stat(filename).st_mode & 0xFFF, expected_mode)
def test_extract_to(self): # Given path = NOSE_EGG arcname = "EGG-INFO/PKG-INFO" # When with ZipFile(path) as zp: zp.extract_to(arcname, "FOO", self.tempdir) extracted_data = zp.read(arcname) self.assertTrue(os.path.exists(os.path.join(self.tempdir, "FOO"))) self.assertEqual(compute_md5(os.path.join(self.tempdir, "FOO")), compute_md5(BytesIO(extracted_data))) self.assertFalse( os.path.exists(os.path.join(self.tempdir, "EGG-INFO", "PKG-INFO")))
def test_extract_preserve_safe_with_symlink(self): # Given python27 = os.path.join(self.tempdir, "bin", "python2.7") python = os.path.join(self.tempdir, "bin", "python") # When with ZipFile(ZIP_WITH_SOFTLINK_AND_PERMISSIONS) as zipfp: zipfp.extractall(self.tempdir, preserve_permissions=PERMS_PRESERVE_SAFE) # Then self.assertTrue(os.path.exists(python)) self.assertTrue(os.path.islink(python)) self.assertTrue(os.path.exists(python27)) self.assertTrue(os.access(python27, os.X_OK))
def test_softlink(self): # Given path = ZIP_WITH_SOFTLINK # When/Then with ZipFile(path) as zp: zp.extractall(self.tempdir) paths = list_files(self.tempdir) self.assertCountEqual( paths, [os.path.join("lib", "foo.so.1.3"), os.path.join("lib", "foo.so")]) self.assertTrue( os.path.islink(os.path.join(self.tempdir, "lib", "foo.so")))
def test_simple(self): # Given path = NOSE_EGG r_paths = [ os.path.join("EGG-INFO", "entry_points.txt"), os.path.join("EGG-INFO", "PKG-INFO"), os.path.join("EGG-INFO", "spec", "depend"), os.path.join("EGG-INFO", "spec", "summary"), os.path.join("EGG-INFO", "usr", "share", "man", "man1", "nosetests.1"), ] # When with ZipFile(path) as zp: zp.extractall(self.tempdir) paths = list_files(self.tempdir) # Then self.assertCountEqual(paths, r_paths)
def test_permissions(self): # Given path = ZIP_WITH_PERMISSIONS symlink = os.path.join(self.tempdir, "bin", "python") target = os.path.join(self.tempdir, "bin", "python2.7") if sys.platform == "win32": r_mode = 0o666 else: r_mode = 0o755 # When/Then with ZipFile(path) as zp: zp.extractall(self.tempdir, preserve_permissions=PERMS_PRESERVE_SAFE) # Then self.assertTrue(os.path.exists(symlink)) self.assertTrue(os.path.exists(target)) self.assertEqual(stat.S_IMODE(os.stat(target).st_mode), r_mode)
def setUp(self): permissions = { 'user': (stat.S_IRUSR, stat.S_IWUSR, stat.S_IXUSR), 'group': (stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP), 'other': (stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH), 'special': (stat.S_ISUID, stat.S_ISGID, stat.S_ISVTX) } self.files = [] name_pattern = '{permgroup:s}_{octalcode:03b}_{specialcode:03b}' self.tempdir = tempfile.mkdtemp() self.filename = os.path.join(self.tempdir, "yoyo_{0}_tmp".format(os.getpid())) for permgroup in ('user', 'group', 'other'): for index in range(8): for specialindex in range(3): filename = name_pattern.\ format(permgroup=permgroup, octalcode=index, specialcode=specialindex) path = os.path.join(self.tempdir, filename) with open(path, 'wt') as file_: file_.write(filename) mode = stat.S_IRUSR for order in range(3): if index & 1 << order: mode |= permissions[permgroup][order] for order in range(3): if specialindex & 1 << order: mode |= permissions['special'][order] os.chmod(path, mode) real_permission = os.stat(path).st_mode & 0xFFF self.files.append((path, real_permission)) with ZipFile(self.filename, 'w', zipfile.ZIP_STORED) as zipfp: for path, mode in self.files: filename = os.path.basename(path) path = os.path.join(self.tempdir, filename) zipfp.write(path, filename) os.chmod(path, stat.S_IWRITE) os.remove(path)
def test_directory_softlink(self): # Given path = ZIP_WITH_DIRECTORY_SOFTLINK directory_link = os.path.join("lib", "foo") r_directory_link = os.path.join(self.tempdir, directory_link) r_paths = ( os.path.join("lib", "foo-1", "foo.so.1.3"), os.path.join("lib", "foo-1", "foo.so"), ) # When with ZipFile(path) as zp: zp.extractall(self.tempdir) # Then paths = list_files(self.tempdir) self.assertCountEqual(paths, r_paths) self.assertTrue(os.path.islink(r_directory_link)) target = os.readlink(r_directory_link) self.assertEqual(target, "foo-1")
def test_softlink_with_broken_entry(self): self.maxDiff = None # Given path = VTK_EGG expected_files = [ os.path.join('EGG-INFO', 'PKG-INFO'), os.path.join('EGG-INFO', 'inst', 'targets.dat'), os.path.join('EGG-INFO', 'inst', 'files_to_install.txt'), os.path.join('EGG-INFO', 'usr', 'lib', 'vtk-5.10', 'libvtkViews.so.5.10.1'), os.path.join('EGG-INFO', 'usr', 'lib', 'vtk-5.10', 'libvtkViews.so.5.10'), os.path.join('EGG-INFO', 'usr', 'lib', 'vtk-5.10', 'libvtkViews.so'), os.path.join('EGG-INFO', 'spec', 'lib-provide'), os.path.join('EGG-INFO', 'spec', 'depend'), os.path.join('EGG-INFO', 'spec', 'lib-depend'), os.path.join('EGG-INFO', 'spec', 'summary'), ] existing_link = os.path.join( self.tempdir, 'EGG-INFO/usr/lib/vtk-5.10/' 'libvtkViews.so') create_broken_symlink(existing_link) # When with ZipFile(path) as zp: zp.extractall(self.tempdir) files = list_files(self.tempdir) # Then self.assertCountEqual(files, expected_files) path = os.path.join(self.tempdir, "EGG-INFO/usr/lib/vtk-5.10/libvtkViews.so") self.assertTrue(os.path.islink(path))
def test_add_tree(self): # Given path = os.path.join(self.tempdir, "foo.zip") source_dir = os.path.join(self.tempdir, "from") extract_dir = os.path.join(self.tempdir, "to") os.makedirs(extract_dir) files = [ os.path.join(source_dir, "foo.txt"), os.path.join(source_dir, "foo", "fubar", "foo.txt"), ] r_files = [ os.path.join(extract_dir, "foo.txt"), os.path.join(extract_dir, "foo", "fubar", "foo.txt"), ] for f in files: os.makedirs(os.path.dirname(f)) with open(f, "wb") as fp: fp.write(b"yolo") # When with ZipFile(path, "w") as zp: zp.add_tree(source_dir) # Then with ZipFile(path) as zp: zp.extractall(extract_dir) self.assertCountEqual( zp.namelist(), ["foo/", "foo/fubar/", "foo.txt", "foo/fubar/foo.txt"]) for f in r_files: os.path.exists(f) with open(f, "rb") as fp: self.assertEqual(fp.read(), b"yolo") # Given r_files = [ os.path.join(extract_dir, "from", "foo.txt"), os.path.join(extract_dir, "from", "foo", "fubar", "foo.txt"), ] # When with ZipFile(path, "w") as zp: zp.add_tree(source_dir, True) # Then with ZipFile(path) as zp: zp.extractall(extract_dir) self.assertCountEqual(zp.namelist(), [ "from/foo/", "from/foo/fubar/", "from/foo.txt", "from/foo/fubar/foo.txt" ]) for f in r_files: os.path.exists(f) with open(f, "rb") as fp: self.assertEqual(fp.read(), b"yolo")
def test_existing_symlink_replacement(self): # Ensure that when we overwrite an existing file with extract* methods, # we don't fail in the case a file already exists but is a symlink to a # file we don't have access to. self.maxDiff = None # Given path = ZIP_WITH_SOFTLINK some_data = b"some data" r_files = [ os.path.join("lib", "foo.so.1.3"), os.path.join("lib", "foo.so") ] r_link = os.path.join(self.tempdir, "lib", "foo.so") r_file = os.path.join(self.tempdir, "lib", "foo.so.1.3") read_only_file = os.path.join(self.tempdir2, "read_only_file") def _create_read_only_file(read_only_file): with open(read_only_file, "wb") as fp: fp.write(some_data) mode = os.stat(read_only_file)[stat.ST_MODE] os.chmod(read_only_file, mode & ~stat.S_IWUSR & ~stat.S_IWGRP & ~stat.S_IWOTH) try: with open(read_only_file, "wb") as fp: pass raise RuntimeError("Creation of RO file failed") except IOError as e: if e.errno != errno.EACCES: raise def _create_link_to_ro(link_to_read_only_file): # Hack: we create a symlink toward a RO file to check the # destination can be overwritten assert not os.path.islink(link_to_read_only_file) os.unlink(link_to_read_only_file) os.symlink(read_only_file, link_to_read_only_file) _create_read_only_file(read_only_file) # When with ZipFile(path) as zp: zp.extractall(self.tempdir) original_md5 = compute_md5(r_file) _create_link_to_ro(r_file) with ZipFile(path) as zp: zp.extractall(self.tempdir) files = list_files(self.tempdir) # Then self.assertCountEqual(files, r_files) self.assertTrue(os.path.islink(r_link)) self.assertFalse(os.path.islink(r_file)) self.assertEqual(compute_md5(r_file), original_md5) # Making sure we did not modify the file originally linked to # by the overwritten symlink self.assertEqual(compute_md5(read_only_file), hashlib.md5(some_data).hexdigest())