Add Python3 support.

This commit is contained in:
Bastian Kleineidam 2012-11-19 20:58:42 +01:00
parent a12a5adb35
commit d7f453cc34
9 changed files with 97 additions and 76 deletions

View File

@ -1,6 +1,7 @@
0.18 "" (released xx.xx.xxxx)
* Fixed unadf archive listing.
* Added support for Python 3.x and depend on Python >= 2.7.
0.17 "I am Bruce Lee" (released 4.8.2012)

View File

@ -3,7 +3,7 @@ Installation
First, install the required software.
1. Python >= 2.5 from http://www.python.org/
1. Python >= 2.7 from http://www.python.org/
Be sure to also have installed the included distutils module.
On most distributions, the distutils module is included in

7
patool
View File

@ -17,6 +17,7 @@
"""
patool [extract|list|create|formats] [sub-command-options] <command-args>
"""
from __future__ import print_function
import os
import sys
from patoolib import handle_archive, list_formats, baker
@ -35,7 +36,7 @@ def handle_multi_archive(archives, cmd, **kwargs):
if not os.path.isfile(archive):
res = 1
msg = "archive %r is not a file" % archive
print >>sys.stderr, "patool error:", msg
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
@ -94,7 +95,7 @@ def formats ():
try:
sys.exit(baker.run())
except baker.CommandError, msg:
print >>sys.stderr, "patool error:", msg
except baker.CommandError as msg:
print("patool error:", msg, file=sys.stderr)
baker.help(sys.argv[0])
sys.exit(1)

View File

@ -13,12 +13,14 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import sys
if not hasattr(sys, "version_info") or sys.version_info < (2, 5, 0, "final", 0):
raise SystemExit("This program requires Python 2.5 or later.")
if not hasattr(sys, "version_info") or sys.version_info < (2, 7, 0, "final", 0):
raise SystemExit("This program requires Python 2.7 or later.")
import os
import shutil
import stat
import importlib
from . import util
# Supported archive commands
@ -310,29 +312,29 @@ def program_supports_compression (program, compression):
def list_formats ():
"""Print information about available archive formats to stdout."""
for format in ArchiveFormats:
print format, "files:"
print(format, "files:")
for command in ArchiveCommands:
programs = ArchivePrograms[format]
if command not in programs and None not in programs:
print " %8s: - (not supported)" % command
print(" %8s: - (not supported)" % command)
continue
try:
program = find_archive_program(format, command)
print " %8s: %s" % (command, program),
print(" %8s: %s" % (command, program), end=' ')
if format == 'tar':
encs = [x for x in ArchiveCompressions if util.find_program(x)]
if encs:
print "(supported compressions: %s)" % ", ".join(encs),
print("(supported compressions: %s)" % ", ".join(encs), end=' ')
elif format == '7z':
if util.p7zip_supports_rar():
print "(rar archives supported)",
print("(rar archives supported)", end=' ')
else:
print "(rar archives not supported)",
print
print("(rar archives not supported)", end=' ')
print()
except util.PatoolError:
handlers = programs.get(None, programs.get(command))
print " %8s: - (no program found; install %s)" % \
(command, util.strlist_with_or(handlers))
print(" %8s: - (no program found; install %s)" %
(command, util.strlist_with_or(handlers)))
return 0
@ -521,15 +523,17 @@ def _handle_archive (archive, command, *args, **kwargs):
def get_archive_cmdlist_func (program, command, format):
# get python module for given archive program
key = util.stripext(os.path.basename(program).lower())
module = ProgramModules.get(key, key)
# import archive handler function (eg. patoolib.programs.star.extract_tar)
args = (module, command, format)
import_cmd = "from .programs.%s import %s_%s as func" % args
modulename = ".programs." + ProgramModules.get(key, key)
# import the module
try:
exec import_cmd
except ImportError:
raise util.PatoolError('ImportError executing %r' % import_cmd)
return locals()['func']
module = importlib.import_module(modulename, __name__)
except ImportError as msg:
raise util.PatoolError(msg)
# get archive handler function (eg. patoolib.programs.star.extract_tar)
try:
return getattr(module, '%s_%s' % (command, format))
except AttributeError as msg:
raise util.PatoolError(msg)
def rmtree_log_error (func, path, exc):
@ -542,7 +546,7 @@ def _diff_archives (archive1, archive2, **kwargs):
"""Show differences between two archives."""
if util.is_same_file(archive1, archive2):
msg = "no differences found: archive `%s' and `%s' are the same files"
print msg % (archive1, archive2)
print(msg % (archive1, archive2))
return 0
diff = util.find_program("diff")
if not diff:
@ -588,10 +592,10 @@ def handle_archive (archive, command, *args, **kwargs):
except KeyboardInterrupt:
util.log_error("aborted")
res = 1
except util.PatoolError, msg:
except util.PatoolError as msg:
util.log_error(msg)
res = 1
except StandardError, msg:
except Exception as msg:
util.log_internal_error()
res = 1
return res

View File

@ -82,6 +82,11 @@ def format_paras(paras, width, indent=0):
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:
@ -188,10 +193,10 @@ class Baker(object):
if defaults:
# Zip up the keyword argument names with their defaults
keywords = dict(zip(arglist[0-len(defaults):], defaults))
keywords = dict(list(zip(arglist[0-len(defaults):], defaults)))
elif has_kwargs:
# Allow keyword arguments specified by params.
keywords = dict(zip(params.keys(), [""]*len(params)))
keywords = dict(list(zip(params.keys(), [""]*len(params))))
# But set a flag to detect this
self.param_keywords = True
else:
@ -409,7 +414,7 @@ class Baker(object):
# Process short option(s)
# For each character after the '-'...
for i in xrange(1, len(arg)):
for i in range(1, len(arg)):
char = arg[i]
if char not in shortchars:
continue

View File

@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Archive commands echoing data, implemented by the Python print
statement."""
from __future__ import print_function
from .. import util
@ -60,5 +61,5 @@ def list_flac (archive, compression, cmd, **kwargs):
def stripext (cmd, archive, extension=""):
"""Print the name without suffix."""
print util.stripext(archive)+extension
print(util.stripext(archive)+extension)
return None

View File

@ -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/>.
"""Utility functions."""
from __future__ import print_function
import os
import sys
import subprocess
@ -30,7 +31,7 @@ def init_mimedb():
global mimedb
try:
mimedb = mimetypes.MimeTypes(strict=False)
except StandardError, msg:
except Exception as msg:
log_error("could not initialize MIME database: %s" % msg)
return
add_mimedb_data(mimedb)
@ -78,7 +79,7 @@ def add_mimetype(mimedb, mimetype, extension):
mimedb.add_type(mimetype, extension, strict=strict)
class PatoolError (StandardError):
class PatoolError (Exception):
"""Raised when errors occur."""
pass
@ -324,7 +325,7 @@ def set_mode (filename, flags):
if not (mode & flags):
try:
os.chmod(filename, flags | mode)
except OSError, msg:
except OSError as msg:
log_error("could not set mode flags for `%s': %s" % (filename, msg))
@ -375,20 +376,20 @@ def get_single_outfile (directory, archive, extension=""):
def log_error (msg, out=sys.stderr):
"""Print error message to stderr (or any other given output)."""
print >> out, "patool error:", msg
print("patool error:", msg, file=out)
def log_info (msg, out=sys.stdout):
"""Print info message to stdout (or any other given output)."""
print >> out, "patool:", msg
print("patool:", msg, file=out)
def log_internal_error (out=sys.stderr):
"""Print internal error message to stderr."""
print >> out, "patool: internal error"
print("patool: internal error", file=out)
traceback.print_exc()
print >> out, "System info:"
print >> out, "Python %s on %s" % (sys.version, sys.platform)
print("System info:", file=out)
print("Python %s on %s" % (sys.version, sys.platform), file=out)
def p7zip_supports_rar ():
@ -421,13 +422,17 @@ def append_to_path (path, directory):
def get_nt_7z_dir ():
"""Return 7-Zip directory from registry, or an empty string."""
# Python 3.x renamed the _winreg module to winreg
try:
import _winreg
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\7-Zip")
import _winreg as winreg
except ImportError:
import winreg
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\7-Zip")
try:
return _winreg.QueryValueEx(key, "Path")[0]
return winreg.QueryValueEx(key, "Path")[0]
finally:
_winreg.CloseKey(key)
winreg.CloseKey(key)
except WindowsError:
return ""

View File

@ -17,10 +17,10 @@
"""
Setup file for the distuils module.
"""
from __future__ import print_function
import sys
if not hasattr(sys, "version_info") or sys.version_info < (2, 4, 0, "final", 0):
raise SystemExit("This program requires Python 2.4 or later.")
if not hasattr(sys, "version_info") or sys.version_info < (2, 7, 0, "final", 0):
raise SystemExit("This program requires Python 2.7 or later.")
import os
import shutil
import glob
@ -164,37 +164,37 @@ class InnoScript:
def write_inno_script (self, fd):
"""Write Inno script contents."""
print >> fd, "; WARNING: This script has been created by py2exe. Changes to this script"
print >> fd, "; will be overwritten the next time py2exe is run!"
print >> fd, "[Setup]"
print >> fd, "AppName=%s" % self.name
print >> fd, "AppVerName=%s %s" % (self.name, self.version)
print >> fd, r"DefaultDirName={pf}\%s" % self.name
print >> fd, "DefaultGroupName=%s" % self.name
print >> fd, "OutputBaseFilename=%s" % self.distfilebase
print >> fd, "OutputDir=.."
print >> fd, "SetupIconFile=%s" % self.icon
print >> fd
print("; WARNING: This script has been created by py2exe. Changes to this script", file=fd)
print("; will be overwritten the next time py2exe is run!", file=fd)
print("[Setup]", file=fd)
print("AppName=%s" % self.name, file=fd)
print("AppVerName=%s %s" % (self.name, self.version), file=fd)
print(r"DefaultDirName={pf}\%s" % self.name, file=fd)
print("DefaultGroupName=%s" % self.name, file=fd)
print("OutputBaseFilename=%s" % self.distfilebase, file=fd)
print("OutputDir=..", file=fd)
print("SetupIconFile=%s" % self.icon, file=fd)
print(file=fd)
# List of source files
files = self.windows_exe_files + \
self.console_exe_files + \
self.service_exe_files + \
self.comserver_files + \
self.lib_files
print >> fd, '[Files]'
print('[Files]', file=fd)
for path in files:
print >> fd, r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion' % (path, os.path.dirname(path))
print(r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion' % (path, os.path.dirname(path)), file=fd)
# Set icon filename
print >> fd, '[Icons]'
print('[Icons]', file=fd)
for path in self.windows_exe_files:
print >> fd, r'Name: "{group}\%s"; Filename: "{app}\%s"' % \
(self.name, path)
print >> fd, r'Name: "{group}\Uninstall %s"; Filename: "{uninstallexe}"' % self.name
print >> fd
print(r'Name: "{group}\%s"; Filename: "{app}\%s"' %
(self.name, path), file=fd)
print(r'Name: "{group}\Uninstall %s"; Filename: "{uninstallexe}"' % self.name, file=fd)
print(file=fd)
# Uninstall optional log files
print >> fd, '[UninstallDelete]'
print >> fd, r'Type: files; Name: "{pf}\%s\patool*.exe.log"' % self.name
print >> fd
print('[UninstallDelete]', file=fd)
print(r'Type: files; Name: "{pf}\%s\patool*.exe.log"' % self.name, file=fd)
print(file=fd)
def compile (self):
"""Compile Inno script with iscc.exe."""
@ -209,7 +209,7 @@ class InnoScript:
cmd = ['signtool.exe', 'sign', '/f', pfxfile, self.distfile]
subprocess.check_call(cmd)
else:
print "No signed installer: certificate %s not found." % pfxfile
print("No signed installer: certificate %s not found." % pfxfile)
try:
from py2exe.build_exe import py2exe as py2exe_build
@ -222,16 +222,16 @@ try:
"""Generate py2exe installer."""
# First, let py2exe do it's work.
py2exe_build.run(self)
print "*** preparing the inno setup script ***"
print("*** preparing the inno setup script ***")
lib_dir = self.lib_dir
dist_dir = self.dist_dir
# create the Installer, using the files py2exe has created.
script = InnoScript(lib_dir, dist_dir, self.windows_exe_files,
self.console_exe_files, self.service_exe_files,
self.comserver_files, self.lib_files)
print "*** creating the inno setup script ***"
print("*** creating the inno setup script ***")
script.create()
print "*** compiling the inno setup script ***"
print("*** compiling the inno setup script ***")
script.compile()
script.sign()
except ImportError:

View File

@ -14,12 +14,18 @@
# 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 os
import sys
import patoolib
import pytest
basedir = os.path.dirname(__file__)
datadir = os.path.join(basedir, 'data')
# Python 3.x renamed the function name attribute
if sys.version_info[0] > 2:
fnameattr = '__name__'
else:
fnameattr = 'func_name'
def needs_os (name):
"""Decorator skipping test if given program is not available."""
@ -28,7 +34,7 @@ def needs_os (name):
if os.name != name:
raise pytest.skip("operating system %s not found" % name)
return f(*args, **kwargs)
newfunc.func_name = f.func_name
setattr(newfunc, fnameattr, getattr(f, fnameattr))
return newfunc
return check_prog
@ -40,7 +46,7 @@ def needs_program (program):
if not patoolib.util.find_program(program):
raise pytest.skip("program `%s' not available" % program)
return f(*args, **kwargs)
newfunc.func_name = f.func_name
setattr(newfunc, fnameattr, getattr(f, fnameattr))
return newfunc
return check_prog
@ -55,7 +61,7 @@ def needs_one_program (programs):
else:
raise pytest.skip("None of programs %s available" % programs)
return f(*args, **kwargs)
newfunc.func_name = f.func_name
setattr(newfunc, fnameattr, getattr(f, fnameattr))
return newfunc
return check_prog
@ -69,7 +75,7 @@ def needs_codec (program, codec):
if not has_codec(program, codec):
raise pytest.skip("codec `%s' for program `%s' not available" % (codec, program))
return f(*args, **kwargs)
newfunc.func_name = f.func_name
setattr(newfunc, fnameattr, getattr(f, fnameattr))
return newfunc
return check_prog
@ -81,5 +87,3 @@ def has_codec (program, codec):
if patoolib.program_supports_compression(program, codec):
return True
return patoolib.util.find_program(codec)