Replace baker with argparse; some code restructuration.
This commit is contained in:
parent
a905c893b9
commit
cee88ecb60
|
|
@ -1,6 +1,7 @@
|
|||
1.0 "" (released xx.xx.2013)
|
||||
|
||||
* Add support for grepping in archive contents.
|
||||
* Add support for searching in archive contents.
|
||||
* Allow multiple --verbose options to increase program output.
|
||||
* Fixed Python lzma archive handling.
|
||||
* Fixed lzop, lrzip and rzip archive handling.
|
||||
* Fixed Python 3.x support.
|
||||
|
|
|
|||
75
doc/patool.1
75
doc/patool.1
|
|
@ -15,15 +15,9 @@
|
|||
.SH NAME
|
||||
patool - portable command line archive file manager
|
||||
.SH SYNOPSIS
|
||||
\fBpatool\fP (\fBlist\fP|\fBtest\fP) [\fB\-\-verbose\fP] <\fIarchive-file\fP>...
|
||||
\fBpatool\fP \fBextract\fP [\fB\-\-verbose\fP] [\fB\-\-outdir=\fP\fIDIRNAME\fP] <\fIarchive-file\fP>...
|
||||
\fBpatool\fP \fBcreate\fP [\fB\-\-verbose\fP] <\fIarchive-file\fP> [\fIfiles\fP...]
|
||||
\fBpatool\fP \fBdiff\fP [\fB\-\-verbose\fP] <\fIarchive1\fP> <\fIarchive2\fP>
|
||||
\fBpatool\fP \fBsearch\fP [\fB\-\-verbose\fP] <\fIpattern\fP> <\fIarchive-file\fP>...
|
||||
\fBpatool\fP \fBrepack\fP [\fB\-\-verbose\fP] <\fIarchive1\fP> <\fIarchive2\fP>
|
||||
\fBpatool\fP \fBformats\fP
|
||||
\fBpatool\fP [\fIglobal-options\fP] (\fBlist\fP|\fBtest\fP|\fBextract\fP|\fBcreate\fP|\fBdiff\fP|\fBsearch\fP|\fBrepack\fP|\fBformats\fP) [\fIcommand-options\fP] <\fIcommand-arguments\fP>...
|
||||
.SH DESCRIPTION
|
||||
Various archive types can be created, extracted, tested and listed by
|
||||
Various archive types can be created, extracted, tested, listed, searched, repacked and compared by
|
||||
\fBpatool\fP. The advantage of patool is its simplicity in handling archive
|
||||
files without having to remember a myriad of programs and options.
|
||||
.PP
|
||||
|
|
@ -39,67 +33,90 @@ TAR (.tar), XZ (.xz), ZIP (.zip, .jar) and ZOO (.zoo) formats.
|
|||
It relies on helper applications to handle those archive formats
|
||||
(for example bzip2 for BZIP2 archives).
|
||||
.PP
|
||||
The archive formats TAR (.tar), ZIP (.zip), BZIP2 (.bz2) and GZIP (.gz)
|
||||
The archive formats TAR, ZIP, BZIP2 and GZIP
|
||||
are supported natively and do not require helper applications to be
|
||||
installed.
|
||||
.SH EXAMPLES
|
||||
\fBpatool extract archive.zip otherarchive.rar\fP
|
||||
\fBpatool test --verbose dist.tar.gz\fP
|
||||
\fBpatool --verbose test dist.tar.gz\fP
|
||||
\fBpatool list package.deb\fP
|
||||
\fPpatool create --verbose myfiles.zip file1.txt dir/\fP
|
||||
\fPpatool --verbose create myfiles.zip file1.txt dir/\fP
|
||||
\fBpatool diff release1.0.tar.gz release2.0.zip\fP
|
||||
\fBpatool search "def urlopen" python-3.3.tar.gz\fP
|
||||
\fBpatool repack linux-2.6.33.tar.gz linux-2.6.33.tar.bz2\fP
|
||||
.SH GLOBAL OPTIONS
|
||||
.TP
|
||||
\fB\-v\fP, \fB\-\-verbose\fP
|
||||
Display more info about what patool does, and display the output
|
||||
of helper applications. Can be given multiple times to increase
|
||||
the output even more.
|
||||
.SH COMMANDS
|
||||
The following rules apply to all commands:
|
||||
.IP "\(bu" 4
|
||||
Existing files are never overwritten.
|
||||
.IP "\(bu" 4
|
||||
The original archive will never be removed.
|
||||
.IP "\(bu" 4
|
||||
Verbose operation displays more info about what patool does. It also
|
||||
displays more info from the helper application if it's supported.
|
||||
.PP
|
||||
Several commands are available.
|
||||
The following commands are available.
|
||||
.SS extract
|
||||
Extract files from an archive. The original archive will never
|
||||
be removed and is left as it is.
|
||||
.br
|
||||
This is the default command if no command was given.
|
||||
\fBpatool\fP \fBextract\fP [\fIoptions\fP] <\fIarchive\fP>...
|
||||
.PP
|
||||
Extract files from given archives. The original archives will never
|
||||
be removed and are left as is.
|
||||
.PP
|
||||
Options:
|
||||
.TP
|
||||
\fB\-\-outdir\fP DIRECTORY
|
||||
Extract to the given output directory. Default is to extract to
|
||||
the current working directory.
|
||||
.PP
|
||||
If the archive contains exactly one
|
||||
file or directory, the archive contents are extracted to the current
|
||||
working directory.
|
||||
Else the files are extracted in a newly created subdirectory of the current
|
||||
working directory. The new directory is named after the archive filename without
|
||||
file or directory, the archive contents are extracted directly to the
|
||||
output directory.
|
||||
Else the files are extracted in a newly created subdirectory of the output
|
||||
directory. The new directory is named after the archive filename without
|
||||
the extension.
|
||||
.br
|
||||
This prevents cluttering the current working directory with a lot
|
||||
This prevents cluttering the output directory with a lot
|
||||
of files from the extracted archive.
|
||||
.PP
|
||||
All extracted files are ensured that they are readable by the
|
||||
current user.
|
||||
.SS list
|
||||
List files in an archive.
|
||||
\fBpatool\fP \fBlist\fP <\fIarchive\fP>...
|
||||
.PP
|
||||
List files in archives.
|
||||
.SS create
|
||||
Create an archive from given files. At least on of the given files to add
|
||||
to the archive has to exist (non-existing files are ignored).
|
||||
\fBpatool\fP \fBcreate\fP <\fIarchive\fP> <\fIfile-or-directory\fP>...
|
||||
.PP
|
||||
Create an archive from given files. All of the given files to add
|
||||
to the archive must be readable by the current user.
|
||||
The format of the archive to create is determined by the archive file
|
||||
extension.
|
||||
.SS test
|
||||
Test files in an archive. If the helper application does not support
|
||||
\fBpatool\fP \fBtest\fP <\fIarchive\fP>...
|
||||
.PP
|
||||
Test the given archives. If the helper application does not support
|
||||
testing, the archive contents are listed instead.
|
||||
.SS diff
|
||||
\fBpatool\fP \fBdiff\fP <\fIarchive1\fP> <\fIarchive2\fP>
|
||||
.PP
|
||||
Show differences between two archives with the \fBdiff(1)\fP program.
|
||||
The diff options used are \fB\-urN\fP.
|
||||
.SS search
|
||||
\fBpatool\fP \fBsearch\fP <\fIpattern\fP> <\fIarchive\fP>
|
||||
.PP
|
||||
Search in archive contents for given pattern using the \fBgrep(1)\fP program.
|
||||
The grep options used are \fB\-r\fP; additional options can be supplied
|
||||
with the \fBGREP_OPTIONS\fP environment variable.
|
||||
.SS repack
|
||||
\fBpatool\fP \fBrepack\fP <\fIarchive\fP> <\fIarchive_new\fP>
|
||||
.PP
|
||||
Repackage archive to a different format. The target archive format is
|
||||
determined by the file extension.
|
||||
determined by the file extension of \fIarchive_new\fP.
|
||||
.SS formats
|
||||
\fBpatool\fP \fBformats\fP
|
||||
.PP
|
||||
Show all supported archive formats (ie. which helper applications
|
||||
are available).
|
||||
.SH HELP OPTION
|
||||
|
|
|
|||
104
doc/patool.txt
104
doc/patool.txt
|
|
@ -6,46 +6,47 @@ NAME
|
|||
patool - portable command line archive file manager
|
||||
|
||||
SYNOPSIS
|
||||
patool (list|test) [--verbose] <archive-file>...
|
||||
patool extract [--verbose] [--outdir=DIRNAME] <archive-
|
||||
file>...
|
||||
patool create [--verbose] <archive-file> [files...]
|
||||
patool diff [--verbose] <archive1> <archive2>
|
||||
patool search [--verbose] <pattern> <archive-file>...
|
||||
patool repack [--verbose] <archive1> <archive2>
|
||||
patool formats
|
||||
patool [global-options]
|
||||
(list|test|extract|create|diff|search|repack|formats)
|
||||
[command-options] <command-arguments>...
|
||||
|
||||
DESCRIPTION
|
||||
Various archive types can be created, extracted, tested and
|
||||
listed by patool. The advantage of patool is its simplicity in
|
||||
handling archive files without having to remember a myriad of
|
||||
programs and options.
|
||||
Various archive types can be created, extracted, tested,
|
||||
listed, searched, repacked and compared by patool. The advan‐
|
||||
tage of patool is its simplicity in handling archive files
|
||||
without having to remember a myriad of programs and options.
|
||||
|
||||
The archive format is determined by the file(1) program and as
|
||||
The archive format is determined by the file(1) program and as
|
||||
a fallback by the archive file extension.
|
||||
|
||||
patool supports 7z (.7z), ACE (.ace), ADF (.adf), ALZIP (.alz),
|
||||
APE (.ape), AR (.a), ARC (.arc), ARJ (.arj), BZIP2 (.bz2), CAB
|
||||
(.cab), compress (.Z), CPIO (.cpio), DEB (.deb), DMS (.dms),
|
||||
FLAC (.flac), GZIP (.gz), LRZIP (.lrz), LZH (.lha, .lzh), LZIP
|
||||
(.lz), LZMA (.lzma), LZOP (.lzo), RPM (.rpm), RAR (.rar), RZIP
|
||||
(.rz), SHN (.shn), TAR (.tar), XZ (.xz), ZIP (.zip, .jar) and
|
||||
APE (.ape), AR (.a), ARC (.arc), ARJ (.arj), BZIP2 (.bz2), CAB
|
||||
(.cab), compress (.Z), CPIO (.cpio), DEB (.deb), DMS (.dms),
|
||||
FLAC (.flac), GZIP (.gz), LRZIP (.lrz), LZH (.lha, .lzh), LZIP
|
||||
(.lz), LZMA (.lzma), LZOP (.lzo), RPM (.rpm), RAR (.rar), RZIP
|
||||
(.rz), SHN (.shn), TAR (.tar), XZ (.xz), ZIP (.zip, .jar) and
|
||||
ZOO (.zoo) formats. It relies on helper applications to handle
|
||||
those archive formats (for example bzip2 for BZIP2 archives).
|
||||
|
||||
The archive formats TAR (.tar), ZIP (.zip), BZIP2 (.bz2) and
|
||||
GZIP (.gz) are supported natively and do not require helper
|
||||
applications to be installed.
|
||||
The archive formats TAR, ZIP, BZIP2 and GZIP are supported
|
||||
natively and do not require helper applications to be
|
||||
installed.
|
||||
|
||||
EXAMPLES
|
||||
patool extract archive.zip otherarchive.rar
|
||||
patool test --verbose dist.tar.gz
|
||||
patool --verbose test dist.tar.gz
|
||||
patool list package.deb
|
||||
patool create --verbose myfiles.zip file1.txt dir/
|
||||
patool --verbose create myfiles.zip file1.txt dir/
|
||||
patool diff release1.0.tar.gz release2.0.zip
|
||||
patool search "def urlopen" python-3.3.tar.gz
|
||||
patool repack linux-2.6.33.tar.gz linux-2.6.33.tar.bz2
|
||||
|
||||
GLOBAL OPTIONS
|
||||
-v, --verbose
|
||||
Display more info about what patool does, and display
|
||||
the output of helper applications. Can be given multiple
|
||||
times to increase the output even more.
|
||||
|
||||
COMMANDS
|
||||
The following rules apply to all commands:
|
||||
|
||||
|
|
@ -53,55 +54,72 @@ COMMANDS
|
|||
|
||||
· The original archive will never be removed.
|
||||
|
||||
· Verbose operation displays more info about what patool
|
||||
does. It also displays more info from the helper applica‐
|
||||
tion if it's supported.
|
||||
|
||||
Several commands are available.
|
||||
The following commands are available.
|
||||
|
||||
extract
|
||||
Extract files from an archive. The original archive will never
|
||||
be removed and is left as it is.
|
||||
This is the default command if no command was given.
|
||||
patool extract [options] <archive>...
|
||||
|
||||
Extract files from given archives. The original archives will
|
||||
never be removed and are left as is.
|
||||
|
||||
Options:
|
||||
|
||||
--outdir DIRECTORY
|
||||
Extract to the given output directory. Default is to
|
||||
extract to the current working directory.
|
||||
|
||||
If the archive contains exactly one file or directory, the ar‐
|
||||
chive contents are extracted to the current working directory.
|
||||
chive contents are extracted directly to the output directory.
|
||||
Else the files are extracted in a newly created subdirectory of
|
||||
the current working directory. The new directory is named after
|
||||
the archive filename without the extension.
|
||||
This prevents cluttering the current working directory with a
|
||||
lot of files from the extracted archive.
|
||||
the output directory. The new directory is named after the ar‐
|
||||
chive filename without the extension.
|
||||
This prevents cluttering the output directory with a lot of
|
||||
files from the extracted archive.
|
||||
|
||||
All extracted files are ensured that they are readable by the
|
||||
current user.
|
||||
|
||||
list
|
||||
List files in an archive.
|
||||
patool list <archive>...
|
||||
|
||||
List files in archives.
|
||||
|
||||
create
|
||||
Create an archive from given files. At least on of the given
|
||||
files to add to the archive has to exist (non-existing files
|
||||
are ignored). The format of the archive to create is deter‐
|
||||
mined by the archive file extension.
|
||||
patool create <archive> <file-or-directory>...
|
||||
|
||||
Create an archive from given files. All of the given files to
|
||||
add to the archive must be readable by the current user. The
|
||||
format of the archive to create is determined by the archive
|
||||
file extension.
|
||||
|
||||
test
|
||||
Test files in an archive. If the helper application does not
|
||||
patool test <archive>...
|
||||
|
||||
Test the given archives. If the helper application does not
|
||||
support testing, the archive contents are listed instead.
|
||||
|
||||
diff
|
||||
patool diff <archive1> <archive2>
|
||||
|
||||
Show differences between two archives with the diff(1) program.
|
||||
The diff options used are -urN.
|
||||
|
||||
search
|
||||
patool search <pattern> <archive>
|
||||
|
||||
Search in archive contents for given pattern using the grep(1)
|
||||
program. The grep options used are -r; additional options can
|
||||
be supplied with the GREP_OPTIONS environment variable.
|
||||
|
||||
repack
|
||||
patool repack <archive> <archive_new>
|
||||
|
||||
Repackage archive to a different format. The target archive
|
||||
format is determined by the file extension.
|
||||
format is determined by the file extension of archive_new.
|
||||
|
||||
formats
|
||||
patool formats
|
||||
|
||||
Show all supported archive formats (ie. which helper applica‐
|
||||
tions are available).
|
||||
|
||||
|
|
|
|||
182
patool
182
patool
|
|
@ -15,93 +15,149 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
patool [extract|list|create|formats] [sub-command-options] <command-args>
|
||||
patool [global-options] {extract|list|create|diff|search|formats} [sub-command-options] <command-args>
|
||||
"""
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
from patoolib import handle_archive, list_formats, baker
|
||||
|
||||
# parameter help and short options
|
||||
params = {
|
||||
"verbose": "Verbose operation (if the helper application supports it).",
|
||||
}
|
||||
shortopts = {"verbose": "v"}
|
||||
import argparse
|
||||
import patoolib
|
||||
from patoolib.util import log_error, log_internal_error, PatoolError
|
||||
|
||||
|
||||
def handle_multi_archive(archives, cmd, **kwargs):
|
||||
"""Handle a multi-archive command."""
|
||||
def run_extract(args):
|
||||
"""Extract files from archive(s)."""
|
||||
res = 0
|
||||
for archive in archives:
|
||||
if not os.path.isfile(archive):
|
||||
res = 1
|
||||
msg = "archive %r is not a file" % archive
|
||||
print("patool error:", msg, file=sys.stderr)
|
||||
else:
|
||||
newres = handle_archive(archive, cmd, **kwargs)
|
||||
# return error if one of the archives could not be extracted
|
||||
if newres:
|
||||
res = newres
|
||||
for archive in args.archive:
|
||||
try:
|
||||
patoolib.extract_archive(archive, verbosity=args.verbosity, outdir=args.outdir)
|
||||
except PatoolError as msg:
|
||||
log_error("error extracting %s: %s" % (archive, msg))
|
||||
res += 1
|
||||
return res
|
||||
|
||||
|
||||
extract_params = {
|
||||
"outdir": "Extract to given directory.",
|
||||
}
|
||||
extract_params.update(params)
|
||||
@baker.command(default=True, shortopts=shortopts, params=extract_params)
|
||||
def extract (archive, *archives, **kwargs):
|
||||
"""Extract files from archive(s)."""
|
||||
return handle_multi_archive((archive,)+archives, 'extract', **kwargs)
|
||||
|
||||
|
||||
@baker.command(shortopts=shortopts, params=params)
|
||||
def list (archive, *archives, **kwargs):
|
||||
def run_list(args):
|
||||
"""List files in archive(s)."""
|
||||
return handle_multi_archive((archive,)+archives, 'list', **kwargs)
|
||||
res = 0
|
||||
for archive in args.archive:
|
||||
try:
|
||||
patoolib.list_archive(archive, verbosity=args.verbosity)
|
||||
except PatoolError as msg:
|
||||
log_error("error listing %s: %s" % (archive, msg))
|
||||
res += 1
|
||||
return res
|
||||
|
||||
|
||||
@baker.command(shortopts=shortopts, params=params)
|
||||
def test (archive, *archives, **kwargs):
|
||||
def run_test(args):
|
||||
"""Test files in archive(s)."""
|
||||
return handle_multi_archive((archive,)+archives, 'test', **kwargs)
|
||||
res = 0
|
||||
for archive in args.archive:
|
||||
try:
|
||||
patoolib.test_archive(archive, verbosity=args.verbosity)
|
||||
except PatoolError as msg:
|
||||
log_error("error testing %s: %s" % (archive, msg))
|
||||
res += 1
|
||||
return res
|
||||
|
||||
|
||||
@baker.command(shortopts=shortopts, params=params)
|
||||
def create (archive, file1, *files, **kwargs):
|
||||
def run_create(args):
|
||||
"""Create an archive from given files."""
|
||||
return handle_archive(archive, 'create', file1, *files, **kwargs)
|
||||
res = 0
|
||||
try:
|
||||
patoolib.create_archive(args.archive, args.filename, verbosity=args.verbosity)
|
||||
except PatoolError as msg:
|
||||
log_error("error creating %s: %s" % (args.archive, msg))
|
||||
res = 1
|
||||
return res
|
||||
|
||||
|
||||
@baker.command(shortopts=shortopts, params=params)
|
||||
def diff (archive1, archive2, **kwargs):
|
||||
def run_diff(args):
|
||||
"""Show differences between two archives."""
|
||||
from patoolib import diff
|
||||
return diff(archive1, archive2, **kwargs)
|
||||
try:
|
||||
res = patoolib.diff_archives(args.archive1, args.archive2, verbosity=args.verbosity)
|
||||
except PatoolError as msg:
|
||||
log_error("error showing differences between %s and %s: %s" % (args.archive1, args.archive2, msg))
|
||||
res = 2
|
||||
return res
|
||||
|
||||
|
||||
@baker.command(shortopts=shortopts, params=params)
|
||||
def search(pattern, archive1, *archives, **kwargs):
|
||||
"""Search for pattern in all given archives."""
|
||||
from patoolib import search
|
||||
return search(pattern, archive1, *archives, **kwargs)
|
||||
def run_search(args):
|
||||
"""Search for pattern in given archive."""
|
||||
try:
|
||||
res = patoolib.search_archive(args.pattern, args.archive, verbosity=args.verbosity)
|
||||
except PatoolError as msg:
|
||||
log_error("error searching %s: %s" % (args.archive, msg))
|
||||
res = 2
|
||||
return res
|
||||
|
||||
|
||||
@baker.command(shortopts=shortopts, params=params)
|
||||
def repack (archive1, archive2, **kwargs):
|
||||
def run_repack(args):
|
||||
"""Repackage one archive in another format."""
|
||||
from patoolib import repack
|
||||
return repack(archive1, archive2, **kwargs)
|
||||
res = 0
|
||||
try:
|
||||
patoolib.repack_archive(args.archive_src, args.archive_dst, verbosity=args.verbosity)
|
||||
except PatoolError as msg:
|
||||
log_error("error repacking %s: %s" % (args.archive_src, msg))
|
||||
res = 1
|
||||
return res
|
||||
|
||||
|
||||
@baker.command
|
||||
def formats ():
|
||||
def run_formats (args):
|
||||
"""List supported and available archive formats."""
|
||||
return list_formats()
|
||||
patoolib.list_formats()
|
||||
return 0
|
||||
|
||||
try:
|
||||
sys.exit(baker.run())
|
||||
except baker.CommandError as msg:
|
||||
print("patool error:", msg, file=sys.stderr)
|
||||
baker.help(sys.argv[0])
|
||||
sys.exit(1)
|
||||
|
||||
def create_argparser():
|
||||
"""Construct and return an argument parser."""
|
||||
parser = argparse.ArgumentParser(description="A commandline archive handler.")
|
||||
parser.add_argument('--verbose', '-v', action='count', default=0, dest='verbosity', help="verbose operation; can be given multiple times")
|
||||
subparsers = parser.add_subparsers(help='the archive command; type "patool COMMAND -h" for command-specific help', dest='command')
|
||||
# extract
|
||||
parser_extract = subparsers.add_parser('extract', help='extract one or more archives')
|
||||
parser_extract.add_argument('--outdir', help="output directory to extract to")
|
||||
parser_extract.add_argument('archive', nargs='+', help="an archive file")
|
||||
# list
|
||||
parser_list = subparsers.add_parser('list', help='list members or one or more archives')
|
||||
parser_list.add_argument('archive', nargs='+', help="an archive file")
|
||||
# create
|
||||
parser_create = subparsers.add_parser('create', help='create an archive')
|
||||
parser_create.add_argument('archive', help="the archive file; the file extension determines the archive program")
|
||||
parser_create.add_argument('filename', nargs='+', help="a file or directory to add to the archive; note that some archive programs do not support directories")
|
||||
# test
|
||||
parser_test = subparsers.add_parser('test', help='test an archive')
|
||||
parser_test.add_argument('archive', nargs='+', help='an archive file')
|
||||
# repack
|
||||
parser_repack = subparsers.add_parser('repack', help='repack an archive to a different format')
|
||||
parser_repack.add_argument('archive_src', help='source archive file')
|
||||
parser_repack.add_argument('archive_dst', help='target archive file')
|
||||
# diff
|
||||
parser_diff = subparsers.add_parser('diff', help='show differences between two archives')
|
||||
parser_diff.add_argument('archive1', help='the first archive file')
|
||||
parser_diff.add_argument('archive2', help='the second archive file')
|
||||
# search
|
||||
parser_search = subparsers.add_parser('search', help="search contents of archive members")
|
||||
parser_search.add_argument('pattern', help='the grep(1) compatible search pattern')
|
||||
parser_search.add_argument('archive', help='the archive file')
|
||||
# formats
|
||||
subparsers.add_parser('formats', help="show supported archive formats")
|
||||
return parser
|
||||
|
||||
|
||||
def main():
|
||||
"""Parse options and execute commands."""
|
||||
try:
|
||||
argparser = create_argparser()
|
||||
args = argparser.parse_args()
|
||||
# run subcommand function
|
||||
return globals()["run_%s" % args.command](args)
|
||||
except KeyboardInterrupt:
|
||||
log_error("aborted")
|
||||
res = 1
|
||||
except Exception:
|
||||
log_internal_error()
|
||||
res = 2
|
||||
return res
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ import shutil
|
|||
import stat
|
||||
import importlib
|
||||
from . import util
|
||||
__all__ = ['list_formats', 'list_archive', 'extract_archive', 'test_archive',
|
||||
'create_archive', 'diff_archives', 'search_archive', 'repack_archive']
|
||||
|
||||
|
||||
# Supported archive commands
|
||||
ArchiveCommands = ('list', 'extract', 'test', 'create')
|
||||
|
|
@ -348,10 +351,9 @@ def list_formats ():
|
|||
handlers = programs.get(None, programs.get(command))
|
||||
print(" %8s: - (no program found; install %s)" %
|
||||
(command, util.strlist_with_or(handlers)))
|
||||
return 0
|
||||
|
||||
|
||||
AllowedConfigKeys = ("verbose", "program")
|
||||
AllowedConfigKeys = ("verbosity", "program")
|
||||
|
||||
def clean_config_keys (kwargs):
|
||||
"""Remove invalid configuration keys from arguments."""
|
||||
|
|
@ -369,7 +371,7 @@ def parse_config (archive, format, compression, command, **kwargs):
|
|||
is not supported.
|
||||
"""
|
||||
config = {
|
||||
'verbose': False,
|
||||
'verbosity': 0,
|
||||
}
|
||||
config['program'] = find_archive_program(format, command)
|
||||
for key, value in kwargs.items():
|
||||
|
|
@ -410,14 +412,14 @@ def move_outdir_orphan (outdir):
|
|||
return (False, "multiple files in root")
|
||||
|
||||
|
||||
def run_archive_cmdlist (archive_cmdlist):
|
||||
def run_archive_cmdlist (archive_cmdlist, verbosity=0):
|
||||
"""Run archive command."""
|
||||
# archive_cmdlist is a command list with optional keyword arguments
|
||||
if isinstance(archive_cmdlist, tuple):
|
||||
cmdlist, runkwargs = archive_cmdlist
|
||||
else:
|
||||
cmdlist, runkwargs = archive_cmdlist, {}
|
||||
util.run_checked(cmdlist, **runkwargs)
|
||||
return util.run_checked(cmdlist, verbosity=verbosity, **runkwargs)
|
||||
|
||||
|
||||
def make_file_readable (filename):
|
||||
|
|
@ -458,31 +460,6 @@ def cleanup_outdir (outdir, archive):
|
|||
return outdir2, "`%s' (%s)" % (outdir2, msg)
|
||||
|
||||
|
||||
def check_archive_arguments (archive, command, *args):
|
||||
"""Check for invalid archive command arguments."""
|
||||
if command == 'create':
|
||||
util.check_archive_filelist(args)
|
||||
util.check_new_filename(archive)
|
||||
elif command == 'repack':
|
||||
util.check_existing_filename(archive)
|
||||
if not args:
|
||||
raise util.PatoolError("missing target archive filename for repack")
|
||||
util.check_new_filename(args[0])
|
||||
elif command == 'diff':
|
||||
util.check_existing_filename(archive)
|
||||
if not args:
|
||||
raise util.PatoolError("missing second archive filename for diff")
|
||||
util.check_existing_filename(args[0])
|
||||
elif command == 'search':
|
||||
if not archive:
|
||||
# archive is the search pattern
|
||||
raise util.PatoolError("empty search pattern")
|
||||
for arg in args:
|
||||
util.check_existing_filename(arg)
|
||||
else:
|
||||
util.check_existing_filename(archive)
|
||||
|
||||
|
||||
def _handle_archive (archive, command, *args, **kwargs):
|
||||
"""Handle archive command; raising PatoolError on errors.
|
||||
@return: output directory if command is 'extract', else None
|
||||
|
|
@ -494,16 +471,13 @@ def _handle_archive (archive, command, *args, **kwargs):
|
|||
check_archive_command(command)
|
||||
config_kwargs = clean_config_keys(kwargs)
|
||||
config = parse_config(archive, format, compression, command, **config_kwargs)
|
||||
# check if archive already exists
|
||||
if command == 'create' and os.path.exists(archive):
|
||||
raise util.PatoolError("archive `%s' already exists" % archive)
|
||||
program = config['program']
|
||||
get_archive_cmdlist = get_archive_cmdlist_func(program, command, format)
|
||||
# prepare keyword arguments for command list
|
||||
cmd_kwargs = dict(verbose=config['verbose'])
|
||||
cmd_kwargs = dict(verbosity=config['verbosity'])
|
||||
origarchive = None
|
||||
if command == 'extract':
|
||||
if "outdir" in kwargs:
|
||||
if kwargs.get('outdir'):
|
||||
cmd_kwargs["outdir"] = kwargs["outdir"]
|
||||
do_cleanup_outdir = False
|
||||
else:
|
||||
|
|
@ -520,13 +494,14 @@ def _handle_archive (archive, command, *args, **kwargs):
|
|||
# an empty command list means the get_archive_cmdlist() function
|
||||
# already handled the command (eg. when it's a builtin Python
|
||||
# function)
|
||||
run_archive_cmdlist(cmdlist)
|
||||
run_archive_cmdlist(cmdlist, verbosity=config['verbosity'])
|
||||
if command == 'extract':
|
||||
if do_cleanup_outdir:
|
||||
target, msg = cleanup_outdir(cmd_kwargs["outdir"], archive)
|
||||
util.log_info("%s extracted to %s" % (archive, msg))
|
||||
else:
|
||||
target, msg = cmd_kwargs["outdir"], "`%s'" % cmd_kwargs["outdir"]
|
||||
if config['verbosity'] >= 0:
|
||||
util.log_info("... %s extracted to %s." % (archive, msg))
|
||||
return target
|
||||
elif command == 'create' and origarchive:
|
||||
shutil.move(archive, origarchive)
|
||||
|
|
@ -561,11 +536,12 @@ def rmtree_log_error (func, path, exc):
|
|||
util.log_error(msg)
|
||||
|
||||
|
||||
def _diff_archives (archive1, archive2, **kwargs):
|
||||
"""Show differences between two archives."""
|
||||
def _diff_archives (archive1, archive2, verbosity=0):
|
||||
"""Show differences between two archives.
|
||||
@return 0 if archives are the same, else 1
|
||||
@raises: PatoolError on errors
|
||||
"""
|
||||
if util.is_same_file(archive1, archive2):
|
||||
msg = "no differences found: archive `%s' and `%s' are the same files"
|
||||
util.log_info(msg % (archive1, archive2))
|
||||
return 0
|
||||
diff = util.find_program("diff")
|
||||
if not diff:
|
||||
|
|
@ -573,65 +549,51 @@ def _diff_archives (archive1, archive2, **kwargs):
|
|||
raise util.PatoolError(msg)
|
||||
tmpdir1 = util.tmpdir()
|
||||
try:
|
||||
path1 = _handle_archive(archive1, 'extract', outdir=tmpdir1, **kwargs)
|
||||
path1 = _handle_archive(archive1, 'extract', outdir=tmpdir1, verbosity=-1)
|
||||
tmpdir2 = util.tmpdir()
|
||||
try:
|
||||
path2 = _handle_archive(archive2, 'extract', outdir=tmpdir2, **kwargs)
|
||||
return util.run([diff, "-urN", path1, path2])
|
||||
path2 = _handle_archive(archive2, 'extract', outdir=tmpdir2, verbosity=-1)
|
||||
return util.run_checked([diff, "-urN", path1, path2], verbosity=1, ret_ok=(0, 1))
|
||||
finally:
|
||||
shutil.rmtree(tmpdir2, onerror=rmtree_log_error)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir1, onerror=rmtree_log_error)
|
||||
|
||||
|
||||
def _search_archives(pattern, *archives, **kwargs):
|
||||
"""Search for given pattern in all archives."""
|
||||
def _search_archive(pattern, archive, verbosity=0):
|
||||
"""Search for given pattern in an archive."""
|
||||
grep = util.find_program("grep")
|
||||
if not grep:
|
||||
msg = "The grep(1) program is required for searching archive contents, please install it."
|
||||
raise util.PatoolError(msg)
|
||||
errors = 0
|
||||
for archive in archives:
|
||||
try:
|
||||
errors += _search_archive(grep, pattern, archive, **kwargs)
|
||||
except util.PatoolError as msg:
|
||||
util.log_error("grep error: %s" % msg)
|
||||
errors += 1
|
||||
return errors
|
||||
|
||||
|
||||
def _search_archive(grep, pattern, archive, **kwargs):
|
||||
"""Extract one archive and search for given pattern in extracted files."""
|
||||
tmpdir = util.tmpdir()
|
||||
try:
|
||||
_handle_archive(archive, 'extract', outdir=tmpdir, **kwargs)
|
||||
return util.run([grep, "-r", "-e", pattern, "."], cwd=tmpdir)
|
||||
path = _handle_archive(archive, 'extract', outdir=tmpdir, verbosity=-1)
|
||||
return util.run_checked([grep, "-r", "-e", pattern, "."], ret_ok=(0, 1), verbosity=1, cwd=path)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir, onerror=rmtree_log_error)
|
||||
|
||||
|
||||
def _repack_archive (archive1, archive2, **kwargs):
|
||||
def _repack_archive (archive1, archive2, verbosity=0):
|
||||
"""Repackage an archive to a different format."""
|
||||
format1, compression1 = get_archive_format(archive1)
|
||||
format2, compression2 = get_archive_format(archive2)
|
||||
if format1 == format2 and compression1 == compression2:
|
||||
# same format and compression allows to copy the file
|
||||
try:
|
||||
util.link_or_copy(archive1, archive2, verbose=kwargs.get('verbose'))
|
||||
return 0
|
||||
except OSError:
|
||||
return 1
|
||||
util.link_or_copy(archive1, archive2, verbosity=verbosity)
|
||||
return
|
||||
tmpdir = util.tmpdir()
|
||||
try:
|
||||
kwargs = dict(verbosity=verbosity, outdir=tmpdir)
|
||||
same_format = (format1 == format2 and compression1 and compression2)
|
||||
if same_format:
|
||||
# only decompress since the format is the same
|
||||
kwargs['format'] = compression1
|
||||
_handle_archive(archive1, 'extract', outdir=tmpdir, **kwargs)
|
||||
path = _handle_archive(archive1, 'extract', **kwargs)
|
||||
archive = os.path.abspath(archive2)
|
||||
files = tuple(os.listdir(tmpdir))
|
||||
files = tuple(os.listdir(path))
|
||||
olddir = os.getcwd()
|
||||
os.chdir(tmpdir)
|
||||
os.chdir(path)
|
||||
try:
|
||||
if same_format:
|
||||
# only compress since the format is the same
|
||||
|
|
@ -639,68 +601,82 @@ def _repack_archive (archive1, archive2, **kwargs):
|
|||
_handle_archive(archive, 'create', *files, **kwargs)
|
||||
finally:
|
||||
os.chdir(olddir)
|
||||
return 0
|
||||
finally:
|
||||
shutil.rmtree(tmpdir, onerror=rmtree_log_error)
|
||||
|
||||
|
||||
def handle_archive (archive, command, *args, **kwargs):
|
||||
"""Handle archive file command; with nice error reporting."""
|
||||
check_archive_arguments(archive, command, *args)
|
||||
try:
|
||||
if command == "diff":
|
||||
res = _diff_archives(archive, args[0], **kwargs)
|
||||
elif command == "search":
|
||||
res = _search_archives(archive, *args, **kwargs)
|
||||
elif command == "repack":
|
||||
res = _repack_archive(archive, args[0], **kwargs)
|
||||
else:
|
||||
_handle_archive(archive, command, *args, **kwargs)
|
||||
res = 0
|
||||
except KeyboardInterrupt:
|
||||
util.log_error("aborted")
|
||||
res = 1
|
||||
except util.PatoolError as msg:
|
||||
util.log_error(msg)
|
||||
res = 1
|
||||
except Exception as msg:
|
||||
util.log_internal_error()
|
||||
res = 1
|
||||
# the patool library API
|
||||
|
||||
def extract_archive(archive, verbosity=0, outdir=None, program=None):
|
||||
"""Extract given archive."""
|
||||
util.check_existing_filename(archive)
|
||||
if verbosity >= 0:
|
||||
util.log_info("Extracting %s ..." % archive)
|
||||
return _handle_archive(archive, 'extract', verbosity=verbosity, outdir=outdir, program=program)
|
||||
|
||||
|
||||
def list_archive(archive, verbosity=0, program=None):
|
||||
"""List given archive."""
|
||||
util.check_existing_filename(archive)
|
||||
if verbosity >= 0:
|
||||
util.log_info("Listing %s ..." % archive)
|
||||
return _handle_archive(archive, 'list', verbosity=verbosity, program=program)
|
||||
|
||||
|
||||
def test_archive(archive, verbosity=0, program=None):
|
||||
"""Test given archive."""
|
||||
util.check_existing_filename(archive)
|
||||
if verbosity >= 0:
|
||||
util.log_info("Testing %s ..." % archive)
|
||||
res = _handle_archive(archive, 'test', verbosity=verbosity, program=program)
|
||||
if verbosity >= 0:
|
||||
util.log_info("... tested ok.")
|
||||
return res
|
||||
|
||||
|
||||
# convenience functions
|
||||
|
||||
def extract (archive, verbose=False, outdir=None):
|
||||
"""Extract given archive."""
|
||||
return handle_archive(archive, 'extract', verbose=verbose, outdir=outdir)
|
||||
|
||||
|
||||
def list (archive, verbose=False):
|
||||
"""List given archive."""
|
||||
return handle_archive(archive, 'list', verbose=verbose)
|
||||
|
||||
|
||||
def test (archive, verbose=False):
|
||||
"""Test given archive."""
|
||||
return handle_archive(archive, 'test', verbose=verbose)
|
||||
|
||||
|
||||
def create (archive, *filenames, **kwargs):
|
||||
def create_archive(archive, filenames, verbosity=0, program=None):
|
||||
"""Create given archive with given files."""
|
||||
return handle_archive(archive, 'create', *filenames, **kwargs)
|
||||
util.check_new_filename(archive)
|
||||
util.check_archive_filelist(filenames)
|
||||
if verbosity >= 0:
|
||||
util.log_info("Creating %s ..." % archive)
|
||||
res = _handle_archive(archive, 'create', *tuple(filenames), verbosity=verbosity, program=program)
|
||||
if verbosity >= 0:
|
||||
util.log_info("... %s created." % archive)
|
||||
return res
|
||||
|
||||
|
||||
def diff (archive1, archive2, verbose=False):
|
||||
def diff_archives(archive1, archive2, verbosity=0):
|
||||
"""Print differences between two archives."""
|
||||
return handle_archive(archive1, 'diff', archive2, verbose=verbose)
|
||||
util.check_existing_filename(archive1)
|
||||
util.check_existing_filename(archive2)
|
||||
if verbosity >= 0:
|
||||
util.log_info("Comparing %s with %s ..." % (archive1, archive2))
|
||||
res = _diff_archives(archive1, archive2, verbosity=verbosity)
|
||||
if res == 0 and verbosity >= 0:
|
||||
util.log_info("... no differences found.")
|
||||
|
||||
|
||||
def search(pattern, *archives, **kwargs):
|
||||
def search_archive(pattern, archive, verbosity=0):
|
||||
"""Search pattern in archive members."""
|
||||
return handle_archive(pattern, 'search', *archives, **kwargs)
|
||||
if not pattern:
|
||||
raise util.PatoolError("empty search pattern")
|
||||
util.check_existing_filename(archive)
|
||||
if verbosity >= 0:
|
||||
util.log_info("Searching %r in %s ..." % (pattern, archive))
|
||||
res = _search_archive(pattern, archive, verbosity=verbosity)
|
||||
if res == 1 and verbosity >= 0:
|
||||
util.log_info("... %r not found" % pattern)
|
||||
return res
|
||||
|
||||
|
||||
def repack (archive1, archive2, verbose=False):
|
||||
def repack_archive (archive, archive_new, verbosity=0):
|
||||
"""Repack archive to different file and/or format."""
|
||||
return handle_archive(archive1, 'repack', archive2, verbose=verbose)
|
||||
util.check_existing_filename(archive)
|
||||
util.check_new_filename(archive_new)
|
||||
if verbosity >= 0:
|
||||
util.log_info("Repacking %s to %s ..." % (archive, archive_new))
|
||||
res = _repack_archive(archive, archive_new, verbosity=verbosity)
|
||||
if verbosity >= 0:
|
||||
util.log_info("... repacking successful.")
|
||||
return res
|
||||
|
|
|
|||
|
|
@ -1,586 +0,0 @@
|
|||
#===============================================================================
|
||||
# Copyright 2010 Matt Chaput
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#===============================================================================
|
||||
|
||||
import re, sys
|
||||
from inspect import getargspec
|
||||
from textwrap import wrap
|
||||
|
||||
|
||||
def normalize_docstring(docstring):
|
||||
"""Normalizes whitespace in the given string.
|
||||
"""
|
||||
return re.sub(r"[\r\n\t ]+", " ", docstring).strip()
|
||||
|
||||
|
||||
param_exp = re.compile(r"^([\t ]*):param (.*?): ([^\n]*\n(\1[ \t]+[^\n]*\n)*)",
|
||||
re.MULTILINE)
|
||||
|
||||
def find_param_docs(docstring):
|
||||
"""Finds ReStructuredText-style ":param:" lines in the docstring and
|
||||
returns a dictionary mapping param names to doc strings.
|
||||
"""
|
||||
|
||||
paramdocs = {}
|
||||
for match in param_exp.finditer(docstring):
|
||||
name = match.group(2)
|
||||
value = match.group(3)
|
||||
paramdocs[name] = value
|
||||
return paramdocs
|
||||
|
||||
def remove_param_docs(docstring):
|
||||
"""Finds ReStructuredText-style ":param:" lines in the docstring and
|
||||
returns a new string with the param documentation removed.
|
||||
"""
|
||||
return param_exp.sub("", docstring)
|
||||
|
||||
|
||||
def process_docstring(docstring):
|
||||
"""Takes a docstring and returns a list of strings representing
|
||||
the paragraphs in the docstring.
|
||||
"""
|
||||
|
||||
lines = docstring.split("\n")
|
||||
paras = [[]]
|
||||
for line in lines:
|
||||
if not line.strip():
|
||||
paras.append([])
|
||||
else:
|
||||
paras[-1].append(line)
|
||||
paras = [normalize_docstring(" ".join(ls))
|
||||
for ls in paras if ls]
|
||||
return paras
|
||||
|
||||
|
||||
def format_paras(paras, width, indent=0):
|
||||
"""Takes a list of paragraph strings and formats them into a word-wrapped,
|
||||
optionally indented string.
|
||||
"""
|
||||
|
||||
output = []
|
||||
for para in paras:
|
||||
lines = wrap(para, width-indent)
|
||||
if lines:
|
||||
for line in lines:
|
||||
output.append((" " * indent) + line)
|
||||
output.append("")
|
||||
return "\n".join(output)
|
||||
|
||||
|
||||
def totype(v, default):
|
||||
"""Tries to convert the value 'v' into the same type as 'default'.
|
||||
"""
|
||||
# Python3 does not have long, so fake it
|
||||
try:
|
||||
long
|
||||
except NameError:
|
||||
long = int
|
||||
|
||||
t = type(default)
|
||||
if t is int:
|
||||
return int(v)
|
||||
elif t is float:
|
||||
return float(v)
|
||||
elif t is long:
|
||||
return long(v)
|
||||
elif t is bool:
|
||||
lv = v.lower()
|
||||
if lv in ("true", "yes", "on", "1"):
|
||||
return True
|
||||
elif lv in ("false", "no", "off", "0"):
|
||||
return False
|
||||
else:
|
||||
raise TypeError
|
||||
else:
|
||||
return v
|
||||
|
||||
|
||||
class CommandError(Exception):
|
||||
"""Error for baker commands."""
|
||||
pass
|
||||
|
||||
|
||||
class Cmd(object):
|
||||
"""Stores metadata about a command.
|
||||
"""
|
||||
|
||||
def __init__(self, name, fn, argnames, keywords, shortopts,
|
||||
has_varargs, has_kwargs, docstring, paramdocs):
|
||||
"""Store given metadata."""
|
||||
self.name = name
|
||||
self.fn = fn
|
||||
self.argnames = argnames
|
||||
self.keywords = keywords
|
||||
self.shortopts = shortopts
|
||||
self.has_varargs = has_varargs
|
||||
self.has_kwargs = has_kwargs
|
||||
self.docstring = docstring
|
||||
self.paramdocs = paramdocs
|
||||
self.param_keywords = False
|
||||
|
||||
|
||||
class Baker(object):
|
||||
"""Main class."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize command variables."""
|
||||
self.commands = {}
|
||||
self.defaultcommand = None
|
||||
|
||||
def command(self, fn=None, name=None, default=False,
|
||||
params=None, shortopts=None):
|
||||
"""Registers a command with the bakery. This does not call the
|
||||
function, it simply adds it to the list of functions this Baker
|
||||
knows about.
|
||||
|
||||
This method is usually used as a decorator::
|
||||
|
||||
b = Baker()
|
||||
|
||||
@b.command
|
||||
def test():
|
||||
pass
|
||||
|
||||
:param fn: the function to register.
|
||||
:param name: use this argument to register the command under a
|
||||
different name than the function name.
|
||||
:param default: if True, this command is used when a command is not
|
||||
specified on the command line.
|
||||
:param params: a dictionary mapping parameter names to docstrings. If
|
||||
you don't specify this argument, parameter annotations will be used
|
||||
(Python 3.x only), or the functions docstring will be searched for
|
||||
Sphinx-style ':param' blocks.
|
||||
:param shortopts: a dictionary mapping parameter names to short
|
||||
options, e.g. {"verbose": "v"}.
|
||||
"""
|
||||
|
||||
# This method works as a decorator with or without arguments.
|
||||
if fn is None:
|
||||
# The decorator was given arguments, e.g. @command(default=True),
|
||||
# so we have to return a function that will wrap the function when
|
||||
# the decorator is applied.
|
||||
return lambda fn: self.command(fn, default=default,
|
||||
params=params,
|
||||
shortopts=shortopts)
|
||||
name = name or fn.__name__
|
||||
|
||||
# Inspect the argument signature of the function
|
||||
arglist, vargsname, kwargsname, defaults = getargspec(fn)
|
||||
has_varargs = bool(vargsname)
|
||||
has_kwargs = bool(kwargsname)
|
||||
|
||||
# Get the function's docstring
|
||||
docstring = fn.__doc__ or ""
|
||||
|
||||
# If the user didn't specify parameter help in the decorator
|
||||
# arguments, try to get it from parameter annotations (Python 3.x)
|
||||
# or RST-style :param: lines in the docstring
|
||||
if params is None:
|
||||
if hasattr(fn, "func_annotations") and fn.func_annotations:
|
||||
params = fn.func_annotations
|
||||
else:
|
||||
params = find_param_docs(docstring)
|
||||
docstring = remove_param_docs(docstring)
|
||||
|
||||
# If the user didn't specify
|
||||
shortopts = shortopts or {}
|
||||
|
||||
if defaults:
|
||||
# Zip up the keyword argument names with their defaults
|
||||
keywords = dict(list(zip(arglist[0-len(defaults):], defaults)))
|
||||
elif has_kwargs:
|
||||
# Allow keyword arguments specified by params.
|
||||
keywords = dict(list(zip(params.keys(), [""]*len(params))))
|
||||
# But set a flag to detect this
|
||||
self.param_keywords = True
|
||||
else:
|
||||
keywords = {}
|
||||
|
||||
# If this is a method, remove 'self' from the argument list
|
||||
if arglist and arglist[0] == "self":
|
||||
arglist.pop(0)
|
||||
|
||||
# Create a Cmd object to represent this command and store it
|
||||
cmd = Cmd(name, fn, arglist, keywords, shortopts,
|
||||
has_varargs, has_kwargs,
|
||||
docstring, params)
|
||||
self.commands[cmd.name] = cmd
|
||||
|
||||
# If default is True, set this as the default command
|
||||
if default:
|
||||
self.defaultcommand = cmd
|
||||
|
||||
return fn
|
||||
|
||||
def print_top_help(self, scriptname, file=sys.stdout):
|
||||
"""Prints the documentation for the script and exits.
|
||||
|
||||
:param scriptname: the name of the script being executed (argv[0]).
|
||||
:param file: the file to write the help to. The default is stdout.
|
||||
"""
|
||||
|
||||
# Get a sorted list of all command names
|
||||
cmdnames = sorted(self.commands.keys())
|
||||
|
||||
# Calculate the indent for the doc strings by taking the longest
|
||||
# command name and adding 3 (one space before the name and two after)
|
||||
rindent = max(len(name) for name in cmdnames) + 3
|
||||
|
||||
# Print the basic help for running a command
|
||||
file.write("\nUsage: %s COMMAND <options>\n\n" % scriptname)
|
||||
|
||||
print("Available commands:\n\n")
|
||||
for cmdname in cmdnames:
|
||||
# Get the Cmd object for this command
|
||||
cmd = self.commands[cmdname]
|
||||
|
||||
# Calculate the padding necessary to fill from the end of the
|
||||
# command name to the documentation margin
|
||||
tab = " " * (rindent - (len(cmdname)+1))
|
||||
file.write(" " + cmdname + tab)
|
||||
|
||||
# Get the paragraphs of the command's docstring
|
||||
paras = process_docstring(cmd.docstring)
|
||||
if paras:
|
||||
# Print the first paragraph
|
||||
file.write(format_paras([paras[0]], 76, indent=rindent).lstrip())
|
||||
|
||||
file.write("\n")
|
||||
file.write('Use "%s <command> --help" for individual command help.\n' % scriptname)
|
||||
sys.exit(0)
|
||||
|
||||
def print_command_help(self, scriptname, cmd, file=sys.stdout):
|
||||
"""Prints the documentation for a specific command and exits.
|
||||
|
||||
:param scriptname: the name of the script being executed (argv[0]).
|
||||
:param cmd: the Cmd object representing the command.
|
||||
:param file: the file to write the help to. The default is stdout.
|
||||
"""
|
||||
|
||||
# Print the usage for the command
|
||||
file.write("\nUsage: %s %s" % (scriptname, cmd.name))
|
||||
|
||||
# Print the required and "optional" arguments (where optional
|
||||
# arguments are keyword arguments with default None).
|
||||
for name in cmd.argnames:
|
||||
if name not in cmd.keywords:
|
||||
# This is a positional argument
|
||||
file.write(" <%s>" % name)
|
||||
else:
|
||||
# This is a keyword argument, so skip it unless the default is
|
||||
# None, in which case treat it like an optional argument.
|
||||
if cmd.keywords[name] is None:
|
||||
file.write(" [<%s>]" % name)
|
||||
|
||||
if cmd.has_varargs:
|
||||
# This command accepts a variable number of positional arguments
|
||||
file.write(" [...]")
|
||||
file.write("\n\n")
|
||||
|
||||
# Print the documentation for this command
|
||||
paras = process_docstring(cmd.docstring)
|
||||
if paras:
|
||||
# Print the first paragraph with no indent (usually just a summary
|
||||
# line)
|
||||
file.write(format_paras([paras[0]], 76))
|
||||
|
||||
# Print subsequent paragraphs indented by 4 spaces
|
||||
if len(paras) > 1:
|
||||
file.write("\n")
|
||||
file.write(format_paras(paras[1:], 76, indent=4))
|
||||
file.write("\n")
|
||||
|
||||
# Get a sorted list of keyword argument names
|
||||
keynames = sorted([key for key, value in cmd.keywords.items() if value is not None])
|
||||
# Print documentation for keyword options
|
||||
if keynames:
|
||||
file.write("Options:\n\n")
|
||||
|
||||
# Make formatted headings, e.g. " -k --keyword ", and put them in
|
||||
# a list like [(name, heading), ...]
|
||||
heads = []
|
||||
for keyname in keynames:
|
||||
if cmd.keywords[keyname] is None: continue
|
||||
|
||||
head = " --" + keyname
|
||||
if keyname in cmd.shortopts:
|
||||
head = " -" + cmd.shortopts[keyname] + head
|
||||
head += " "
|
||||
heads.append((keyname, head))
|
||||
|
||||
if heads:
|
||||
# Find the length of the longest formatted heading
|
||||
rindent = max(len(head) for keyname, head in heads)
|
||||
# Pad the headings so they're all as long as the longest one
|
||||
heads = [(keyname, head + (" " * (rindent - len(head))))
|
||||
for keyname, head in heads]
|
||||
|
||||
# Print the option docs
|
||||
for keyname, head in heads:
|
||||
# Print the heading
|
||||
file.write(head)
|
||||
|
||||
# If this parameter has documentation, print it after the
|
||||
# heading
|
||||
if keyname in cmd.paramdocs:
|
||||
paras = process_docstring(cmd.paramdocs.get(keyname, ""))
|
||||
file.write(format_paras(paras, 76, indent=rindent).lstrip())
|
||||
else:
|
||||
file.write("\n")
|
||||
file.write("\n")
|
||||
|
||||
if any((cmd.keywords.get(a) is None) for a in cmd.argnames):
|
||||
file.write("(specifying a single hyphen (-) in the argument list means all\n")
|
||||
file.write("subsequent arguments are treated as bare arguments, not options)\n")
|
||||
file.write("\n")
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
def parse_args(self, scriptname, cmd, argv):
|
||||
"""Parse command arguments."""
|
||||
keywords = cmd.keywords
|
||||
shortopts = cmd.shortopts
|
||||
|
||||
# shortopts maps long option names to characters. To look up short
|
||||
# options, we need to create a reverse mapping.
|
||||
shortchars = dict((v, k) for k, v in shortopts.items())
|
||||
|
||||
# The *vargs list and **kwargs dict to build up from the command line
|
||||
# arguments
|
||||
vargs = []
|
||||
kwargs = {}
|
||||
|
||||
while argv:
|
||||
# Take the next argument
|
||||
arg = argv.pop(0)
|
||||
|
||||
if arg == "--":
|
||||
# All arguments following a double hyphen are treated as
|
||||
# positional arguments
|
||||
vargs.extend(argv)
|
||||
break
|
||||
|
||||
elif arg == "-":
|
||||
# What to do with a bare -? Right now, it's ignored.
|
||||
continue
|
||||
|
||||
elif arg.startswith("--"):
|
||||
# Process long option
|
||||
|
||||
value = None
|
||||
if "=" in arg:
|
||||
# The argument was specified like --keyword=value
|
||||
name, value = arg[2:].split("=", 1)
|
||||
default = keywords.get(name)
|
||||
try:
|
||||
value = totype(value, default)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
# The argument was not specified with a value, assuming
|
||||
# this is a flag
|
||||
name = arg[2:]
|
||||
default = keywords.get(name)
|
||||
|
||||
if type(default) is bool:
|
||||
# If this option is a boolean, it doesn't need a value;
|
||||
# specifying it on the command line means "do the
|
||||
# opposite of the default".
|
||||
value = not default
|
||||
else:
|
||||
# The next item in the argument list is the value, i.e.
|
||||
# --keyword value
|
||||
if not argv or argv[0].startswith("-") or self.param_keywords:
|
||||
# There isn't a value available, or its derived
|
||||
# from parameters. Just use True, assuming this
|
||||
# is a flag.
|
||||
value = True
|
||||
else:
|
||||
value = argv.pop(0)
|
||||
try:
|
||||
value = totype(value, default)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
# Store this option
|
||||
kwargs[name] = value
|
||||
|
||||
elif arg.startswith("-") and cmd.shortopts:
|
||||
# Process short option(s)
|
||||
|
||||
# For each character after the '-'...
|
||||
for i in range(1, len(arg)):
|
||||
char = arg[i]
|
||||
if char not in shortchars:
|
||||
continue
|
||||
|
||||
# Get the long option name corresponding to this char
|
||||
name = shortchars[char]
|
||||
|
||||
default = keywords[name]
|
||||
if type(default) is bool:
|
||||
# If this option is a boolean, it doesn't need a value;
|
||||
# specifying it on the command line means "do the
|
||||
# opposite of the default".
|
||||
kwargs[name] = not default
|
||||
else:
|
||||
# This option requires a value...
|
||||
if self.param_keywords:
|
||||
# It's derived from parameters. Just use True,
|
||||
# assuming this is a flag.
|
||||
value = True
|
||||
elif i < len(arg)-1:
|
||||
# There are other characters after this one, so
|
||||
# the rest of the characters must represent the
|
||||
# value (i.e. old-style UNIX option like -Nname)
|
||||
value = totype(arg[i+1:], default)
|
||||
elif argv:
|
||||
# This is the last character in the list, so the
|
||||
# next argument on the command line is the value.
|
||||
value = argv.pop(0)
|
||||
else:
|
||||
# There is no value available. Just use True,
|
||||
# assuming this is a flag.
|
||||
value = True
|
||||
|
||||
try:
|
||||
kwargs[name] = totype(value, default)
|
||||
except ValueError:
|
||||
raise CommandError("Couldn't convert %s value %r to type %s" % (name, value, type(default)))
|
||||
break
|
||||
else:
|
||||
# This doesn't start with "-", so just add it to the list of
|
||||
# positional arguments.
|
||||
vargs.append(arg)
|
||||
|
||||
return vargs, kwargs
|
||||
|
||||
def parse(self, argv=None):
|
||||
"""Parses the command and parameters to call from the list of command
|
||||
line arguments. Returns a tuple of (Cmd object, position arg list,
|
||||
keyword arg dict).
|
||||
|
||||
:param argv: the list of options passed to the command line (sys.argv).
|
||||
"""
|
||||
|
||||
if argv is None: argv = sys.argv
|
||||
|
||||
scriptname = argv[0]
|
||||
|
||||
if (len(argv) < 2) or (argv[1] == "-h" or argv[1] == "--help"):
|
||||
# Print the documentation for the script
|
||||
self.print_top_help(scriptname)
|
||||
|
||||
if argv[1] == "help":
|
||||
if len(argv) > 2 and argv[2] in self.commands:
|
||||
cmd = self.commands[argv[2]]
|
||||
self.print_command_help(scriptname, cmd)
|
||||
self.print_top_help(scriptname)
|
||||
|
||||
if len(argv) > 1 and argv[1] in self.commands:
|
||||
# The first argument on the command line (after the script name
|
||||
# is the command to run.
|
||||
cmd = self.commands[argv[1]]
|
||||
|
||||
if len(argv) > 2 and (argv[2] == "-h" or argv[2] == "--help"):
|
||||
# Print the help for this command and exit
|
||||
self.print_command_help(scriptname, cmd)
|
||||
|
||||
options = argv[2:]
|
||||
else:
|
||||
# No known command was specified. If there's a default command,
|
||||
# use that.
|
||||
cmd = self.defaultcommand
|
||||
if cmd is None:
|
||||
raise CommandError("unknown command `%s' specified" % argv[1])
|
||||
|
||||
options = argv[1:]
|
||||
|
||||
# Parse the rest of the arguments on the command line and use them to
|
||||
# call the command function.
|
||||
args, kwargs = self.parse_args(scriptname, cmd, options)
|
||||
return (cmd, args, kwargs)
|
||||
|
||||
def apply(self, cmd, args, kwargs):
|
||||
"""Calls the command function.
|
||||
"""
|
||||
|
||||
# Create a list of positional arguments: arguments that are either
|
||||
# required (not in keywords), or where the default is None (taken to be
|
||||
# an optional positional argument). This is different from the Python
|
||||
# calling convention, which will fill in keyword arguments with extra
|
||||
# positional arguments.
|
||||
posargs = [a for a in cmd.argnames if cmd.keywords.get(a) is None]
|
||||
|
||||
if len(args) > len(posargs) and not cmd.has_varargs:
|
||||
raise CommandError("Too many arguments to %s: %s" % (cmd.name, " ".join(args)))
|
||||
|
||||
if cmd.keywords:
|
||||
for k in sorted(kwargs.keys()):
|
||||
if k not in cmd.keywords:
|
||||
raise CommandError("Unknown option --%s" % k)
|
||||
|
||||
# Rearrange the arguments into the order Python expects
|
||||
newargs = []
|
||||
newkwargs = dict(kwargs)
|
||||
for name in cmd.argnames:
|
||||
if args and cmd.keywords.get(name) is None:
|
||||
# This argument is required or optional and we have a bare arg
|
||||
# to fill it
|
||||
newargs.append(args.pop(0))
|
||||
elif name not in cmd.keywords and not args:
|
||||
# This argument is required but we don't have a bare arg to
|
||||
# fill it
|
||||
raise CommandError("Required argument '%s' not given" % name)
|
||||
else:
|
||||
# This is a keyword argument
|
||||
newkwargs[name] = kwargs.get(name, cmd.keywords[name])
|
||||
newargs.extend(args)
|
||||
|
||||
return cmd.fn(*newargs, **newkwargs)
|
||||
|
||||
def run(self, argv=None):
|
||||
"""Takes a list of command line arguments, parses it into a command
|
||||
name and options, and calls the function corresponding to the command
|
||||
with the given arguments.
|
||||
|
||||
:param argv: the list of options passed to the command line (sys.argv).
|
||||
"""
|
||||
|
||||
return self.apply(*self.parse(argv))
|
||||
|
||||
def test(self, argv=None):
|
||||
"""Takes a list of command line arguments, parses it into a command
|
||||
name and options, and returns what the resulting function call would
|
||||
look like. This may be useful for testing how command line arguments
|
||||
would be passed to your functions.
|
||||
|
||||
:param argv: the list of options passed to the command line (sys.argv).
|
||||
"""
|
||||
|
||||
cmd, args, kwargs = self.parse(argv)
|
||||
result = "%s(%s" % (cmd.name, ",".join(repr(a) for a in args))
|
||||
if kwargs:
|
||||
kws = ",".join("%s=%r" % (k, v) for k, v in kwargs.items())
|
||||
result += "," + kws
|
||||
result += ")"
|
||||
return result
|
||||
|
||||
|
||||
_baker = Baker()
|
||||
command = _baker.command
|
||||
run = _baker.run
|
||||
test = _baker.test
|
||||
help = _baker.print_top_help
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -18,7 +18,7 @@ from .. import util
|
|||
def extract_singlefile_standard (archive, compression, cmd, **kwargs):
|
||||
"""Standard routine to extract a singlefile archive (like gzip)."""
|
||||
cmdlist = [util.shell_quote(cmd)]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
outfile = util.get_single_outfile(kwargs['outdir'], archive)
|
||||
cmdlist.extend(['-c', '-d', '--', util.shell_quote(archive), '>',
|
||||
|
|
@ -29,7 +29,7 @@ def extract_singlefile_standard (archive, compression, cmd, **kwargs):
|
|||
def test_singlefile_standard (archive, compression, cmd, **kwargs):
|
||||
"""Standard routine to test a singlefile archive (like gzip)."""
|
||||
cmdlist = [cmd]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['-t', '--', archive])
|
||||
return cmdlist
|
||||
|
|
@ -38,7 +38,7 @@ def test_singlefile_standard (archive, compression, cmd, **kwargs):
|
|||
def create_singlefile_standard (archive, compression, cmd, *args, **kwargs):
|
||||
"""Standard routine to create a singlefile archive (like gzip)."""
|
||||
cmdlist = [util.shell_quote(cmd)]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['-c', '--'])
|
||||
cmdlist.extend([util.shell_quote(x) for x in args])
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -19,7 +19,7 @@ import os
|
|||
def extract_ar (archive, compression, cmd, **kwargs):
|
||||
"""Extract a AR archive."""
|
||||
opts = 'x'
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
opts += 'v'
|
||||
cmdlist = [cmd, opts, os.path.abspath(archive)]
|
||||
return (cmdlist, {'cwd': kwargs['outdir']})
|
||||
|
|
@ -27,7 +27,7 @@ def extract_ar (archive, compression, cmd, **kwargs):
|
|||
def list_ar (archive, compression, cmd, **kwargs):
|
||||
"""List a AR archive."""
|
||||
opts = 't'
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
opts += 'v'
|
||||
return [cmd, opts, archive]
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ test_ar = list_ar
|
|||
def create_ar (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a AR archive."""
|
||||
opts = 'rc'
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
opts += 'v'
|
||||
cmdlist = [cmd, opts, archive]
|
||||
cmdlist.extend(args)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -26,7 +26,7 @@ def extract_arc (archive, compression, cmd, **kwargs):
|
|||
def list_arc (archive, compression, cmd, **kwargs):
|
||||
"""List a ARC archive."""
|
||||
cmdlist = [cmd]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('v')
|
||||
else:
|
||||
cmdlist.append('l')
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -17,39 +17,27 @@
|
|||
|
||||
def extract_arj (archive, compression, cmd, **kwargs):
|
||||
"""Extract a ARJ archive."""
|
||||
cmdlist = [cmd, 'x', '-r', '-y']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-i-')
|
||||
cmdlist.extend([archive, kwargs['outdir']])
|
||||
return cmdlist
|
||||
return [cmd, 'x', '-r', '-y', archive, kwargs['outdir']]
|
||||
|
||||
|
||||
def list_arj (archive, compression, cmd, **kwargs):
|
||||
"""List a ARJ archive."""
|
||||
cmdlist = [cmd]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('v')
|
||||
else:
|
||||
cmdlist.append('l')
|
||||
cmdlist.append('-i-')
|
||||
cmdlist.extend(['-r', '-y', archive])
|
||||
return cmdlist
|
||||
|
||||
|
||||
def test_arj (archive, compression, cmd, **kwargs):
|
||||
"""Test a ARJ archive."""
|
||||
cmdlist = [cmd, 't']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-i-')
|
||||
cmdlist.extend(['-r', '-y', archive])
|
||||
return cmdlist
|
||||
return [cmd, 't', '-r', '-y', archive]
|
||||
|
||||
|
||||
def create_arj (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a ARJ archive."""
|
||||
cmdlist = [cmd, 'a', '-r', '-y']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-i-')
|
||||
cmdlist.append(archive)
|
||||
cmdlist = [cmd, 'a', '-r', '-y', archive]
|
||||
cmdlist.extend(args)
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -23,7 +23,7 @@ test_bzip2 = test_singlefile_standard
|
|||
def create_bzip2 (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a BZIP2 archive."""
|
||||
cmdlist = [util.shell_quote(cmd)]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['-c', '-z', '--'])
|
||||
cmdlist.extend([util.shell_quote(x) for x in args])
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
def extract_cab (archive, compression, cmd, **kwargs):
|
||||
"""Extract a CAB archive."""
|
||||
cmdlist = [cmd, '-d', kwargs['outdir']]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 0:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
|
|
@ -26,7 +26,7 @@ def extract_cab (archive, compression, cmd, **kwargs):
|
|||
def list_cab (archive, compression, cmd, **kwargs):
|
||||
"""List a CAB archive."""
|
||||
cmdlist = [cmd, '-l']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 0:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -20,7 +20,7 @@ from .. import util
|
|||
def create_compress (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a compressed archive."""
|
||||
cmdlist = [util.shell_quote(cmd)]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.append('-c')
|
||||
cmdlist.extend([util.shell_quote(x) for x in args])
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -25,7 +25,7 @@ def extract_cpio (archive, compression, cmd, **kwargs):
|
|||
if sys.platform.startswith('linux') and not cmd.endswith('bsdcpio'):
|
||||
cmdlist.extend(['--no-absolute-filenames',
|
||||
'--force-local', '--nonmatching', r'"*\.\.*"'])
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['<', util.shell_quote(os.path.abspath(archive))])
|
||||
return (cmdlist, {'cwd': kwargs['outdir'], 'shell': True})
|
||||
|
|
@ -34,7 +34,7 @@ def extract_cpio (archive, compression, cmd, **kwargs):
|
|||
def list_cpio (archive, compression, cmd, **kwargs):
|
||||
"""List a CPIO archive."""
|
||||
cmdlist = [cmd, '-i', '-t']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['-F', archive])
|
||||
return cmdlist
|
||||
|
|
@ -44,7 +44,7 @@ test_cpio = list_cpio
|
|||
def create_cpio(archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a CPIO archive."""
|
||||
cmdlist = [util.shell_quote(cmd), '--create']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
if len(args) != 0:
|
||||
findcmd = ['find']
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
def extract_deb (archive, compression, cmd, **kwargs):
|
||||
"""Extract a DEB archive."""
|
||||
cmdlist = [cmd]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('--vextract')
|
||||
else:
|
||||
cmdlist.append('--extract')
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2012 Bastian Kleineidam
|
||||
# Copyright (C) 2012-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -32,8 +32,4 @@ def create_flac (archive, compression, cmd, *args, **kwargs):
|
|||
|
||||
def test_flac (archive, compression, cmd, **kwargs):
|
||||
"""Test a FLAC file."""
|
||||
cmdlist = [cmd, '--test']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-s')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
return [cmd, '--test', archive]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -24,7 +24,7 @@ create_gzip = create_singlefile_standard
|
|||
def list_gzip (archive, compression, cmd, **kwargs):
|
||||
"""List a GZIP archive."""
|
||||
cmdlist = [cmd]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 0:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['-l', '--', archive])
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2012 Bastian Kleineidam
|
||||
# Copyright (C) 2012-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
def create_cab (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a CAB archive."""
|
||||
cmdlist = [cmd, '-r']
|
||||
if not kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-q')
|
||||
cmdlist.extend(args)
|
||||
cmdlist.append(archive)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
def extract_lzh (archive, compression, cmd, **kwargs):
|
||||
"""Extract a LZH archive."""
|
||||
opts = 'x'
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
opts += 'v'
|
||||
opts += "w=%s" % kwargs['outdir']
|
||||
return [cmd, opts, archive]
|
||||
|
|
@ -26,7 +26,7 @@ def extract_lzh (archive, compression, cmd, **kwargs):
|
|||
def list_lzh (archive, compression, cmd, **kwargs):
|
||||
"""List a LZH archive."""
|
||||
cmdlist = [cmd]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('v')
|
||||
else:
|
||||
cmdlist.append('l')
|
||||
|
|
@ -36,14 +36,14 @@ def list_lzh (archive, compression, cmd, **kwargs):
|
|||
def test_lzh (archive, compression, cmd, **kwargs):
|
||||
"""Test a LZH archive."""
|
||||
opts = 't'
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
opts += 'v'
|
||||
return [cmd, opts, archive]
|
||||
|
||||
def create_lzh (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a LZH archive."""
|
||||
opts = 'a'
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
opts += 'v'
|
||||
cmdlist = [cmd, opts, archive]
|
||||
cmdlist.extend(args)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ from .. import util
|
|||
def extract_lrzip (archive, compression, cmd, **kwargs):
|
||||
"""Extract a LRZIP archive."""
|
||||
cmdlist = [cmd, '-d']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
outfile = util.get_single_outfile(kwargs['outdir'], archive)
|
||||
cmdlist.extend(["-o", outfile, os.path.abspath(archive)])
|
||||
|
|
@ -29,7 +29,7 @@ def extract_lrzip (archive, compression, cmd, **kwargs):
|
|||
def test_lrzip (archive, compression, cmd, **kwargs):
|
||||
"""Test a LRZIP archive."""
|
||||
cmdlist = [cmd, '-t']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
|
|
@ -37,7 +37,7 @@ def test_lrzip (archive, compression, cmd, **kwargs):
|
|||
def create_lrzip (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a LRZIP archive."""
|
||||
cmdlist = [cmd, '-o', archive]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(args)
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -23,7 +23,7 @@ extract_lzop = extract_singlefile_standard
|
|||
def list_lzop (archive, compression, cmd, **kwargs):
|
||||
"""List a LZOP archive."""
|
||||
cmdlist = [cmd, '--list']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('--verbose')
|
||||
cmdlist.extend(['--', archive])
|
||||
return cmdlist
|
||||
|
|
@ -31,7 +31,7 @@ def list_lzop (archive, compression, cmd, **kwargs):
|
|||
def test_lzop (archive, compression, cmd, **kwargs):
|
||||
"""Test a LZOP archive."""
|
||||
cmdlist = [cmd, '--test']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('--verbose')
|
||||
cmdlist.extend(['--', archive])
|
||||
return cmdlist
|
||||
|
|
@ -39,7 +39,7 @@ def test_lzop (archive, compression, cmd, **kwargs):
|
|||
def create_lzop (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a LZOP archive."""
|
||||
cmdlist = [cmd]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['-o', archive, '--'])
|
||||
cmdlist.extend(args)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -26,7 +26,7 @@ def extract_arc (archive, compression, cmd, **kwargs):
|
|||
def list_arc (archive, compression, cmd, **kwargs):
|
||||
"""List a ARC archive."""
|
||||
cmdlist = [cmd, '-l']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -17,11 +17,7 @@
|
|||
|
||||
def extract_7z (archive, compression, cmd, **kwargs):
|
||||
"""Extract a 7z archive."""
|
||||
cmdlist = [cmd, 'x']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-bd')
|
||||
cmdlist.extend(['-o%s' % kwargs['outdir'], '--', archive])
|
||||
return cmdlist
|
||||
return [cmd, 'x', '-o%s' % kwargs['outdir'], '--', archive]
|
||||
|
||||
extract_bzip2 = \
|
||||
extract_gzip = \
|
||||
|
|
@ -37,12 +33,7 @@ extract_bzip2 = \
|
|||
|
||||
def list_7z (archive, compression, cmd, **kwargs):
|
||||
"""List a 7z archive."""
|
||||
cmdlist = [cmd, 'l']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-bd')
|
||||
cmdlist.append('--')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
return [cmd, 'l', '--', archive]
|
||||
|
||||
list_bzip2 = \
|
||||
list_gzip = \
|
||||
|
|
@ -59,12 +50,7 @@ list_bzip2 = \
|
|||
|
||||
def test_7z (archive, compression, cmd, **kwargs):
|
||||
"""Test a 7z archive."""
|
||||
cmdlist = [cmd, 't']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-bd')
|
||||
cmdlist.append('--')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
return [cmd, 't', '--', archive]
|
||||
|
||||
test_bzip2 = \
|
||||
test_gzip = \
|
||||
|
|
@ -81,11 +67,7 @@ test_bzip2 = \
|
|||
|
||||
def create_7z (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a 7z archive."""
|
||||
cmdlist = [cmd, 'a']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-bd')
|
||||
cmdlist.append('--')
|
||||
cmdlist.append(archive)
|
||||
cmdlist = [cmd, 'a', '--', archive]
|
||||
cmdlist.extend(args)
|
||||
return cmdlist
|
||||
|
||||
|
|
|
|||
|
|
@ -21,46 +21,39 @@ try:
|
|||
except ImportError:
|
||||
import bz2
|
||||
|
||||
# read in 1MB chunks
|
||||
READ_SIZE_BYTES = 1024*1024
|
||||
|
||||
def extract_bzip2 (archive, compression, cmd, **kwargs):
|
||||
"""Extract a BZIP2 archive with the bz2 Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
outdir = kwargs['outdir']
|
||||
if verbose:
|
||||
util.log_info('extracting %s...' % archive)
|
||||
targetname = util.get_single_outfile(outdir, archive)
|
||||
bz2file = bz2.BZ2File(archive)
|
||||
try:
|
||||
with open(targetname, 'wb') as targetfile:
|
||||
data = bz2file.read(READ_SIZE_BYTES)
|
||||
while data:
|
||||
targetfile.write(data)
|
||||
with bz2.BZ2File(archive) as bz2file:
|
||||
with open(targetname, 'wb') as targetfile:
|
||||
data = bz2file.read(READ_SIZE_BYTES)
|
||||
finally:
|
||||
bz2file.close()
|
||||
if verbose:
|
||||
util.log_info('... extracted to %s' % targetname)
|
||||
while data:
|
||||
targetfile.write(data)
|
||||
data = bz2file.read(READ_SIZE_BYTES)
|
||||
except Exception as err:
|
||||
msg = "error extracting %s to %s: %s" % (archive, targetname, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
||||
|
||||
def create_bzip2 (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a BZIP2 archive with the bz2 Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
if verbose:
|
||||
util.log_info('creating %s...' % archive)
|
||||
if len(args) > 1:
|
||||
util.log_error('multi-file compression not supported in Python bz2')
|
||||
bz2file = bz2.BZ2File(archive, 'wb')
|
||||
raise util.PatoolError('multi-file compression not supported in Python bz2')
|
||||
try:
|
||||
filename = args[0]
|
||||
with open(filename, 'rb') as srcfile:
|
||||
data = srcfile.read(READ_SIZE_BYTES)
|
||||
while data:
|
||||
bz2file.write(data)
|
||||
with bz2.BZ2File(archive, 'wb') as bz2file:
|
||||
filename = args[0]
|
||||
with open(filename, 'rb') as srcfile:
|
||||
data = srcfile.read(READ_SIZE_BYTES)
|
||||
if verbose:
|
||||
util.log_info('... added %s' % filename)
|
||||
finally:
|
||||
bz2file.close()
|
||||
while data:
|
||||
bz2file.write(data)
|
||||
data = srcfile.read(READ_SIZE_BYTES)
|
||||
except Exception as err:
|
||||
msg = "error creating %s: %s" % (archive, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -23,42 +23,34 @@ READ_SIZE_BYTES = 1024*1024
|
|||
|
||||
def extract_gzip (archive, compression, cmd, **kwargs):
|
||||
"""Extract a GZIP archive with the gzip Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
outdir = kwargs['outdir']
|
||||
if verbose:
|
||||
util.log_info('extracting %s...' % archive)
|
||||
targetname = util.get_single_outfile(outdir, archive)
|
||||
gzipfile = gzip.GzipFile(archive)
|
||||
try:
|
||||
with open(targetname, 'wb') as targetfile:
|
||||
data = gzipfile.read(READ_SIZE_BYTES)
|
||||
while data:
|
||||
targetfile.write(data)
|
||||
with gzip.GzipFile(archive) as gzipfile:
|
||||
with open(targetname, 'wb') as targetfile:
|
||||
data = gzipfile.read(READ_SIZE_BYTES)
|
||||
finally:
|
||||
gzipfile.close()
|
||||
if verbose:
|
||||
util.log_info('... extracted to %s' % targetname)
|
||||
while data:
|
||||
targetfile.write(data)
|
||||
data = gzipfile.read(READ_SIZE_BYTES)
|
||||
except Exception as err:
|
||||
msg = "error extracting %s to %s: %s" % (archive, targetname, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
||||
|
||||
def create_gzip (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a GZIP archive with the gzip Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
if verbose:
|
||||
util.log_info('creating %s...' % archive)
|
||||
if len(args) > 1:
|
||||
util.log_error('multi-file compression not supported in Python gzip')
|
||||
gzipfile = gzip.GzipFile(archive, 'wb')
|
||||
raise util.PatoolError('multi-file compression not supported in Python gzip')
|
||||
try:
|
||||
filename = args[0]
|
||||
with open(filename, 'rb') as srcfile:
|
||||
data = srcfile.read(READ_SIZE_BYTES)
|
||||
while data:
|
||||
gzipfile.write(data)
|
||||
with gzip.GzipFile(archive, 'wb') as gzipfile:
|
||||
filename = args[0]
|
||||
with open(filename, 'rb') as srcfile:
|
||||
data = srcfile.read(READ_SIZE_BYTES)
|
||||
if verbose:
|
||||
util.log_info('... added %s' % filename)
|
||||
finally:
|
||||
gzipfile.close()
|
||||
while data:
|
||||
gzipfile.write(data)
|
||||
data = srcfile.read(READ_SIZE_BYTES)
|
||||
except Exception as err:
|
||||
msg = "error creating %s: %s" % (archive, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -21,22 +21,18 @@ READ_SIZE_BYTES = 1024*1024
|
|||
|
||||
def _extract(archive, compression, cmd, format, **kwargs):
|
||||
"""Extract an LZMA or XZ archive with the lzma Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
outdir = kwargs['outdir']
|
||||
if verbose:
|
||||
util.log_info('extracting %s...' % archive)
|
||||
targetname = util.get_single_outfile(outdir, archive)
|
||||
lzmafile = lzma.LZMAFile(archive, format=format)
|
||||
try:
|
||||
with open(targetname, 'wb') as targetfile:
|
||||
data = lzmafile.read(READ_SIZE_BYTES)
|
||||
while data:
|
||||
targetfile.write(data)
|
||||
with lzma.LZMAFile(archive, format=format) as lzmafile:
|
||||
with open(targetname, 'wb') as targetfile:
|
||||
data = lzmafile.read(READ_SIZE_BYTES)
|
||||
finally:
|
||||
lzmafile.close()
|
||||
if verbose:
|
||||
util.log_info('... extracted to %s' % targetname)
|
||||
while data:
|
||||
targetfile.write(data)
|
||||
data = lzmafile.read(READ_SIZE_BYTES)
|
||||
except Exception as err:
|
||||
msg = "error extracting %s to %s: %s" % (archive, targetname, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
||||
def extract_lzma(archive, compression, cmd, **kwargs):
|
||||
|
|
@ -50,23 +46,19 @@ def extract_xz(archive, compression, cmd, **kwargs):
|
|||
|
||||
def _create(archive, compression, cmd, format, *args, **kwargs):
|
||||
"""Create an LZMA or XZ archive with the lzma Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
if verbose:
|
||||
util.log_info('creating %s...' % archive)
|
||||
if len(args) > 1:
|
||||
util.log_error('multi-file compression not supported in Python lzma')
|
||||
lzmafile = lzma.LZMAFile(archive, 'wb', format)
|
||||
raise util.PatoolError('multi-file compression not supported in Python lzma')
|
||||
try:
|
||||
filename = args[0]
|
||||
with open(filename, 'rb') as srcfile:
|
||||
data = srcfile.read(READ_SIZE_BYTES)
|
||||
while data:
|
||||
lzmafile.write(data)
|
||||
with lzma.LZMAFile(archive, 'wb', format) as lzmafile:
|
||||
filename = args[0]
|
||||
with open(filename, 'rb') as srcfile:
|
||||
data = srcfile.read(READ_SIZE_BYTES)
|
||||
if verbose:
|
||||
util.log_info('... added %s' % filename)
|
||||
finally:
|
||||
lzmafile.close()
|
||||
while data:
|
||||
lzmafile.write(data)
|
||||
data = srcfile.read(READ_SIZE_BYTES)
|
||||
except Exception as err:
|
||||
msg = "error creating %s: %s" % (archive, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
||||
def create_lzma(archive, compression, cmd, *args, **kwargs):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2012 Bastian Kleineidam
|
||||
# Copyright (C) 2012-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -22,46 +22,38 @@ READ_SIZE_BYTES = 1024*1024
|
|||
|
||||
def list_tar (archive, compression, cmd, **kwargs):
|
||||
"""List a TAR archive with the tarfile Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
if verbose:
|
||||
util.log_info('listing %s...' % archive)
|
||||
tfile = tarfile.open(archive)
|
||||
try:
|
||||
tfile.list(verbose=verbose)
|
||||
finally:
|
||||
tfile.close()
|
||||
with tarfile.open(archive) as tfile:
|
||||
tfile.list(verbose=kwargs["verbosity"]>1)
|
||||
except Exception as err:
|
||||
msg = "error listing %s: %s" % (archive, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
||||
test_tar = list_tar
|
||||
|
||||
def extract_tar (archive, compression, cmd, **kwargs):
|
||||
"""Extract a TAR archive with the tarfile Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
outdir = kwargs['outdir']
|
||||
if verbose:
|
||||
util.log_info('extracting %s...' % archive)
|
||||
tfile = tarfile.open(archive)
|
||||
try:
|
||||
tfile.extractall(path=outdir)
|
||||
finally:
|
||||
tfile.close()
|
||||
if verbose:
|
||||
util.log_info('... extracted to %s' % outdir)
|
||||
with tarfile.open(archive) as tfile:
|
||||
tfile.extractall(path=outdir)
|
||||
except Exception as err:
|
||||
msg = "error extracting %s: %s" % (archive, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
||||
|
||||
def create_tar (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a TAR archive with the tarfile Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
if verbose:
|
||||
util.log_info('creating %s...' % archive)
|
||||
mode = get_tar_mode(compression)
|
||||
tfile = tarfile.open(archive, mode)
|
||||
try:
|
||||
for filename in args:
|
||||
tfile.add(filename)
|
||||
finally:
|
||||
tfile.close()
|
||||
with tarfile.open(archive, mode) as tfile:
|
||||
for filename in args:
|
||||
tfile.add(filename)
|
||||
except Exception as err:
|
||||
msg = "error creating %s: %s" % (archive, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
||||
|
||||
|
|
@ -73,6 +65,6 @@ def get_tar_mode (compression):
|
|||
return 'w:bz2'
|
||||
if compression:
|
||||
msg = 'pytarfile does not support %s for tar compression'
|
||||
util.log_error(msg % compression)
|
||||
raise util.PatoolError(msg % compression)
|
||||
# no compression
|
||||
return 'w'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2012 Bastian Kleineidam
|
||||
# Copyright (C) 2012-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""Archive commands for the zipfile Python module."""
|
||||
from __future__ import print_function
|
||||
from .. import util
|
||||
import zipfile
|
||||
import os
|
||||
|
|
@ -23,49 +24,43 @@ READ_SIZE_BYTES = 1024*1024
|
|||
|
||||
def list_zip (archive, compression, cmd, **kwargs):
|
||||
"""List member of a ZIP archive with the zipfile Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
if verbose:
|
||||
util.log_info('listing %s...' % archive)
|
||||
zfile = zipfile.ZipFile(archive, "r")
|
||||
verbosity = kwargs['verbosity']
|
||||
try:
|
||||
for name in zfile.namelist():
|
||||
util.log_info('member %s' % name)
|
||||
finally:
|
||||
zfile.close()
|
||||
with zipfile.ZipFile(archive, "r") as zfile:
|
||||
for name in zfile.namelist():
|
||||
if verbosity >= 0:
|
||||
print(name)
|
||||
except Exception as err:
|
||||
msg = "error listing %s: %s" % (archive, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
||||
test_zip = list_zip
|
||||
|
||||
def extract_zip (archive, compression, cmd, **kwargs):
|
||||
"""Extract a ZIP archive with the zipfile Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
outdir = kwargs['outdir']
|
||||
if verbose:
|
||||
util.log_info('extracting %s...' % archive)
|
||||
zfile = zipfile.ZipFile(archive)
|
||||
try:
|
||||
zfile.extractall(outdir)
|
||||
finally:
|
||||
zfile.close()
|
||||
if verbose:
|
||||
util.log_info('... extracted to %s' % outdir)
|
||||
with zipfile.ZipFile(archive) as zfile:
|
||||
zfile.extractall(outdir)
|
||||
except Exception as err:
|
||||
msg = "error extracting %s: %s" % (archive, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
||||
|
||||
def create_zip (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a ZIP archive with the zipfile Python module."""
|
||||
verbose = kwargs['verbose']
|
||||
if verbose:
|
||||
util.log_info('creating %s...' % archive)
|
||||
zfile = zipfile.ZipFile(archive, 'w')
|
||||
try:
|
||||
for filename in args:
|
||||
if os.path.isdir(filename):
|
||||
write_directory(zfile, filename)
|
||||
else:
|
||||
zfile.write(filename)
|
||||
finally:
|
||||
zfile.close()
|
||||
with zipfile.ZipFile(archive, 'w') as zfile:
|
||||
for filename in args:
|
||||
if os.path.isdir(filename):
|
||||
write_directory(zfile, filename)
|
||||
else:
|
||||
zfile.write(filename)
|
||||
except Exception as err:
|
||||
msg = "error creating %s: %s" % (archive, err)
|
||||
raise util.PatoolError(msg)
|
||||
return None
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -18,36 +18,25 @@ import os
|
|||
|
||||
def extract_rar (archive, compression, cmd, **kwargs):
|
||||
"""Extract a RAR archive."""
|
||||
cmdlist = [cmd, 'x']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-c-')
|
||||
cmdlist.extend(['--', os.path.abspath(archive)])
|
||||
cmdlist = [cmd, 'x', '--', os.path.abspath(archive)]
|
||||
return (cmdlist, {'cwd': kwargs['outdir']})
|
||||
|
||||
def list_rar (archive, compression, cmd, **kwargs):
|
||||
"""List a RAR archive."""
|
||||
cmdlist = [cmd]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('v')
|
||||
else:
|
||||
cmdlist.append('l')
|
||||
cmdlist.append('-c-')
|
||||
cmdlist.extend(['--', archive])
|
||||
return cmdlist
|
||||
|
||||
def test_rar (archive, compression, cmd, **kwargs):
|
||||
"""Test a RAR archive."""
|
||||
cmdlist = [cmd, 't']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-c-')
|
||||
cmdlist.extend(['--', archive])
|
||||
return cmdlist
|
||||
return [cmd, 't', '--', archive]
|
||||
|
||||
def create_rar (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a RAR archive."""
|
||||
cmdlist = [cmd, 'a']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-c-')
|
||||
cmdlist.extend(['-r', '--', archive])
|
||||
cmdlist = [cmd, 'a', '-r', '--', archive]
|
||||
cmdlist.extend(args)
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
def list_rpm (archive, compression, cmd, **kwargs):
|
||||
"""List a RPM archive."""
|
||||
cmdlist = [cmd, '-q', '-l']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['-p', '--', archive])
|
||||
return cmdlist
|
||||
|
|
@ -26,7 +26,7 @@ def list_rpm (archive, compression, cmd, **kwargs):
|
|||
def test_rpm (archive, compression, cmd, **kwargs):
|
||||
"""Test a RPM archive."""
|
||||
cmdlist = [cmd, 'V']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['-p', '--', archive])
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -28,6 +28,6 @@ def extract_rpm (archive, compression, cmd, **kwargs):
|
|||
'--extract', '--make-directories', '--preserve-modification-time',
|
||||
'--no-absolute-filenames', '--force-local', '--nonmatching',
|
||||
r'"*\.\.*"']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
return (cmdlist, {'cwd': kwargs['outdir'], 'shell': True})
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -14,13 +14,12 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""Archive commands for the rzip program."""
|
||||
import os
|
||||
from .. import util
|
||||
|
||||
def extract_rzip (archive, compression, cmd, **kwargs):
|
||||
"""Extract an RZIP archive."""
|
||||
cmdlist = [cmd, '-d', '-k']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
outfile = util.get_single_outfile(kwargs['outdir'], archive)
|
||||
cmdlist.extend(["-o", outfile, archive])
|
||||
|
|
@ -29,7 +28,7 @@ def extract_rzip (archive, compression, cmd, **kwargs):
|
|||
def create_rzip (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create an RZIP archive."""
|
||||
cmdlist = [cmd, '-k', '-o', archive]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(args)
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2012 Bastian Kleineidam
|
||||
# Copyright (C) 2012-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -19,8 +19,6 @@ from .. import util
|
|||
def create_shar (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a SHAR archive."""
|
||||
cmdlist = [util.shell_quote(cmd)]
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-q')
|
||||
cmdlist.extend([util.shell_quote(x) for x in args])
|
||||
cmdlist.extend(['>', util.shell_quote(archive)])
|
||||
return (cmdlist, {'shell': True})
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -19,14 +19,14 @@ from .tar import add_tar_opts as add_star_opts
|
|||
def extract_tar (archive, compression, cmd, **kwargs):
|
||||
"""Extract a TAR archive."""
|
||||
cmdlist = [cmd, '-x']
|
||||
add_star_opts(cmdlist, compression, kwargs['verbose'])
|
||||
add_star_opts(cmdlist, compression, kwargs['verbosity'])
|
||||
cmdlist.extend(['-C', kwargs['outdir'], 'file=%s' % archive])
|
||||
return cmdlist
|
||||
|
||||
def list_tar (archive, compression, cmd, **kwargs):
|
||||
"""List a TAR archive."""
|
||||
cmdlist = [cmd, '-n']
|
||||
add_star_opts(cmdlist, compression, kwargs['verbose'])
|
||||
add_star_opts(cmdlist, compression, kwargs['verbosity'])
|
||||
cmdlist.append("file=%s" % archive)
|
||||
return cmdlist
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ test_tar = list_tar
|
|||
def create_tar (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a TAR archive."""
|
||||
cmdlist = [cmd, '-c']
|
||||
add_star_opts(cmdlist, compression, kwargs['verbose'])
|
||||
add_star_opts(cmdlist, compression, kwargs['verbosity'])
|
||||
cmdlist.append("file=%s" % archive)
|
||||
cmdlist.extend(args)
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -20,14 +20,14 @@ import os
|
|||
def extract_tar (archive, compression, cmd, **kwargs):
|
||||
"""Extract a TAR archive."""
|
||||
cmdlist = [cmd, '--extract']
|
||||
add_tar_opts(cmdlist, compression, kwargs['verbose'])
|
||||
add_tar_opts(cmdlist, compression, kwargs['verbosity'])
|
||||
cmdlist.extend(["--file", archive, '--directory', kwargs['outdir']])
|
||||
return cmdlist
|
||||
|
||||
def list_tar (archive, compression, cmd, **kwargs):
|
||||
"""List a TAR archive."""
|
||||
cmdlist = [cmd, '--list']
|
||||
add_tar_opts(cmdlist, compression, kwargs['verbose'])
|
||||
add_tar_opts(cmdlist, compression, kwargs['verbosity'])
|
||||
cmdlist.extend(["--file", archive])
|
||||
return cmdlist
|
||||
|
||||
|
|
@ -36,12 +36,12 @@ test_tar = list_tar
|
|||
def create_tar (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a TAR archive."""
|
||||
cmdlist = [cmd, '--create']
|
||||
add_tar_opts(cmdlist, compression, kwargs['verbose'])
|
||||
add_tar_opts(cmdlist, compression, kwargs['verbosity'])
|
||||
cmdlist.extend(["--file", archive, '--'])
|
||||
cmdlist.extend(args)
|
||||
return cmdlist
|
||||
|
||||
def add_tar_opts (cmdlist, compression, verbose):
|
||||
def add_tar_opts (cmdlist, compression, verbosity):
|
||||
"""Add tar options to cmdlist."""
|
||||
progname = os.path.basename(cmdlist[0])
|
||||
if compression == 'gzip':
|
||||
|
|
@ -58,5 +58,5 @@ def add_tar_opts (cmdlist, compression, verbose):
|
|||
program = compression
|
||||
# set compression program
|
||||
cmdlist.extend(['--use-compress-program', program])
|
||||
if verbose:
|
||||
if verbosity > 1:
|
||||
cmdlist.append('--verbose')
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -18,8 +18,6 @@
|
|||
def extract_ace (archive, compression, cmd, **kwargs):
|
||||
"""Extract a ACE archive."""
|
||||
cmdlist = [cmd, 'x']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-c-')
|
||||
outdir = kwargs['outdir']
|
||||
if not outdir.endswith('/'):
|
||||
outdir += '/'
|
||||
|
|
@ -29,18 +27,13 @@ def extract_ace (archive, compression, cmd, **kwargs):
|
|||
def list_ace (archive, compression, cmd, **kwargs):
|
||||
"""List a ACE archive."""
|
||||
cmdlist = [cmd]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('v')
|
||||
else:
|
||||
cmdlist.append('l')
|
||||
cmdlist.append('-c-')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
|
||||
def test_ace (archive, compression, cmd, **kwargs):
|
||||
"""Test a ACE archive."""
|
||||
cmdlist = [cmd, 't']
|
||||
if not kwargs['verbose']:
|
||||
cmdlist.append('-c-')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
return [cmd, 't', archive]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -20,7 +20,7 @@ from .. import util
|
|||
def extract_compress (archive, compression, cmd, **kwargs):
|
||||
"""Extract a compressed archive."""
|
||||
cmdlist = [util.shell_quote(cmd)]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
outfile = util.get_single_outfile(kwargs['outdir'], archive)
|
||||
cmdlist.extend(['-c', util.shell_quote(archive), '>',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
def extract_zip (archive, compression, cmd, **kwargs):
|
||||
"""Extract a ZIP archive."""
|
||||
cmdlist = [cmd]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['--', archive, '-d', kwargs['outdir']])
|
||||
return cmdlist
|
||||
|
|
@ -26,7 +26,7 @@ def extract_zip (archive, compression, cmd, **kwargs):
|
|||
def list_zip (archive, compression, cmd, **kwargs):
|
||||
"""List a ZIP archive."""
|
||||
cmdlist = [cmd, '-l']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['--', archive])
|
||||
return cmdlist
|
||||
|
|
@ -34,7 +34,7 @@ def list_zip (archive, compression, cmd, **kwargs):
|
|||
def test_zip (archive, compression, cmd, **kwargs):
|
||||
"""Test a ZIP archive."""
|
||||
cmdlist = [cmd, '-t']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['--', archive])
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2011-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2011-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -21,7 +21,7 @@ def extract_dms (archive, compression, cmd, **kwargs):
|
|||
"""Extract a DMS archive."""
|
||||
check_archive_ext(archive)
|
||||
cmdlist = [cmd, '-d', kwargs['outdir']]
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.extend(['u', archive])
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -26,7 +26,7 @@ def list_xz (archive, compression, cmd, **kwargs):
|
|||
"""List a XZ archive."""
|
||||
cmdlist = [cmd]
|
||||
cmdlist.append('-l')
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
def create_zip (archive, compression, cmd, *args, **kwargs):
|
||||
"""Create a ZIP archive."""
|
||||
cmdlist = [cmd, '-r']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.append(archive)
|
||||
cmdlist.extend(args)
|
||||
|
|
@ -27,7 +27,7 @@ def create_zip (archive, compression, cmd, *args, **kwargs):
|
|||
def test_zip (archive, compression, cmd, *args, **kwargs):
|
||||
"""Test a ZIP archive."""
|
||||
cmdlist = [cmd, '--test']
|
||||
if kwargs['verbose']:
|
||||
if kwargs['verbosity'] > 1:
|
||||
cmdlist.append('-v')
|
||||
cmdlist.append(archive)
|
||||
return cmdlist
|
||||
|
|
|
|||
102
patoolib/util.py
102
patoolib/util.py
|
|
@ -21,9 +21,14 @@ import shutil
|
|||
import subprocess
|
||||
import mimetypes
|
||||
import tempfile
|
||||
import time
|
||||
import traceback
|
||||
from distutils.spawn import find_executable
|
||||
|
||||
AppName = "patool"
|
||||
App = "%s 1.0" % AppName
|
||||
SupportUrl = "https://github.com/wummel/patool/issues"
|
||||
|
||||
# internal MIME database
|
||||
mimedb = None
|
||||
|
||||
|
|
@ -120,25 +125,34 @@ def backtick (cmd, encoding='utf-8'):
|
|||
return data.decode(encoding)
|
||||
|
||||
|
||||
def run (cmd, **kwargs):
|
||||
def run (cmd, verbosity=0, **kwargs):
|
||||
"""Run command without error checking.
|
||||
@return: command return code"""
|
||||
# Note that shell_quote_nt() result is not suitable for copy-paste
|
||||
# (especially on Unix systems), but it looks nicer than shell_quote().
|
||||
log_info("running %s" % " ".join(map(shell_quote_nt, cmd)))
|
||||
if verbosity >= 0:
|
||||
log_info("running %s" % " ".join(map(shell_quote_nt, cmd)))
|
||||
if kwargs:
|
||||
log_info(" with %s" % ", ".join("%s=%s" % (k, shell_quote(str(v)))\
|
||||
if verbosity >= 0:
|
||||
log_info(" with %s" % ", ".join("%s=%s" % (k, shell_quote(str(v)))\
|
||||
for k, v in kwargs.items()))
|
||||
if kwargs.get("shell"):
|
||||
# for shell calls the command must be a string
|
||||
cmd = " ".join(cmd)
|
||||
return subprocess.call(cmd, **kwargs)
|
||||
if verbosity < 1:
|
||||
# hide command output on stdout
|
||||
with open(os.devnull, 'wb') as devnull:
|
||||
kwargs['stdout'] = devnull
|
||||
res = subprocess.call(cmd, **kwargs)
|
||||
else:
|
||||
res = subprocess.call(cmd, **kwargs)
|
||||
return res
|
||||
|
||||
|
||||
def run_checked (cmd, **kwargs):
|
||||
def run_checked (cmd, ret_ok=(0,), **kwargs):
|
||||
"""Run command and raise PatoolError on error."""
|
||||
retcode = run(cmd, **kwargs)
|
||||
if retcode:
|
||||
if retcode not in ret_ok:
|
||||
msg = "Command `%s' returned non-zero exit status %d" % (cmd, retcode)
|
||||
raise PatoolError(msg)
|
||||
return retcode
|
||||
|
|
@ -391,12 +405,69 @@ def log_info (msg, out=sys.stdout):
|
|||
print("patool:", msg, file=out)
|
||||
|
||||
|
||||
def log_internal_error (out=sys.stderr):
|
||||
"""Print internal error message to stderr."""
|
||||
print("patool: internal error", file=out)
|
||||
traceback.print_exc()
|
||||
def log_internal_error(out=sys.stderr, etype=None, evalue=None, tb=None):
|
||||
"""Print internal error message (output defaults to stderr)."""
|
||||
print(os.linesep, file=out)
|
||||
print("""********** Oops, I did it again. *************
|
||||
|
||||
You have found an internal error in %(app)s. Please write a bug report
|
||||
at %(url)s and include at least the information below:
|
||||
|
||||
Not disclosing some of the information below due to privacy reasons is ok.
|
||||
I will try to help you nonetheless, but you have to give me something
|
||||
I can work with ;) .
|
||||
""" % dict(app=AppName, url=SupportUrl), file=out)
|
||||
if etype is None:
|
||||
etype = sys.exc_info()[0]
|
||||
if evalue is None:
|
||||
evalue = sys.exc_info()[1]
|
||||
print(etype, evalue, file=out)
|
||||
if tb is None:
|
||||
tb = sys.exc_info()[2]
|
||||
traceback.print_exception(etype, evalue, tb, None, out)
|
||||
print_app_info(out=out)
|
||||
print_locale_info(out=out)
|
||||
print(os.linesep,
|
||||
"******** %s internal error, over and out ********" % AppName, file=out)
|
||||
|
||||
def print_env_info(key, out=sys.stderr):
|
||||
"""If given environment key is defined, print it out."""
|
||||
value = os.getenv(key)
|
||||
if value is not None:
|
||||
print(key, "=", repr(value), file=out)
|
||||
|
||||
|
||||
def print_locale_info(out=sys.stderr):
|
||||
"""Print locale info."""
|
||||
for key in ("LANGUAGE", "LC_ALL", "LC_CTYPE", "LANG"):
|
||||
print_env_info(key, out=out)
|
||||
|
||||
|
||||
def print_app_info(out=sys.stderr):
|
||||
"""Print system and application info (output defaults to stderr)."""
|
||||
print("System info:", file=out)
|
||||
print("Python %s on %s" % (sys.version, sys.platform), file=out)
|
||||
print(App, file=out)
|
||||
print("Python %(version)s on %(platform)s" %
|
||||
{"version": sys.version, "platform": sys.platform}, file=out)
|
||||
stime = strtime(time.time())
|
||||
print("Local time:", stime, file=out)
|
||||
print("sys.argv", sys.argv, file=out)
|
||||
|
||||
|
||||
def strtime(t):
|
||||
"""Return ISO 8601 formatted time."""
|
||||
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(t)) + \
|
||||
strtimezone()
|
||||
|
||||
|
||||
def strtimezone():
|
||||
"""Return timezone info, %z on some platforms, but not supported on all.
|
||||
"""
|
||||
if time.daylight:
|
||||
zone = time.altzone
|
||||
else:
|
||||
zone = time.timezone
|
||||
return "%+04d" % (-zone//3600)
|
||||
|
||||
|
||||
def p7zip_supports_rar ():
|
||||
|
|
@ -480,17 +551,20 @@ def is_same_filename (filename1, filename2):
|
|||
return os.path.realpath(filename1) == os.path.realpath(filename2)
|
||||
|
||||
|
||||
def link_or_copy(src, dst, verbose=False):
|
||||
def link_or_copy(src, dst, verbosity=0):
|
||||
"""Try to make a hard link from src to dst and if that fails
|
||||
copy the file. Hard links save some disk space and linking
|
||||
should fail fast since no copying is involved.
|
||||
"""
|
||||
if verbose:
|
||||
if verbosity > 0:
|
||||
log_info("Copying %s -> %s" % (src, dst))
|
||||
try:
|
||||
os.link(src, dst)
|
||||
except OSError:
|
||||
shutil.copy(src, dst)
|
||||
try:
|
||||
shutil.copy(src, dst)
|
||||
except OSError as msg:
|
||||
raise PatoolError(msg)
|
||||
|
||||
|
||||
def chdir(directory):
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -309,7 +309,7 @@ installed.
|
|||
classifiers = [
|
||||
'Environment :: Console',
|
||||
'Topic :: System :: Archiving',
|
||||
'Development Status :: 4 - Beta',
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'Programming Language :: Python',
|
||||
'Operating System :: OS Independent',
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import importlib
|
|||
|
||||
basedir = os.path.dirname(__file__)
|
||||
datadir = os.path.join(basedir, 'data')
|
||||
patool_cmd = os.path.join(os.path.dirname(basedir), "patool")
|
||||
|
||||
# Python 3.x renamed the function name attribute
|
||||
if sys.version_info[0] > 2:
|
||||
|
|
|
|||
|
|
@ -67,15 +67,15 @@ class ArchiveTest (unittest.TestCase):
|
|||
self._archive_extract(archive, check)
|
||||
# archive name relative to tmpdir
|
||||
relarchive = os.path.join("..", archive[len(basedir)+1:])
|
||||
self._archive_extract(relarchive, check, verbose=True)
|
||||
self._archive_extract(relarchive, check, verbosity=1)
|
||||
|
||||
def _archive_extract (self, archive, check, verbose=False):
|
||||
def _archive_extract (self, archive, check, verbosity=0):
|
||||
# create a temporary directory for extraction
|
||||
tmpdir = patoolib.util.tmpdir(dir=basedir)
|
||||
try:
|
||||
olddir = patoolib.util.chdir(tmpdir)
|
||||
try:
|
||||
output = patoolib._handle_archive(archive, 'extract', program=self.program, verbose=verbose)
|
||||
output = patoolib.extract_archive(archive, program=self.program, verbosity=verbosity)
|
||||
if check:
|
||||
self.check_extracted_archive(archive, output, check)
|
||||
finally:
|
||||
|
|
@ -103,10 +103,12 @@ class ArchiveTest (unittest.TestCase):
|
|||
self.check_textfile(txtfile2, 't2.txt')
|
||||
|
||||
def check_directory (self, dirname, expectedname):
|
||||
"""Check that directory exists."""
|
||||
self.assertTrue(os.path.isdir(dirname), dirname)
|
||||
self.assertEqual(os.path.basename(dirname), expectedname)
|
||||
|
||||
def check_textfile (self, filename, expectedname):
|
||||
"""Check that filename exists and has the default content."""
|
||||
self.assertTrue(os.path.isfile(filename), repr(filename))
|
||||
self.assertEqual(os.path.basename(filename), expectedname)
|
||||
self.assertEqual(get_filecontent(filename), TextFileContent)
|
||||
|
|
@ -114,14 +116,14 @@ class ArchiveTest (unittest.TestCase):
|
|||
def archive_list (self, filename):
|
||||
"""Test archive listing."""
|
||||
archive = os.path.join(datadir, filename)
|
||||
patoolib._handle_archive(archive, 'list', program=self.program)
|
||||
patoolib._handle_archive(archive, 'list', program=self.program, verbose=True)
|
||||
for verbosity in (-1, 0, 1, 2):
|
||||
patoolib.list_archive(archive, program=self.program, verbosity=verbosity)
|
||||
|
||||
def archive_test (self, filename):
|
||||
"""Test archive testing."""
|
||||
archive = os.path.join(datadir, filename)
|
||||
patoolib._handle_archive(archive, 'test', program=self.program)
|
||||
patoolib._handle_archive(archive, 'test', program=self.program, verbose=True)
|
||||
for verbosity in (-1, 0, 1, 2):
|
||||
patoolib.test_archive(archive, program=self.program, verbosity=verbosity)
|
||||
|
||||
def archive_create (self, archive, srcfiles=None, check=Content.Recursive):
|
||||
"""Test archive creation."""
|
||||
|
|
@ -138,14 +140,13 @@ class ArchiveTest (unittest.TestCase):
|
|||
try:
|
||||
# The format and compression arguments are needed for creating
|
||||
# archives with unusual file extensions.
|
||||
self._archive_create(archive, srcfiles, program=self.program)
|
||||
# create again in verbose mode
|
||||
self._archive_create(archive, srcfiles, program=self.program, verbose=True)
|
||||
for verbosity in (-1, 0, 1, 2):
|
||||
self._archive_create(archive, srcfiles, program=self.program, verbosity=verbosity)
|
||||
finally:
|
||||
if olddir:
|
||||
os.chdir(olddir)
|
||||
|
||||
def _archive_create (self, archive, srcfiles, **kwargs):
|
||||
def _archive_create (self, archive, srcfiles, program=None, verbosity=0):
|
||||
"""Create archive from filename."""
|
||||
for srcfile in srcfiles:
|
||||
self.assertFalse(os.path.isabs(srcfile))
|
||||
|
|
@ -155,7 +156,7 @@ class ArchiveTest (unittest.TestCase):
|
|||
try:
|
||||
archive = os.path.join(tmpdir, archive)
|
||||
self.assertTrue(os.path.isabs(archive), "archive path is not absolute: %r" % archive)
|
||||
patoolib._handle_archive(archive, 'create', *srcfiles, **kwargs)
|
||||
patoolib.create_archive(archive, srcfiles, verbosity=verbosity, program=program)
|
||||
self.assertTrue(os.path.isfile(archive))
|
||||
self.check_created_archive_with_test(archive)
|
||||
self.check_created_archive_with_diff(archive, srcfiles)
|
||||
|
|
@ -163,7 +164,7 @@ class ArchiveTest (unittest.TestCase):
|
|||
shutil.rmtree(tmpdir)
|
||||
|
||||
def check_created_archive_with_test(self, archive):
|
||||
command = 'test'
|
||||
command = patoolib.test_archive
|
||||
program = self.program
|
||||
# special case for programs that cannot test what they create
|
||||
if self.program in ('compress', 'py_gzip'):
|
||||
|
|
@ -176,12 +177,12 @@ class ArchiveTest (unittest.TestCase):
|
|||
program = 'unzip'
|
||||
elif self.program in ('rzip', 'shorten'):
|
||||
program = 'py_echo'
|
||||
command = 'list'
|
||||
command = patoolib.list_archive
|
||||
elif self.program == 'lcab':
|
||||
program = 'cabextract'
|
||||
elif self.program == 'shar':
|
||||
return
|
||||
patoolib._handle_archive(archive, command, program=program)
|
||||
command(archive, program=program)
|
||||
|
||||
def check_created_archive_with_diff(self, archive, srcfiles):
|
||||
"""Extract created archive again and compare the contents."""
|
||||
|
|
@ -203,17 +204,15 @@ class ArchiveTest (unittest.TestCase):
|
|||
try:
|
||||
olddir = patoolib.util.chdir(tmpdir)
|
||||
try:
|
||||
output = patoolib._handle_archive(archive, 'extract', program=program)
|
||||
output = patoolib.extract_archive(archive, program=program)
|
||||
if len(srcfiles) == 1:
|
||||
source = os.path.join(datadir, srcfiles[0])
|
||||
res = patoolib.util.run([diff, "-urN", source, output])
|
||||
self.assertEqual(res, 0)
|
||||
patoolib.util.run_checked([diff, "-urN", source, output])
|
||||
else:
|
||||
for srcfile in srcfiles:
|
||||
source = os.path.join(datadir, srcfile)
|
||||
target = os.path.join(output, srcfile)
|
||||
res = patoolib.util.run([diff, "-urN", source, target])
|
||||
self.assertEqual(res, 0)
|
||||
patoolib.util.run_checked([diff, "-urN", source, target])
|
||||
finally:
|
||||
if olddir:
|
||||
os.chdir(olddir)
|
||||
|
|
@ -222,15 +221,17 @@ class ArchiveTest (unittest.TestCase):
|
|||
|
||||
|
||||
def get_filecontent(filename):
|
||||
"""Get file data as text."""
|
||||
with open(filename) as fo:
|
||||
return fo.read()
|
||||
|
||||
|
||||
def get_nonexisting_directory(basedir):
|
||||
"""Note: this is _not_ intended to be used to create a directory."""
|
||||
d = os.path.join(basedir, "foo")
|
||||
while os.path.exists(d):
|
||||
d += 'a'
|
||||
if len(d) > 100:
|
||||
# wtf
|
||||
raise ValueError('could not find non-existing directory at %r' % basedir)
|
||||
raise ValueError('could not construct unique directory name at %r' % basedir)
|
||||
return d
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
from patoolib import baker
|
||||
|
||||
|
||||
class TestBaker (unittest.TestCase):
|
||||
|
||||
def test_func_args (self):
|
||||
@baker.command
|
||||
def func(a, b, c):
|
||||
return (a, b, c)
|
||||
argv = [__file__, 'func', '1', '2', '3']
|
||||
self.assertEqual(baker.test(argv=argv), "func('1','2','3')")
|
||||
self.assertEqual(baker.run(argv=argv), ('1','2','3'))
|
||||
|
||||
def test_func_noargs (self):
|
||||
@baker.command
|
||||
def func():
|
||||
return 42
|
||||
argv = [__file__, 'func']
|
||||
self.assertEqual(baker.test(argv=argv), "func()")
|
||||
self.assertEqual(baker.run(argv=argv), 42)
|
||||
|
||||
def test_func_kwargs (self):
|
||||
@baker.command
|
||||
def func(arg1, arg2, *args, **kwargs):
|
||||
return arg1, arg2, kwargs['verbose']
|
||||
argv = [__file__, 'func', 'argvalue1', 'argvalue2', '--verbose']
|
||||
self.assertEqual(baker.test(argv=argv), "func('argvalue1','argvalue2',verbose=True)")
|
||||
self.assertEqual(baker.run(argv=argv), ('argvalue1', 'argvalue2', True))
|
||||
|
||||
def test_func_kwargs_revorder (self):
|
||||
@baker.command
|
||||
def func(arg1, arg2, *args, **kwargs):
|
||||
return arg1, arg2, kwargs['verbose']
|
||||
argv = [__file__, 'func', 'argvalue1', '--verbose', 'argvalue2']
|
||||
self.assertEqual(baker.test(argv=argv), "func('argvalue1','argvalue2',verbose=True)")
|
||||
self.assertEqual(baker.run(argv=argv), ('argvalue1', 'argvalue2', True))
|
||||
|
||||
def test_func_kwargs_params (self):
|
||||
@baker.command(shortopts={"verbose": "v"}, params={"verbose": "Be verbose"})
|
||||
def func(*args, **kwargs):
|
||||
return kwargs['verbose']
|
||||
res = baker.run(argv=[__file__, 'func', '--verbose', 'arg1'])
|
||||
self.assertEqual(res, True)
|
||||
res = baker.run(argv=[__file__, 'func', 'arg1', '--verbose'])
|
||||
self.assertEqual(res, True)
|
||||
res = baker.run(argv=[__file__, 'func', '-v'])
|
||||
self.assertEqual(res, True)
|
||||
res = baker.run(argv=[__file__, 'func', '-v', 'arg1'])
|
||||
self.assertEqual(res, True)
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
from patoolib import util
|
||||
from . import basedir, datadir, needs_program, patool_cmd
|
||||
|
||||
class ArchiveCreateTest (unittest.TestCase):
|
||||
|
||||
@needs_program('7z')
|
||||
def test_create(self):
|
||||
tmpdir = util.tmpdir(dir=basedir)
|
||||
try:
|
||||
files = [os.path.join(datadir, "t"), os.path.join(datadir, "t.txt")]
|
||||
archive = os.path.join(tmpdir, "t.7z")
|
||||
cmd = [sys.executable, patool_cmd, "-vv", "create", archive]
|
||||
cmd.extend(files)
|
||||
util.run_checked(cmd)
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2010-2012 Bastian Kleineidam
|
||||
# Copyright (C) 2010-2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -15,8 +15,9 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
import os
|
||||
import patoolib
|
||||
from . import datadir, needs_program
|
||||
import sys
|
||||
from patoolib.util import run_checked
|
||||
from . import datadir, needs_program, patool_cmd
|
||||
|
||||
class ArchiveDiffTest (unittest.TestCase):
|
||||
|
||||
|
|
@ -26,6 +27,4 @@ class ArchiveDiffTest (unittest.TestCase):
|
|||
def test_diff (self):
|
||||
archive1 = os.path.join(datadir, "t.tar")
|
||||
archive2 = os.path.join(datadir, "t.zip")
|
||||
res = patoolib.handle_archive(archive1, "diff", archive2)
|
||||
# both archives have the same data
|
||||
self.assertEqual(res, 0)
|
||||
run_checked([sys.executable, patool_cmd, "-vv", "diff", archive1, archive2])
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
from patoolib import util
|
||||
from . import basedir, datadir, needs_program, patool_cmd
|
||||
|
||||
class ArchiveExtractTest (unittest.TestCase):
|
||||
|
||||
@needs_program('7z')
|
||||
def test_extract(self):
|
||||
tmpdir = util.tmpdir(dir=basedir)
|
||||
try:
|
||||
archive = os.path.join(datadir, "t .7z")
|
||||
util.run_checked([sys.executable, patool_cmd, "-vv", "extract", "--outdir", tmpdir, archive])
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
|
|
@ -14,9 +14,11 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
import patoolib
|
||||
import sys
|
||||
from patoolib.util import run_checked
|
||||
from . import patool_cmd
|
||||
|
||||
class TestFormats (unittest.TestCase):
|
||||
|
||||
def test_list_formats (self):
|
||||
patoolib.list_formats()
|
||||
run_checked([sys.executable, patool_cmd, "-vv", 'formats'])
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
from patoolib.util import run_checked
|
||||
from . import datadir, needs_program, patool_cmd
|
||||
|
||||
class ArchiveListTest (unittest.TestCase):
|
||||
|
||||
@needs_program('tar')
|
||||
def test_list(self):
|
||||
archive = os.path.join(datadir, "t.tar")
|
||||
run_checked([sys.executable, patool_cmd, "-vv", "list", archive])
|
||||
|
|
@ -15,23 +15,21 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import patoolib
|
||||
from . import datadir, needs_program, needs_one_program
|
||||
from patoolib import util
|
||||
from . import datadir, needs_program, needs_one_program, patool_cmd
|
||||
|
||||
class ArchiveRepackTest (unittest.TestCase):
|
||||
|
||||
def repack(self, name1, name2):
|
||||
"""Repack archive with name1 to archive with name2."""
|
||||
archive1 = os.path.join(datadir, name1)
|
||||
tmpdir = patoolib.util.tmpdir()
|
||||
tmpdir = util.tmpdir()
|
||||
try:
|
||||
archive2 = os.path.join(tmpdir, name2)
|
||||
res = patoolib.handle_archive(archive1, "repack", archive2)
|
||||
self.assertEqual(res, 0)
|
||||
res = patoolib.handle_archive(archive1, "diff", archive2)
|
||||
# both archives have the same data
|
||||
self.assertEqual(res, 0)
|
||||
util.run_checked([sys.executable, patool_cmd, "-vv", "repack", archive1, archive2])
|
||||
util.run_checked([sys.executable, patool_cmd, "diff", archive1, archive2])
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
import os
|
||||
import patoolib
|
||||
from . import datadir, needs_program
|
||||
import sys
|
||||
from patoolib.util import run_checked
|
||||
from . import datadir, needs_program, patool_cmd
|
||||
|
||||
class ArchiveSearchTest (unittest.TestCase):
|
||||
|
||||
|
|
@ -25,7 +26,10 @@ class ArchiveSearchTest (unittest.TestCase):
|
|||
@needs_program('tar')
|
||||
def test_search(self):
|
||||
pattern = "42"
|
||||
archive1 = os.path.join(datadir, "t.tar")
|
||||
archive2 = os.path.join(datadir, "t.zip")
|
||||
res = patoolib.handle_archive(pattern, "search", archive1, archive2)
|
||||
self.assertEqual(res, 0)
|
||||
archive = os.path.join(datadir, "t.tar")
|
||||
self.search(pattern, archive)
|
||||
archive = os.path.join(datadir, "t.zip")
|
||||
self.search(pattern, archive)
|
||||
|
||||
def search(self, pattern, archive):
|
||||
run_checked([sys.executable, patool_cmd, "-vv", "search", pattern, archive])
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2013 Bastian Kleineidam
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
import os
|
||||
import sys
|
||||
from patoolib.util import run_checked
|
||||
from . import datadir, needs_program, patool_cmd
|
||||
|
||||
class ArchiveTestTest (unittest.TestCase):
|
||||
|
||||
@needs_program('7z')
|
||||
def test_test(self):
|
||||
archive = os.path.join(datadir, "t .7z")
|
||||
run_checked([sys.executable, patool_cmd, "test", archive])
|
||||
Loading…
Reference in New Issue