From 2061c56ada6fdcf32b341a90f3e02f4f535f793b Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Mon, 25 Jun 2018 05:01:35 +0000 Subject: [PATCH 01/68] Python 3 preparation: convert print to a function. --- detectors/irker.py | 3 +- roundup/backends/portalocker.py | 3 +- roundup/cgi/TAL/talgettext.py | 21 +++++++------- roundup/cgi/cgitb.py | 5 ++-- roundup/cgi/engine_jinja2.py | 5 ++-- roundup/date.py | 25 ++++++++-------- roundup/dehtml.py | 11 +++---- roundup/dist/command/build.py | 9 +++--- roundup/init.py | 5 ++-- roundup/mailgw.py | 5 ++-- roundup/msgfmt.py | 21 +++++++------- roundup/scripts/roundup_gettext.py | 5 ++-- roundup/scripts/roundup_mailgw.py | 9 +++--- roundup/scripts/roundup_server.py | 35 ++++++++++++----------- roundup/scripts/roundup_xmlrpc_server.py | 19 +++++++------ roundup/support.py | 3 +- roundup/version_check.py | 5 ++-- scripts/copy-user.py | 23 ++++++++------- scripts/imapServer.py | 3 +- scripts/schema_diagram.py | 21 +++++++------- setup.py | 5 ++-- test/benchmark.py | 5 ++-- test/db_test_base.py | 11 +++---- test/test_actions.py | 5 ++-- test/test_cgi.py | 49 ++++++++++++++++---------------- test/test_security.py | 3 +- test/test_templating.py | 7 +++-- test/test_xmlrpc.py | 13 +++++---- test/tx_Source_detector.py | 5 ++-- tools/load_tracker.py | 13 +++++---- tools/migrate-queries.py | 13 +++++---- tools/pygettext.py | 39 ++++++++++++------------- 32 files changed, 218 insertions(+), 186 deletions(-) diff --git a/detectors/irker.py b/detectors/irker.py index dc42a50..57ce2bf 100644 --- a/detectors/irker.py +++ b/detectors/irker.py @@ -14,6 +14,7 @@ # channels = irc://chat.freenode.net/channelname # +from __future__ import print_function import re import json import socket @@ -94,7 +95,7 @@ def notify_irker(db, cl, nodeid, oldvalues): # Ignore any errors in sending the irker; # if the server is down, that's just bad luck # XXX might want to do some logging here - print '* Sending message to irker failed', str(e) + print('* Sending message to irker failed', str(e)) def init(db): db.issue.react('create', notify_irker) diff --git a/roundup/backends/portalocker.py b/roundup/backends/portalocker.py index c58fdb4..d157353 100644 --- a/roundup/backends/portalocker.py +++ b/roundup/backends/portalocker.py @@ -47,6 +47,7 @@ Roundup Changes - Added return result """ +from __future__ import print_function __docformat__ = 'restructuredtext' import os @@ -151,7 +152,7 @@ if __name__ == '__main__': timestamp = strftime("%m/%d/%Y %H:%M:%S\n", localtime(time())) log.write( timestamp ) - print "Wrote lines. Hit enter to release lock." + print("Wrote lines. Hit enter to release lock.") dummy = sys.stdin.readline() log.close() diff --git a/roundup/cgi/TAL/talgettext.py b/roundup/cgi/TAL/talgettext.py index 1ceabe6..0f742f8 100644 --- a/roundup/cgi/TAL/talgettext.py +++ b/roundup/cgi/TAL/talgettext.py @@ -33,6 +33,7 @@ Options: found. """ +from __future__ import print_function import sys import time import getopt @@ -73,9 +74,9 @@ except NameError: def usage(code, msg=''): # Python 2.1 required - print >> sys.stderr, __doc__ + print(__doc__, file=sys.stderr) if msg: - print >> sys.stderr, msg + print(msg, file=sys.stderr) sys.exit(code) @@ -163,7 +164,7 @@ class UpdatePOEngine(POEngine): try: lines = open(self._filename).readlines() except IOError as msg: - print >> sys.stderr, msg + print(msg, file=sys.stderr) sys.exit(1) section = None @@ -205,9 +206,9 @@ class UpdatePOEngine(POEngine): elif section == STR: msgstr += '%s\n' % l else: - print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \ - 'before:' - print >> sys.stderr, l + print('Syntax error on %s:%d' % (infile, lno), + 'before:', file=sys.stderr) + print(l, file=sys.stderr) sys.exit(1) # Add last entry if section == STR: @@ -253,7 +254,7 @@ def main(): engine = UpdatePOEngine(filename=arg) if not args: - print 'nothing to do' + print('nothing to do') return # We don't care about the rendered output of the .pt file @@ -276,7 +277,7 @@ def main(): POTALInterpreter(program, macros, engine, stream=Devnull(), metal=False)() except: # Hee hee, I love bare excepts! - print 'There was an error processing', filename + print('There was an error processing', filename) traceback.print_exc() # Now output the keys in the engine. Write them to a file if --output or @@ -296,8 +297,8 @@ def main(): except AttributeError: pass if '' not in messages: - print >> outfile, pot_header % {'time': time.ctime(), - 'version': __version__} + print(pot_header % {'time': time.ctime(), + 'version': __version__}, file=outfile) msgids = catalog.keys() # XXX: You should not sort by msgid, but by filename and position. (SR) diff --git a/roundup/cgi/cgitb.py b/roundup/cgi/cgitb.py index c7f1d47..7671ed7 100644 --- a/roundup/cgi/cgitb.py +++ b/roundup/cgi/cgitb.py @@ -4,6 +4,7 @@ """Extended CGI traceback handler by Ka-Ping Yee, . """ +from __future__ import print_function __docformat__ = 'restructuredtext' import sys, os, types, string, keyword, linecache, tokenize, inspect, cgi @@ -213,7 +214,7 @@ def html(context=5, i18n=None): return head + string.join(attribs) + string.join(traceback) + '

 

' def handler(): - print breaker() - print html() + print(breaker()) + print(html()) # vim: set filetype=python ts=4 sw=4 et si : diff --git a/roundup/cgi/engine_jinja2.py b/roundup/cgi/engine_jinja2.py index 8574059..3d2c3bc 100644 --- a/roundup/cgi/engine_jinja2.py +++ b/roundup/cgi/engine_jinja2.py @@ -31,6 +31,7 @@ minimal set (to avoid Roundup state changes from template). https://github.com/mitsuhiko/jinja2/issues/174 """ +from __future__ import print_function import jinja2 import gettext @@ -45,8 +46,8 @@ class Jinja2Loader(LoaderBase): extensions = [ 'jinja2.ext.autoescape', ] - print "Jinja2 templates: ", dir - print "Extensions: ", extensions + print("Jinja2 templates: ", dir) + print("Extensions: ", extensions) self._env = jinja2.Environment( loader=jinja2.FileSystemLoader(dir), extensions=extensions diff --git a/roundup/date.py b/roundup/date.py index 34e25c7..528b979 100644 --- a/roundup/date.py +++ b/roundup/date.py @@ -17,6 +17,7 @@ """Date, time and time interval handling. """ +from __future__ import print_function __docformat__ = 'restructuredtext' import calendar @@ -1204,30 +1205,30 @@ def test_range(): "2002-11-10; 2002-12-12", "; 20:00 +1d", '2002-10-12') rispecs = ('from -1w 2d 4:32 to 4d', '-2w 1d') for rspec in rspecs: - print '>>> Range("%s")' % rspec - print `Range(rspec, Date)` - print + print('>>> Range("%s")' % rspec) + print(`Range(rspec, Date)`) + print() for rspec in rispecs: - print '>>> Range("%s")' % rspec - print `Range(rspec, Interval)` - print + print('>>> Range("%s")' % rspec) + print(`Range(rspec, Interval)`) + print() def test(): intervals = (" 3w 1 d 2:00", " + 2d", "3w") for interval in intervals: - print '>>> Interval("%s")'%interval - print `Interval(interval)` + print('>>> Interval("%s")'%interval) + print(`Interval(interval)`) dates = (".", "2000-06-25.19:34:02", ". + 2d", "1997-04-17", "01-25", "08-13.22:13", "14:25", '2002-12') for date in dates: - print '>>> Date("%s")'%date - print `Date(date)` + print('>>> Date("%s")'%date) + print(`Date(date)`) sums = ((". + 2d", "3w"), (".", " 3w 1 d 2:00")) for date, interval in sums: - print '>>> Date("%s") + Interval("%s")'%(date, interval) - print `Date(date) + Interval(interval)` + print('>>> Date("%s") + Interval("%s")'%(date, interval)) + print(`Date(date) + Interval(interval)`) if __name__ == '__main__': test() diff --git a/roundup/dehtml.py b/roundup/dehtml.py index a4955b2..bb76a3b 100644 --- a/roundup/dehtml.py +++ b/roundup/dehtml.py @@ -1,4 +1,5 @@ +from __future__ import print_function class dehtml: def __init__(self, converter): if converter == "none": @@ -128,20 +129,20 @@ have to install the win32all package separately (get it from html2text = dehtml("dehtml").html2text if html2text: - print html2text(html) + print(html2text(html)) try: # trap error seen if N_TOKENS not defined when run. html2text = dehtml("beautifulsoup").html2text if html2text: - print html2text(html) + print(html2text(html)) except NameError as e: - print "captured error %s"%e + print("captured error %s"%e) html2text = dehtml("none").html2text if html2text: - print "FAIL: Error, dehtml(none) is returning a function" + print("FAIL: Error, dehtml(none) is returning a function") else: - print "PASS: dehtml(none) is returning None" + print("PASS: dehtml(none) is returning None") diff --git a/roundup/dist/command/build.py b/roundup/dist/command/build.py index 4d2a1f5..bc98b49 100644 --- a/roundup/dist/command/build.py +++ b/roundup/dist/command/build.py @@ -3,6 +3,7 @@ # All rights reserved. # For license terms see the file COPYING.txt. # +from __future__ import print_function from roundup import msgfmt from distutils.command.build import build as base import os @@ -26,7 +27,7 @@ def check_manifest(): try: f = open('MANIFEST') except: - print '\n*** SOURCE WARNING: The MANIFEST file is missing!' + print('\n*** SOURCE WARNING: The MANIFEST file is missing!') return try: manifest = [l.strip() for l in f.readlines()] @@ -38,9 +39,9 @@ def check_manifest(): 'roundup-mailgw', 'roundup-server', 'roundup-xmlrpc-server']) if err: n = len(manifest) - print '\n*** SOURCE WARNING: There are files missing (%d/%d found)!'%( - n-len(err), n) - print 'Missing:', '\nMissing: '.join(err) + print('\n*** SOURCE WARNING: There are files missing (%d/%d found)!'%( + n-len(err), n)) + print('Missing:', '\nMissing: '.join(err)) def build_message_files(command): """For each locale/*.po, build .mo file in target locale directory""" diff --git a/roundup/init.py b/roundup/init.py index 05f4c50..2b88d3d 100644 --- a/roundup/init.py +++ b/roundup/init.py @@ -17,6 +17,7 @@ # """Init (create) a roundup instance. """ +from __future__ import print_function __docformat__ = 'restructuredtext' import os, errno, email.parser @@ -132,9 +133,9 @@ def loadTemplateInfo(path): return None if os.path.exists(os.path.join(path, 'config.py')): - print _("WARNING: directory '%s'\n" + print(_("WARNING: directory '%s'\n" "\tcontains old-style template - ignored" - ) % os.path.abspath(path) + ) % os.path.abspath(path)) return None # load up the template's information diff --git a/roundup/mailgw.py b/roundup/mailgw.py index 5fb0d4b..52a8646 100644 --- a/roundup/mailgw.py +++ b/roundup/mailgw.py @@ -92,6 +92,7 @@ are calling the create() method to create a new node). If an auditor raises an exception, the original message is bounced back to the sender with the explanatory message given in the exception. """ +from __future__ import print_function __docformat__ = 'restructuredtext' import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri @@ -1379,7 +1380,7 @@ class MailGW: password = getpass.getpass() except (KeyboardInterrupt, EOFError): # Ctrl C or D maybe also Ctrl Z under Windows. - print "\nAborted by user." + print("\nAborted by user.") return 1 # open a connection to the server and retrieve all messages try: @@ -1468,7 +1469,7 @@ class MailGW: password = getpass.getpass() except (KeyboardInterrupt, EOFError): # Ctrl C or D maybe also Ctrl Z under Windows. - print "\nAborted by user." + print("\nAborted by user.") return 1 # open a connection to the server and retrieve all messages diff --git a/roundup/msgfmt.py b/roundup/msgfmt.py index ee7fec5..fa889ce 100644 --- a/roundup/msgfmt.py +++ b/roundup/msgfmt.py @@ -26,6 +26,7 @@ Options: Display version information and exit. """ +from __future__ import print_function import sys import os import getopt @@ -39,9 +40,9 @@ MESSAGES = {} def usage(code, msg=''): - print >> sys.stderr, __doc__ + print(__doc__, file=sys.stderr) if msg: - print >> sys.stderr, msg + print(msg, file=sys.stderr) sys.exit(code) @@ -117,7 +118,7 @@ def make(filename, outfile): try: lines = open(infile).readlines() except IOError as msg: - print >> sys.stderr, msg + print(msg, file=sys.stderr) sys.exit(1) # remove UTF-8 Byte Order Mark, if any. @@ -176,9 +177,9 @@ def make(filename, outfile): elif section == STR: msgstr += l else: - print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \ - 'before:' - print >> sys.stderr, l + print('Syntax error on %s:%d' % (infile, lno), + 'before:', file=sys.stderr) + print(l, file=sys.stderr) sys.exit(1) # Add last entry if section == STR: @@ -190,7 +191,7 @@ def make(filename, outfile): try: open(outfile,"wb").write(output) except IOError as msg: - print >> sys.stderr, msg + print(msg, file=sys.stderr) @@ -207,14 +208,14 @@ def main(): if opt in ('-h', '--help'): usage(0) elif opt in ('-V', '--version'): - print >> sys.stderr, "msgfmt.py", __version__ + print("msgfmt.py", __version__, file=sys.stderr) sys.exit(0) elif opt in ('-o', '--output-file'): outfile = arg # do it if not args: - print >> sys.stderr, 'No input file given' - print >> sys.stderr, "Try `msgfmt --help' for more information." + print('No input file given', file=sys.stderr) + print("Try `msgfmt --help' for more information.", file=sys.stderr) return for filename in args: diff --git a/roundup/scripts/roundup_gettext.py b/roundup/scripts/roundup_gettext.py index 3a18647..48e5aec 100644 --- a/roundup/scripts/roundup_gettext.py +++ b/roundup/scripts/roundup_gettext.py @@ -4,6 +4,7 @@ """Extract translatable strings from tracker templates""" +from __future__ import print_function import os import sys @@ -30,7 +31,7 @@ TEMPLATE_FILE = "messages.pot" def run(): # return unless command line arguments contain single directory path if (len(sys.argv) != 2) or (sys.argv[1] in ("-h", "--help")): - print _("Usage: %(program)s ") % {"program": sys.argv[0]} + print(_("Usage: %(program)s ") % {"program": sys.argv[0]}) return # collect file paths of html templates home = os.path.abspath(sys.argv[1]) @@ -45,7 +46,7 @@ def run(): htmlfiles = [] # return if no html files found if not htmlfiles: - print _("No tracker templates found in directory %s") % home + print(_("No tracker templates found in directory %s") % home) return # change to locale dir to have relative source references locale = os.path.join(home, "locale") diff --git a/roundup/scripts/roundup_mailgw.py b/roundup/scripts/roundup_mailgw.py index 5c044e4..d3c16b7 100644 --- a/roundup/scripts/roundup_mailgw.py +++ b/roundup/scripts/roundup_mailgw.py @@ -16,6 +16,7 @@ """Command-line script stub that calls the roundup.mailgw. """ +from __future__ import print_function __docformat__ = 'restructuredtext' @@ -43,8 +44,8 @@ from roundup.i18n import _ def usage(args, message=None): if message is not None: - print message - print _( + print(message) + print(_( """Usage: %(program)s [-v] [-c class] [[-C class] -S field=value]* [instance home] [mail source [specification]] Options: @@ -123,7 +124,7 @@ IMAPS_CRAM: This supports the same notation as IMAP. imaps_cram username:password@server [mailbox] -""")%{'program': args[0]} +""")%{'program': args[0]}) return 1 def main(argv): @@ -141,7 +142,7 @@ def main(argv): for (opt, arg) in optionsList: if opt == '-v': - print '%s (python %s)'%(roundup_version, sys.version.split()[0]) + print('%s (python %s)'%(roundup_version, sys.version.split()[0])) return # figure the instance home diff --git a/roundup/scripts/roundup_server.py b/roundup/scripts/roundup_server.py index 366164c..01f2d90 100644 --- a/roundup/scripts/roundup_server.py +++ b/roundup/scripts/roundup_server.py @@ -17,6 +17,7 @@ """Command-line script that runs a server over roundup.cgi.client. """ +from __future__ import print_function __docformat__ = 'restructuredtext' @@ -87,7 +88,7 @@ if hasattr(os, 'fork'): DEFAULT_MULTIPROCESS = MULTIPROCESS_TYPES[-1] def auto_ssl(): - print _('WARNING: generating temporary SSL certificate') + print(_('WARNING: generating temporary SSL certificate')) import OpenSSL, random pkey = OpenSSL.crypto.PKey() pkey.generate_key(OpenSSL.crypto.TYPE_RSA, 768) @@ -236,7 +237,7 @@ class RoundupRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): self.wfile.write('''

%s: An error occurred. Please check the server log for more information.

'''%ts) # out to the logfile - print 'EXCEPTION AT', ts + print('EXCEPTION AT', ts) traceback.print_exc() do_GET = do_POST = do_HEAD = run_cgi @@ -472,7 +473,7 @@ def setgid(group): # if root, setgid to the running user if os.getuid(): - print _('WARNING: ignoring "-g" argument, not root') + print(_('WARNING: ignoring "-g" argument, not root')) return try: @@ -501,7 +502,7 @@ def setuid(user): raise ValueError, _("Can't run as root!") if os.getuid(): - print _('WARNING: ignoring "-u" argument, not root') + print(_('WARNING: ignoring "-u" argument, not root')) return try: @@ -697,8 +698,8 @@ class ServerConfig(configuration.Config): # obtain request server class if self["MULTIPROCESS"] not in MULTIPROCESS_TYPES: - print _("Multiprocess mode \"%s\" is not available, " - "switching to single-process") % self["MULTIPROCESS"] + print(_("Multiprocess mode \"%s\" is not available, " + "switching to single-process") % self["MULTIPROCESS"]) self["MULTIPROCESS"] = "none" server_class = base_server elif self["MULTIPROCESS"] == "fork": @@ -807,7 +808,7 @@ def usage(message=''): specified if -d is used.''' if message: message += '\n' - print _('''%(message)sUsage: roundup-server [options] [name=tracker home]* + print(_('''%(message)sUsage: roundup-server [options] [name=tracker home]* Options: -v print the Roundup version number and exit @@ -869,7 +870,7 @@ How to use "name=tracker home": "port": DEFAULT_PORT, "mp_def": DEFAULT_MULTIPROCESS, "mp_types": ", ".join(MULTIPROCESS_TYPES), -} +}) def writepidfile(pidfile): @@ -975,11 +976,11 @@ def run(port=undefined, success_message=None): if opt in ("-h", "--help"): usage() elif opt in ("-v", "--version"): - print '%s (python %s)' % (roundup_version, - sys.version.split()[0]) + print('%s (python %s)' % (roundup_version, + sys.version.split()[0])) elif opt in ("-S", "--save-config"): config.save() - print _("Configuration saved to %s") % config.filepath + print(_("Configuration saved to %s") % config.filepath) # any of the above options prevent server from running return @@ -997,8 +998,8 @@ def run(port=undefined, success_message=None): # fork the server from our parent if a pidfile is specified if config["PIDFILE"]: if not hasattr(os, 'fork'): - print _("Sorry, you can't run the server as a daemon" - " on this Operating System") + print(_("Sorry, you can't run the server as a daemon" + " on this Operating System")) sys.exit(0) else: if config['NODAEMON']: @@ -1010,15 +1011,15 @@ def run(port=undefined, success_message=None): httpd = config.get_server() if success_message: - print success_message + print(success_message) else: - print _('Roundup server started on %(HOST)s:%(PORT)s') \ - % config + print(_('Roundup server started on %(HOST)s:%(PORT)s') + % config) try: httpd.serve_forever() except KeyboardInterrupt: - print 'Keyboard Interrupt: exiting' + print('Keyboard Interrupt: exiting') if __name__ == '__main__': run() diff --git a/roundup/scripts/roundup_xmlrpc_server.py b/roundup/scripts/roundup_xmlrpc_server.py index 926230e..51b753d 100644 --- a/roundup/scripts/roundup_xmlrpc_server.py +++ b/roundup/scripts/roundup_xmlrpc_server.py @@ -7,6 +7,7 @@ # --- patch sys.path to make sure 'import roundup' finds correct version +from __future__ import print_function import sys import os.path as osp @@ -105,7 +106,7 @@ class RequestHandler(SimpleXMLRPCRequestHandler): if db: db.close() exc, val, tb = sys.exc_info() - print exc, val, tb + print(exc, val, tb) raise if db: db.close() @@ -121,14 +122,14 @@ class Server(SimpleXMLRPCServer): def usage(): - print """Usage: %s: [options] [name=tracker home]+ + print("""Usage: %s: [options] [name=tracker home]+ Options: -e, --encoding -- specify the encoding to use -V -- be verbose when importing -p, --port -- port to listen on -"""%sys.argv[0] +"""%sys.argv[0]) def run(): @@ -158,10 +159,10 @@ def run(): # Validate the argument tracker = roundup.instance.open(home) except ValueError: - print 'Instances must be name=home' + print('Instances must be name=home') sys.exit(-1) except TrackerError: - print 'Tracker home does not exist.' + print('Tracker home does not exist.') sys.exit(-1) tracker_homes[name] = home @@ -170,7 +171,7 @@ def run(): if sys.version_info[0:2] < (2,5): if encoding: - print 'encodings not supported with python < 2.5' + print('encodings not supported with python < 2.5') sys.exit(-1) server = Server(('', port), RequestHandler) else: @@ -178,12 +179,12 @@ def run(): allow_none=True, encoding=encoding) # Go into the main listener loop - print 'Roundup XMLRPC server started on %s:%d' \ - % (socket.gethostname(), port) + print('Roundup XMLRPC server started on %s:%d' + % (socket.gethostname(), port)) try: server.serve_forever() except KeyboardInterrupt: - print 'Keyboard Interrupt: exiting' + print('Keyboard Interrupt: exiting') if __name__ == '__main__': run() diff --git a/roundup/support.py b/roundup/support.py index 1ddae5f..3f86493 100644 --- a/roundup/support.py +++ b/roundup/support.py @@ -2,6 +2,7 @@ places in Roundup code. """ +from __future__ import print_function __docformat__ = 'restructuredtext' import os, time, sys, re @@ -79,7 +80,7 @@ class Progress: self.num += 1 if self.num > self.total: - print self.info, 'done', ' '*(75-len(self.info)-6) + print(self.info, 'done', ' '*(75-len(self.info)-6)) sys.stdout.flush() return self.sequence.next() diff --git a/roundup/version_check.py b/roundup/version_check.py index 9120a2b..ec1d7ab 100644 --- a/roundup/version_check.py +++ b/roundup/version_check.py @@ -1,10 +1,11 @@ #!/usr/bin/env python # Roundup requires Python 2.7+ as mentioned in doc\installation.txt +from __future__ import print_function VERSION_NEEDED = (2,7) import sys if sys.version_info < VERSION_NEEDED: - print "Content-Type: text/plain\n" - print "Roundup requires Python %s.%s or newer." % VERSION_NEEDED + print("Content-Type: text/plain\n") + print("Roundup requires Python %s.%s or newer." % VERSION_NEEDED) sys.exit(0) diff --git a/scripts/copy-user.py b/scripts/copy-user.py index af81824..0d87307 100755 --- a/scripts/copy-user.py +++ b/scripts/copy-user.py @@ -15,6 +15,7 @@ Example: (copies users 3, 4, 5, 6, 7, 8, 9, 10, 14 and 16) """ +from __future__ import print_function import sys import roundup.instance @@ -27,16 +28,16 @@ def copy_user(home1, home2, *userids): try: instance1 = roundup.instance.open(home1) - print "Opened source instance: %s" % home1 + print("Opened source instance: %s" % home1) except: - print "Can't open source instance: %s" % home1 + print("Can't open source instance: %s" % home1) sys.exit(1) try: instance2 = roundup.instance.open(home2) - print "Opened target instance: %s" % home2 + print("Opened target instance: %s" % home2) except: - print "Can't open target instance: %s" % home2 + print("Can't open target instance: %s" % home2) sys.exit(1) db1 = instance1.open('admin') @@ -50,10 +51,10 @@ def copy_user(home1, home2, *userids): try: userid = str(int(userid)) except ValueError as why: - print "Not a numeric user id: %s Skipping ..." % (userid,) + print("Not a numeric user id: %s Skipping ..." % (userid,)) continue if userid not in userlist: - print "User %s not in source instance. Skipping ..." % userid + print("User %s not in source instance. Skipping ..." % userid) continue user = {} @@ -63,23 +64,23 @@ def copy_user(home1, home2, *userids): user[attrib] = value try: db2.user.lookup(user['username']) - print "User %s: Username '%s' exists in target instance. Skipping ..." % (userid, user['username']) + print("User %s: Username '%s' exists in target instance. Skipping ..." % (userid, user['username'])) continue except KeyError as why: pass - print "Copying user %s (%s) ..." % (userid, user['username']) + print("Copying user %s (%s) ..." % (userid, user['username'])) db2.user.create(**user) db2.commit() db2.close() - print "Closed target instance." + print("Closed target instance.") db1.close() - print "Closed source instance." + print("Closed source instance.") if __name__ == "__main__": if len(sys.argv) < 4: - print __doc__ + print(__doc__) sys.exit(1) else: copy_user(*sys.argv[1:]) diff --git a/scripts/imapServer.py b/scripts/imapServer.py index b45acd1..5b9628b 100644 --- a/scripts/imapServer.py +++ b/scripts/imapServer.py @@ -30,6 +30,7 @@ It also connects to a secure IMAP server. The main reasons for this script are: Add an option for changing the uid/gid of the running process. """ +from __future__ import print_function import getpass import logging import imaplib @@ -76,7 +77,7 @@ class RoundupMailbox: raise ValueError, 'Invalid Username' if not self.password: - print 'For server %s, user %s' % (self.server, self.username) + print('For server %s, user %s' % (self.server, self.username)) self.password = getpass.getpass() # password can be empty because it could be superceeded # by a later entry diff --git a/scripts/schema_diagram.py b/scripts/schema_diagram.py index d48cb6f..af3d0df 100644 --- a/scripts/schema_diagram.py +++ b/scripts/schema_diagram.py @@ -10,6 +10,7 @@ # %> dot -Tps schema.dot -o schema.ps # %> gv schema.ps # +from __future__ import print_function import sys import roundup.instance @@ -18,17 +19,17 @@ instance = roundup.instance.open(sys.argv[1]) db = instance.open() # diagram preamble -print 'digraph schema {' -print 'size="8,6"' -print 'node [shape="record" bgcolor="#ffe4c4" style=filled]' -print 'edge [taillabel="1" headlabel="1" dir=back arrowtail=ediamond]' +print('digraph schema {') +print('size="8,6"') +print('node [shape="record" bgcolor="#ffe4c4" style=filled]') +print('edge [taillabel="1" headlabel="1" dir=back arrowtail=ediamond]') # get all the classes types = db.classes.keys() # one record node per class for i in range(len(types)): - print 'node%d [label=\"{%s|}"]'%(i, types[i]) + print('node%d [label=\"{%s|}"]'%(i, types[i])) # now draw in the relations for name in db.classes.keys(): @@ -37,12 +38,12 @@ for name in db.classes.keys(): for a in attributes.keys(): attribute = attributes[a] if isinstance(attribute, roundup.hyperdb.Link): - print 'node%d -> node%d [label=%s]'%(types.index(name), + print('node%d -> node%d [label=%s]'%(types.index(name), types.index(attribute.classname), - a) + a)) elif isinstance(attribute, roundup.hyperdb.Multilink): - print 'node%d -> node%d [taillabel="*" label=%s]'%(types.index(name), + print('node%d -> node%d [taillabel="*" label=%s]'%(types.index(name), types.index(attribute.classname), - a) + a)) # all done -print '}' +print('}') diff --git a/setup.py b/setup.py index 9acfbae..f619e79 100755 --- a/setup.py +++ b/setup.py @@ -19,6 +19,7 @@ # +from __future__ import print_function from roundup.dist.command.build_doc import build_doc from roundup.dist.command.build_scripts import build_scripts from roundup.dist.command.build import build, list_message_files @@ -111,8 +112,8 @@ def main(): # attempt to interpret string as 'ascii' long_description = long_description.encode('ascii') except UnicodeEncodeError as cause: - print >> sys.stderr, "doc/announcement.txt contains non-ascii: %s" \ - % cause + print("doc/announcement.txt contains non-ascii: %s" + % cause, file=sys.stderr) sys.exit(42) setup(name='roundup', diff --git a/test/benchmark.py b/test/benchmark.py index b42a7a2..d3a6af3 100644 --- a/test/benchmark.py +++ b/test/benchmark.py @@ -1,3 +1,4 @@ +from __future__ import print_function import sys, os, time from roundup.hyperdb import String, Password, Link, Multilink, Date, \ @@ -114,13 +115,13 @@ def main(backendname, time=time.time, numissues=10): else: sys.stdout.write(' %-6.2f'%(stamp-last)) last = stamp - print ' %-6.2f'%(last-first) + print(' %-6.2f'%(last-first)) sys.stdout.flush() if __name__ == '__main__': # 0 1 2 3 4 5 6 # 01234567890123456789012345678901234567890123456789012345678901234 - print 'Test name fetch journl jprops lookup filter filtml TOTAL ' + print('Test name fetch journl jprops lookup filter filtml TOTAL ') for name in 'anydbm metakit sqlite'.split(): main(name) for name in 'anydbm metakit sqlite'.split(): diff --git a/test/db_test_base.py b/test/db_test_base.py index c879a01..4983f05 100644 --- a/test/db_test_base.py +++ b/test/db_test_base.py @@ -15,6 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +from __future__ import print_function import unittest, os, shutil, errno, imp, sys, time, pprint, base64, os.path import logging, cgi import gpgmelib @@ -1048,7 +1049,7 @@ class DBTest(commonDBTest): # check history including quiet properties result=self.db.issue.history(new_issue, skipquiet=False) - print result + print(result) ''' output should be like: [ ... ('1', , '1', 'set', {'assignedto': None, 'nosy': (('+', ['3', '2']),), @@ -1061,7 +1062,7 @@ class DBTest(commonDBTest): 'title': 'title'} result.sort() - print "history include quiet props", result[-1] + print("history include quiet props", result[-1]) (id, tx_date, user, action, args) = result[-1] # check piecewise ignoring date of transaction self.assertEqual('1', id) @@ -1078,7 +1079,7 @@ class DBTest(commonDBTest): expected = {'title': 'title'} result.sort() - print "history remove quiet props", result[-1] + print("history remove quiet props", result[-1]) (id, tx_date, user, action, args) = result[-1] # check piecewise self.assertEqual('1', id) @@ -1112,7 +1113,7 @@ class DBTest(commonDBTest): 'deadline': date.Date("2016-07-30.22:39:00.000")} result.sort() - print "result unquiet", result + print("result unquiet", result) (id, tx_date, user, action, args) = result[-1] # check piecewise self.assertEqual('1', id) @@ -3378,7 +3379,7 @@ class SpecialActionTest(FormTestParent): # does a commit of the otk to the database. cl.inner_main() cl.db.close() - print self.out + print(self.out) # Make sure the action was called self.assertEqual(SpecialAction.x, True) # Check that the Reject worked: diff --git a/test/test_actions.py b/test/test_actions.py index 122f5df..ac2e2bd 100644 --- a/test/test_actions.py +++ b/test/test_actions.py @@ -1,3 +1,4 @@ +from __future__ import print_function import unittest from cgi import FieldStorage, MiniFieldStorage @@ -152,7 +153,7 @@ class FakeFilterVarsTestCase(SearchActionTestCase): def testNumKey(self): # testing patch: http://hg.python.org/tracker/roundup/rev/98508a47c126 for val in [ "-1000a", "test", "o0.9999", "o0", "1.00/10" ]: - print "testing ", val + print("testing ", val) self.client.db.classes.get_transitive_prop = lambda x: hyperdb.Number() self.form.value.append(MiniFieldStorage('foo', val)) # invalid numbers self.assertRaises(FormError, self.action.fakeFilterVars) @@ -166,7 +167,7 @@ class FakeFilterVarsTestCase(SearchActionTestCase): def testIntKey(self): # testing patch: http://hg.python.org/tracker/roundup/rev/98508a47c126 for val in [ "-1000a", "test", "-5E-5", "0.9999", "0.0", "1.000", "0456", "1E4" ]: - print "testing ", val + print("testing ", val) self.client.db.classes.get_transitive_prop = lambda x: hyperdb.Integer() self.form.value.append(MiniFieldStorage('foo', val)) self.assertRaises(FormError, self.action.fakeFilterVars) diff --git a/test/test_cgi.py b/test/test_cgi.py index a91ffba..4071edb 100644 --- a/test/test_cgi.py +++ b/test/test_cgi.py @@ -8,6 +8,7 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +from __future__ import print_function import unittest, os, shutil, errno, sys, difflib, cgi, re, StringIO from roundup.cgi import client, actions, exceptions @@ -866,7 +867,7 @@ class FormTestCase(FormTestParent, unittest.TestCase): # test with no headers and config by default requires 1 cl.inner_main() match_at=out[0].find('Unable to verify sufficient headers') - print "result of subtest 1:", out[0] + print("result of subtest 1:", out[0]) self.assertNotEqual(match_at, -1) del(out[0]) @@ -875,7 +876,7 @@ class FormTestCase(FormTestParent, unittest.TestCase): cl.env['HTTP_REFERER'] = 'http://whoami.com/path/' cl.inner_main() match_at=out[0].find('Redirecting to Csrf token is missing.

') - print "result of subtest 6a:", out[0], match_at + print("result of subtest 6a:", out[0], match_at) self.assertEqual(match_at, 33) del(out[0]) cl.db.config['WEB_CSRF_ENFORCE_TOKEN'] = 'yes' @@ -943,7 +944,7 @@ class FormTestCase(FormTestParent, unittest.TestCase): cl.inner_main() match_at=out[0].find('Invalid csrf token found: booogus') - print "result of subtest 7:", out[0] + print("result of subtest 7:", out[0]) self.assertEqual(match_at, 36) del(out[0]) @@ -952,9 +953,9 @@ class FormTestCase(FormTestParent, unittest.TestCase): # verify that we can see the nonce otks = cl.db.getOTKManager() isitthere = otks.exists(nonce) - print "result of subtest 8:", isitthere - print "otks: user, session", otks.get(nonce, 'uid', default=None), \ - otks.get(nonce, 'session', default=None) + print("result of subtest 8:", isitthere) + print("otks: user, session", otks.get(nonce, 'uid', default=None), + otks.get(nonce, 'session', default=None)) self.assertEqual(isitthere, True) form2.update({'@csrf': nonce}) @@ -963,7 +964,7 @@ class FormTestCase(FormTestParent, unittest.TestCase): cl.inner_main() # csrf passes and redirects to the new issue. match_at=out[0].find('Redirecting to
Invalid request

') - print "result of subtest 11:", out[0] + print("result of subtest 11:", out[0]) self.assertEqual(match_at, 33) del(out[0]) # the token should be gone isitthere = otks.exists(nonce) - print "result of subtest 12:", isitthere + print("result of subtest 12:", isitthere) self.assertEqual(isitthere, False) # change to post and should fail w/ invalid csrf # since get deleted the token. cl.env.update({'REQUEST_METHOD': 'POST'}) - print cl.env + print(cl.env) cl.inner_main() match_at=out[0].find('Invalid csrf token found: %s'%nonce) - print "post failure after get", out[0] - print "result of subtest 13:", out[0] + print("post failure after get", out[0]) + print("result of subtest 13:", out[0]) self.assertEqual(match_at, 36) del(out[0]) @@ -1054,7 +1055,7 @@ class FormTestCase(FormTestParent, unittest.TestCase): cl.form = MockNull(file = True, value = "\n\ndisplay\n\n\nuser1\n\n\nusername\n\n\n\n" ) answer ="\n\n\n\n\n\nusername\nadmin\n\n\n\n\n\n" cl.handle_xmlrpc() - print out + print(out) self.assertEqual(out[0], answer) del(out[0]) @@ -1062,14 +1063,14 @@ class FormTestCase(FormTestParent, unittest.TestCase): del(cl.env['HTTP_X-REQUESTED-WITH']) cl.handle_xmlrpc() output="\n\n\n\n\nfaultCode\n1\n\n\nfaultString\n<class 'roundup.exceptions.UsageError'>:Required Header Missing\n\n\n\n\n" - print out[0] + print(out[0]) self.assertEqual(output,out[0]) del(out[0]) # change config to not require X-REQUESTED-WITH header cl.db.config['WEB_CSRF_ENFORCE_HEADER_X-REQUESTED-WITH'] = 'logfailure' cl.handle_xmlrpc() - print out + print(out) self.assertEqual(out[0], answer) del(out[0]) @@ -1609,7 +1610,7 @@ class TemplateHtmlRendering(unittest.TestCase): self.assertEqual(self.client._ok_message, []) result = self.client.renderContext() - print result + print(result) # sha1sum of classic tracker user.forgotten.template must be found sha1sum = '' self.assertNotEqual(-1, result.index(sha1sum)) @@ -1626,7 +1627,7 @@ class TemplateHtmlRendering(unittest.TestCase): self.assertEqual(self.client._error_message, ["this is an error"]) result = self.client.renderContext() - print result + print(result) # sha1sum of classic tracker user.item.template must be found sha1sum = '' self.assertNotEqual(-1, result.index(sha1sum)) diff --git a/test/test_security.py b/test/test_security.py index 8212412..cc74271 100644 --- a/test/test_security.py +++ b/test/test_security.py @@ -18,6 +18,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from __future__ import print_function import os, unittest, shutil from roundup import backends @@ -219,7 +220,7 @@ class PermissionTest(MyTestCase, unittest.TestCase): check=check_old_style, properties=['a', 'b'])) user7 = self.db.user.create(username='user7', roles='Role7') - print user7 + print(user7) # *any* access to class self.assertEquals(has('Test', user1, 'test'), 1) diff --git a/test/test_templating.py b/test/test_templating.py index 7a52b58..3c17c09 100644 --- a/test/test_templating.py +++ b/test/test_templating.py @@ -1,3 +1,4 @@ +from __future__ import print_function import unittest from cgi import FieldStorage, MiniFieldStorage @@ -148,7 +149,7 @@ class HTMLClassTestCase(TemplatingTestCase) : otks=self.client.db.getOTKManager() for test in [ 'module', 'template', 'default_time' ]: - print "Testing:", test + print("Testing:", test) if test == 'module': # test the module function @@ -177,8 +178,8 @@ class HTMLClassTestCase(TemplatingTestCase) : now = time.time() - print "now, timestamp, greater, difference", \ - now, timestamp, greater_than, now - timestamp + print("now, timestamp, greater, difference", + now, timestamp, greater_than, now - timestamp) # lower bound of the difference is above. Upper bound diff --git a/test/test_xmlrpc.py b/test/test_xmlrpc.py index a417dab..eeaf0c5 100644 --- a/test/test_xmlrpc.py +++ b/test/test_xmlrpc.py @@ -4,6 +4,7 @@ # For license terms see the file COPYING.txt. # +from __future__ import print_function import unittest, os, shutil, errno, sys, difflib, cgi, re from xmlrpclib import MultiCall @@ -31,7 +32,7 @@ class XmlrpcTest(object): # open the database self.db = self.instance.open('admin') - print "props_only default", self.db.security.get_props_only_default() + print("props_only default", self.db.security.get_props_only_default()) # Get user id (user4 maybe). Used later to get data from db. self.joeid = 'user' + self.db.user.create(username='joe', @@ -163,7 +164,7 @@ class XmlrpcTest(object): # test a bogus action with self.assertRaises(Exception) as cm: self.server.action('bogus') - print cm.exception + print(cm.exception) self.assertEqual(cm.exception.message, 'action "bogus" is not supported ') @@ -206,14 +207,14 @@ class XmlrpcTest(object): self.db.security.addPermissionToRole('Project', 'Web Access') # Allow viewing keyword p = self.db.security.addPermission(name='View', klass='keyword') - print "View keyword class: %r"%p + print("View keyword class: %r"%p) self.db.security.addPermissionToRole('User', p) # Allow viewing interesting things (but not keyword) on issue # But users might only view issues where they are on nosy # (so in the real world the check method would be better) p = self.db.security.addPermission(name='View', klass='issue', properties=("title", "status"), check=lambda x,y,z: True) - print "View keyword class w/ props: %r"%p + print("View keyword class w/ props: %r"%p) self.db.security.addPermissionToRole('User', p) # Allow role "Project" access to whole issue p = self.db.security.addPermission(name='View', klass='issue') @@ -242,12 +243,12 @@ class XmlrpcTest(object): # this might check for keyword owner in the real world) p = self.db.security.addPermission(name='View', klass='issue', check=lambda x,y,z: False) - print "View issue class: %r"%p + print("View issue class: %r"%p) self.db.security.addPermissionToRole('User', p) # Allow user to search for issue.status p = self.db.security.addPermission(name='Search', klass='issue', properties=("status",)) - print "View Search class w/ props: %r"%p + print("View Search class w/ props: %r"%p) self.db.security.addPermissionToRole('User', p) keyw = {'keyword':self.db.keyword.lookup('d1')} diff --git a/test/tx_Source_detector.py b/test/tx_Source_detector.py index 90aa025..fa94ca3 100644 --- a/test/tx_Source_detector.py +++ b/test/tx_Source_detector.py @@ -14,6 +14,7 @@ # Note that the calls are interleaved, but the proper # tx_Source is associated with the same ticket. +from __future__ import print_function import time as time def tx_SourceCheckAudit(db, cl, nodeid, newvalues): @@ -31,7 +32,7 @@ def tx_SourceCheckAudit(db, cl, nodeid, newvalues): signature is used ''' if __debug__ and False: - print "\n tx_SourceCheckAudit(%s) db.tx_Source: %s"%(nodeid, db.tx_Source) + print("\n tx_SourceCheckAudit(%s) db.tx_Source: %s"%(nodeid, db.tx_Source)) newvalues['tx_Source'] = db.tx_Source @@ -57,7 +58,7 @@ def tx_SourceCheckReact(db, cl, nodeid, oldvalues): ''' if __debug__ and False: - print " tx_SourceCheckReact(%s) db.tx_Source: %s"%(nodeid, db.tx_Source) + print(" tx_SourceCheckReact(%s) db.tx_Source: %s"%(nodeid, db.tx_Source)) diff --git a/tools/load_tracker.py b/tools/load_tracker.py index ac9bbdc..97f9b69 100755 --- a/tools/load_tracker.py +++ b/tools/load_tracker.py @@ -5,13 +5,14 @@ Usage: %s Load up the indicated tracker with N issues and N/100 users. ''' +from __future__ import print_function import sys, os, random from roundup import instance # open the instance if len(sys.argv) < 2: - print "Error: Not enough arguments" - print __doc__.strip()%(sys.argv[0]) + print("Error: Not enough arguments") + print(__doc__.strip()%(sys.argv[0])) sys.exit(1) tracker_home = sys.argv[1] N = int(sys.argv[2]) @@ -58,7 +59,7 @@ try: # add some users M = N/100 for i in range(M): - print '\ruser', i, ' ', + print('\ruser', i, ' ', end=' ') sys.stdout.flush() if i/17 == 0: db.user.create(username=names[i%17]) @@ -68,11 +69,11 @@ try: # assignable user list users = db.user.list() users.remove(db.user.lookup('anonymous')) - print + print() # now create the issues for i in range(N): - print '\rissue', i, ' ', + print('\rissue', i, ' ', end=' ') sys.stdout.flush() # in practise, about 90% of issues are resolved if random.random() > .9: @@ -86,7 +87,7 @@ try: assignedto=random.choice(users)) if not i%1000: db.commit() - print + print() db.commit() finally: diff --git a/tools/migrate-queries.py b/tools/migrate-queries.py index 67f0352..3cfad27 100644 --- a/tools/migrate-queries.py +++ b/tools/migrate-queries.py @@ -7,13 +7,14 @@ removing the leading ? from their URLs. 0.6.0+ queries do not carry a leading ?; it is added by the 0.6.0 templating, so old queries lead to query URLs with a double leading ?? and a consequent 404 Not Found. ''' +from __future__ import print_function __author__ = 'James Kew ' import sys import roundup.instance if len(sys.argv) == 1: - print __doc__ + print(__doc__) sys.exit(1) # Iterate over all instance homes specified in argv. @@ -22,20 +23,20 @@ for home in sys.argv[1:]: try: instance = roundup.instance.open(home) except: - print 'Cannot open instance home directory %s!' % home + print('Cannot open instance home directory %s!' % home) continue db = instance.open('admin') db.tx_Source = "cli" - print 'Migrating active queries in %s (%s):'%( - instance.config.TRACKER_NAME, home) + print('Migrating active queries in %s (%s):'%( + instance.config.TRACKER_NAME, home)) for query in db.query.list(): url = db.query.get(query, 'url') if url[0] == '?': url = url[1:] - print ' Migrating query%s (%s)'%(query, - db.query.get(query, 'name')) + print(' Migrating query%s (%s)'%(query, + db.query.get(query, 'name'))) db.query.set(query, url=url) db.commit() diff --git a/tools/pygettext.py b/tools/pygettext.py index 0a079d3..0ca66f7 100644 --- a/tools/pygettext.py +++ b/tools/pygettext.py @@ -14,6 +14,7 @@ # # for selftesting +from __future__ import print_function try: import fintl _ = fintl.gettext @@ -197,9 +198,9 @@ msgstr "" def usage(code, msg=''): - print >> sys.stderr, __doc__ % globals() + print(__doc__ % globals(), file=sys.stderr) if msg: - print >> sys.stderr, msg + print(msg, file=sys.stderr) sys.exit(code) @@ -423,13 +424,13 @@ class TokenEater: elif ttype not in [tokenize.COMMENT, token.INDENT, token.DEDENT, token.NEWLINE, tokenize.NL]: # warn if we see anything else than STRING or whitespace - print >> sys.stderr, _( + print(_( '*** %(file)s:%(lineno)s: Seen unexpected token "%(token)s"' ) % { 'token': tstring, 'file': self.__curfile, 'lineno': self.__lineno - } + }, file=sys.stderr) self.__state = self.__waiting def __addentry(self, msg, lineno=None, isdocstring=0): @@ -448,7 +449,7 @@ class TokenEater: timestamp = time.strftime('%Y-%m-%d %H:%M+%Z') # The time stamp in the header doesn't have the same format as that # generated by xgettext... - print >> fp, pot_header % {'time': timestamp, 'version': __version__} + print(pot_header % {'time': timestamp, 'version': __version__}, file=fp) # Sort the entries. First sort each particular entry's keys, then # sort all the entries by their first item. reverse = {} @@ -479,8 +480,8 @@ class TokenEater: elif options.locationstyle == options.SOLARIS: for filename, lineno in v: d = {'filename': filename, 'lineno': lineno} - print >>fp, _( - '# File: %(filename)s, line: %(lineno)d') % d + print(_( + '# File: %(filename)s, line: %(lineno)d') % d, file=fp) elif options.locationstyle == options.GNU: # fit as many locations on one line, as long as the # resulting line length doesn't exceeds 'options.width' @@ -491,14 +492,14 @@ class TokenEater: if len(locline) + len(s) <= options.width: locline = locline + s else: - print >> fp, locline + print(locline, file=fp) locline = "#:" + s if len(locline) > 2: - print >> fp, locline + print(locline, file=fp) if isdocstring: - print >> fp, '#, docstring' - print >> fp, 'msgid', normalize(k) - print >> fp, 'msgstr ""\n' + print('#, docstring', file=fp) + print('msgid', normalize(k), file=fp) + print('msgstr ""\n', file=fp) @@ -572,7 +573,7 @@ def main(): elif opt in ('-v', '--verbose'): options.verbose = 1 elif opt in ('-V', '--version'): - print _('pygettext.py (xgettext for Python) %s') % __version__ + print(_('pygettext.py (xgettext for Python) %s') % __version__) sys.exit(0) elif opt in ('-w', '--width'): try: @@ -605,8 +606,8 @@ def main(): options.toexclude = fp.readlines() fp.close() except IOError: - print >> sys.stderr, _( - "Can't read --exclude-file: %s") % options.excludefilename + print(_( + "Can't read --exclude-file: %s") % options.excludefilename, file=sys.stderr) sys.exit(1) else: options.toexclude = [] @@ -625,12 +626,12 @@ def main(): for filename in args: if filename == '-': if options.verbose: - print _('Reading standard input') + print(_('Reading standard input')) fp = sys.stdin closep = 0 else: if options.verbose: - print _('Working on %s') % filename + print(_('Working on %s') % filename) fp = open(filename) closep = 1 try: @@ -638,8 +639,8 @@ def main(): try: tokenize.tokenize(fp.readline, eater) except tokenize.TokenError as e: - print >> sys.stderr, '%s: %s, line %d, column %d' % ( - e[0], filename, e[1][0], e[1][1]) + print('%s: %s, line %d, column %d' % ( + e[0], filename, e[1][0], e[1][1]), file=sys.stderr) finally: if closep: fp.close() -- 2.7.4