Add more checks.

This commit is contained in:
Bastian Kleineidam 2012-05-11 20:07:50 +02:00
parent 2bfa5e2a6c
commit 96be0020ea
4 changed files with 108 additions and 11 deletions

View File

@ -8,6 +8,7 @@
Closes: SF bug #2977749
* Added support for the lbzip2 program handling BZIP2 archives.
* Added support for the plzip program handling LZIP archives.
* Prevent overwriting the same file with repack.
0.15 "Contraband" (released 8.4.2012)

65
doc/development.txt Normal file
View File

@ -0,0 +1,65 @@
Development with the patoolib library
======================================
The patool funtionality can also be used in other Python programs.
To do this, install the patool program, import the library and
use one or more of the convenience functions.
import patoolib
if patoolib.extract("myarchive.zip", verbose=True) == 0:
print "Success."
else:
print "Error."
General rules for all convenience functions:
* All convenience function return zero when no error occurred, else
an integer unequal zero.
* Error messages are printed on stderr, informative messages
are printed on stdout.
* All file arguments are filenames. File objects are not accepted
as input.
* Filenames can be relative or absolute.
The convenience functions are:
* ``def extract(archive, verbose=False, outdir=None)``
This function extracts the given archive filename to the current
working directory or if specified to the given directory name in outdir.
If verbose operation is set to True, additional output of the archive
program is shown.
* ``def list(archive, verbose=False)``
This function lists the contents of the given archive filename
on stdout.
If verbose operation is set to True, additional output of the archive
program is shown.
* ``def test(archive, verbose=False)``
This function tests the given archive filename.
If verbose operation is set to True, additional output of the archive
program is shown.
* ``def create(archive, *filenames, **kwargs)``
This function create a new archive. The type of archive is determined
by the archive filename extension. The archive must not already
exist.
The list of filenames to add to the archive must not be empty.
If verbose operation is set to True, additional output of the archive
program is shown.
* ``def diff(archive1, archive2, verbose=False)``
This function
* ``def repack(archive1, archive2, verbose=False)``
This function

View File

@ -398,9 +398,12 @@ def cleanup_outdir (outdir):
def _handle_archive (archive, command, *args, **kwargs):
"""Handle archive command; raising PatoolError on errors."""
if command != 'create':
# check that archive is a regular file
util.check_filename(archive)
# check arguments
if command == 'create':
util.check_archive_filelist(args)
util.check_new_filename(archive)
else:
util.check_existing_filename(archive)
format, encoding = kwargs.get("format"), kwargs.get("encoding")
if format is None:
format, encoding = get_archive_format(archive)
@ -470,9 +473,14 @@ def rmtree_log_error (func, path, exc):
def _diff_archives (archive1, archive2, **kwargs):
"""Show differences between two archives."""
if util.is_same_file(archive1, archive2):
msg = "no differences found: archive `%s' and `%s' are the same files"
print msg % (archive1, archive2)
return 0
diff = util.find_program("diff")
if not diff:
raise util.PatoolError("The diff(1) program is required for showing archive differences, please install it")
msg = "The diff(1) program is required for showing archive differences, please install it."
raise util.PatoolError(msg)
tmpdir1 = util.tmpdir()
tmpdir2 = util.tmpdir()
try:
@ -486,6 +494,9 @@ def _diff_archives (archive1, archive2, **kwargs):
def _repack_archive (archive1, archive2, **kwargs):
"""Repackage an archive to a different format."""
if util.is_same_file(archive1, archive2):
msg = "cannot repack identical archives `%s' and `%s'"
raise util.PatoolError(msg % (archive1, archive2))
tmpdir = util.tmpdir()
try:
_handle_archive(archive1, 'extract', outdir=tmpdir, **kwargs)
@ -539,7 +550,6 @@ def test (archive, verbose=False):
def create (archive, *filenames, **kwargs):
"""Create given archive with given files."""
assert len(filenames) > 0
return handle_archive(archive, 'create', *filenames, **kwargs)

View File

@ -189,7 +189,7 @@ def guess_mime_file_mime (file_prog, filename):
cmd = [file_prog, "--brief", "--mime", "--uncompress", filename]
try:
outparts = backtick(cmd).strip().split(";")
except OSError, msg:
except OSError:
# ignore errors, as file(1) is only a fallback
return mime, encoding
mime2 = outparts[0].split(" ", 1)[0]
@ -250,7 +250,7 @@ def guess_mime_file_text (file_prog, filename):
cmd = [file_prog, "--brief", filename]
try:
output = backtick(cmd).strip()
except OSError, msg:
except OSError:
# ignore errors, as file(1) is only a fallback
return None
# match output against known strings
@ -260,14 +260,28 @@ def guess_mime_file_text (file_prog, filename):
return None
def check_filename (filename):
def check_existing_filename (filename):
"""Ensure that given filename is a valid, existing file."""
if not os.path.isfile(filename):
raise PatoolError("`%s' is not a file." % filename)
raise PatoolError("`%s' is not a file" % filename)
if not os.path.exists(filename):
raise PatoolError("File `%s' not found." % filename)
raise PatoolError("file `%s' was not found" % filename)
if not os.access(filename, os.R_OK):
raise PatoolError("File `%s' not readable." % filename)
raise PatoolError("file `%s' is not readable" % filename)
def check_new_filename (filename):
"""Check that filename does not already exist."""
if os.path.exists(filename):
raise PatoolError("cannot overwrite existing file `%s'" % filename)
def check_archive_filelist (filenames):
"""Check that file list is not empty and contains only existing files."""
if not filenames:
raise PatoolError("cannot create archive with empty filelist")
for filename in filenames:
check_existing_filename(filename)
def set_mode (filename, flags):
@ -387,3 +401,10 @@ def strlist_with_or (alist):
if len(alist) > 1:
return "%s or %s" % (", ".join(alist[:-1]), alist[-1])
return ", ".join(alist)
def is_same_file (filename1, filename2):
"""Check if filename1 and filename2 point to the same file object."""
if os.name == 'posix':
return os.path.samefile(filename1, filename2)
return os.path.realpath(filename1) == os.path.realpath(filename2)