initial changes from 2to3-3.3 py33
authorrptlab
Tue, 30 Apr 2013 14:20:22 +0100
branchpy33
changeset 3721 0c93dd8ff567
parent 3720 7a059dde5bf5
child 3722 29c11b905751
initial changes from 2to3-3.3
demos/colors/colortest.py
demos/odyssey/dodyssey.py
demos/odyssey/fodyssey.py
demos/odyssey/odyssey.py
demos/rlzope/rlzope.py
demos/stdfonts/stdfonts.py
demos/tests/testdemos.py
docs/genAll.py
docs/reference/genreference.py
docs/source/conf.py
docs/userguide/ch2a_fonts.py
docs/userguide/ch5_paragraphs.py
docs/userguide/genuserguide.py
setup.py
src/reportlab/graphics/barcode/__init__.py
src/reportlab/graphics/barcode/code128.py
src/reportlab/graphics/barcode/code39.py
src/reportlab/graphics/barcode/code93.py
src/reportlab/graphics/barcode/common.py
src/reportlab/graphics/barcode/eanbc.py
src/reportlab/graphics/barcode/fourstate.py
src/reportlab/graphics/barcode/lto.py
src/reportlab/graphics/barcode/qr.py
src/reportlab/graphics/barcode/test.py
src/reportlab/graphics/barcode/usps.py
src/reportlab/graphics/barcode/usps4s.py
src/reportlab/graphics/charts/axes.py
src/reportlab/graphics/charts/barcharts.py
src/reportlab/graphics/charts/doughnut.py
src/reportlab/graphics/charts/legends.py
src/reportlab/graphics/charts/linecharts.py
src/reportlab/graphics/charts/lineplots.py
src/reportlab/graphics/charts/piecharts.py
src/reportlab/graphics/charts/spider.py
src/reportlab/graphics/charts/textlabels.py
src/reportlab/graphics/charts/utils.py
src/reportlab/graphics/charts/utils3d.py
src/reportlab/graphics/renderPDF.py
src/reportlab/graphics/renderPM.py
src/reportlab/graphics/renderPS.py
src/reportlab/graphics/renderSVG.py
src/reportlab/graphics/renderbase.py
src/reportlab/graphics/samples/bubble.py
src/reportlab/graphics/samples/clustered_bar.py
src/reportlab/graphics/samples/clustered_column.py
src/reportlab/graphics/samples/exploded_pie.py
src/reportlab/graphics/samples/filled_radar.py
src/reportlab/graphics/samples/line_chart.py
src/reportlab/graphics/samples/linechart_with_markers.py
src/reportlab/graphics/samples/radar.py
src/reportlab/graphics/samples/runall.py
src/reportlab/graphics/samples/scatter.py
src/reportlab/graphics/samples/scatter_lines.py
src/reportlab/graphics/samples/scatter_lines_markers.py
src/reportlab/graphics/samples/simple_pie.py
src/reportlab/graphics/samples/stacked_bar.py
src/reportlab/graphics/samples/stacked_column.py
src/reportlab/graphics/shapes.py
src/reportlab/graphics/testdrawings.py
src/reportlab/graphics/testshapes.py
src/reportlab/graphics/widgetbase.py
src/reportlab/graphics/widgets/eventcal.py
src/reportlab/graphics/widgets/flags.py
src/reportlab/graphics/widgets/grids.py
src/reportlab/graphics/widgets/markers.py
src/reportlab/graphics/widgets/signsandsymbols.py
src/reportlab/graphics/widgets/table.py
src/reportlab/lib/PyFontify.py
src/reportlab/lib/abag.py
src/reportlab/lib/arciv.py
src/reportlab/lib/attrmap.py
src/reportlab/lib/codecharts.py
src/reportlab/lib/colors.py
src/reportlab/lib/corp.py
src/reportlab/lib/extformat.py
src/reportlab/lib/fontfinder.py
src/reportlab/lib/fonts.py
src/reportlab/lib/formatters.py
src/reportlab/lib/normalDate.py
src/reportlab/lib/pdfencrypt.py
src/reportlab/lib/pygments2xpre.py
src/reportlab/lib/randomtext.py
src/reportlab/lib/rparsexml.py
src/reportlab/lib/sequencer.py
src/reportlab/lib/set_ops.py
src/reportlab/lib/styles.py
src/reportlab/lib/testutils.py
src/reportlab/lib/textsplit.py
src/reportlab/lib/units.py
src/reportlab/lib/utils.py
src/reportlab/lib/validators.py
src/reportlab/lib/xmllib.py
src/reportlab/lib/yaml.py
src/reportlab/pdfbase/_can_cmap_data.py
src/reportlab/pdfbase/_cidfontdata.py
src/reportlab/pdfbase/_fontdata.py
src/reportlab/pdfbase/cidfonts.py
src/reportlab/pdfbase/pdfdoc.py
src/reportlab/pdfbase/pdfform.py
src/reportlab/pdfbase/pdfmetrics.py
src/reportlab/pdfbase/pdfpattern.py
src/reportlab/pdfbase/pdfutils.py
src/reportlab/pdfbase/rl_codecs.py
src/reportlab/pdfbase/ttfonts.py
src/reportlab/pdfgen/canvas.py
src/reportlab/pdfgen/pdfimages.py
src/reportlab/pdfgen/pycanvas.py
src/reportlab/pdfgen/textobject.py
src/reportlab/platypus/__init__.py
src/reportlab/platypus/doctemplate.py
src/reportlab/platypus/flowables.py
src/reportlab/platypus/frames.py
src/reportlab/platypus/para.py
src/reportlab/platypus/paragraph.py
src/reportlab/platypus/paraparser.py
src/reportlab/platypus/tableofcontents.py
src/reportlab/platypus/tables.py
src/reportlab/platypus/xpreformatted.py
src/rl_addons/renderPM/pfm.py
src/rl_addons/renderPM/setup.py
src/rl_addons/renderPM/test_renderPM.py
src/rl_addons/renderPM/tr.py
src/rl_addons/rl_accel/tests/t0.py
src/rl_addons/rl_accel/tests/t1.py
src/rl_addons/rl_accel/tests/t2.py
src/rl_addons/rl_accel/tests/t3.py
src/rl_addons/rl_accel/tests/t4.py
src/rl_addons/rl_accel/tests/t5.py
tests/runAll.py
tests/test_crypto_algorithms.py
tests/test_docs_build.py
tests/test_docstrings.py
tests/test_encrypt.py
tests/test_extra.py
tests/test_graphics_charts.py
tests/test_graphics_layout.py
tests/test_hello.py
tests/test_invariant.py
tests/test_lib_colors.py
tests/test_lib_sequencer.py
tests/test_lib_validators.py
tests/test_multibyte_chs.py
tests/test_multibyte_cht.py
tests/test_multibyte_jpn.py
tests/test_multibyte_kor.py
tests/test_paragraphs.py
tests/test_pdfbase_encodings.py
tests/test_pdfbase_pdfdoc.py
tests/test_pdfbase_pdfmetrics.py
tests/test_pdfbase_pdfutils.py
tests/test_pdfbase_postscript.py
tests/test_pdfbase_ttfonts.py
tests/test_pdfgen_general.py
tests/test_pdfgen_links.py
tests/test_pdfgen_pycanvas.py
tests/test_platypus_accum.py
tests/test_platypus_breaking.py
tests/test_platypus_cjk_wrap.py
tests/test_platypus_general.py
tests/test_platypus_lists.py
tests/test_platypus_paragraphs.py
tests/test_platypus_paraparser.py
tests/test_platypus_programming.py
tests/test_platypus_tables.py
tests/test_platypus_toc.py
tests/test_pyfiles.py
tests/test_renderSVG.py
tests/test_rl_accel.py
tests/test_source_chars.py
tests/test_table_layout.py
tests/test_widgets_grids.py
tools/docco/codegrab.py
tools/docco/docpy.py
tools/docco/examples.py
tools/docco/graphdocpy.py
tools/docco/rl_doc_utils.py
tools/docco/t_parse.py
tools/docco/yaml.py
tools/docco/yaml2pdf.py
tools/pythonpoint/demos/examples.py
tools/pythonpoint/pythonpoint.py
tools/pythonpoint/stdparser.py
tools/utils/add_bleed.py
tools/utils/dumpttf.py
--- a/demos/colors/colortest.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/demos/colors/colortest.py	Tue Apr 30 14:20:22 2013 +0100
@@ -64,7 +64,7 @@
     #do all named colors
     framePage(c, 'Color Demo - RGB Space - page %d' % c.getPageNumber())
 
-    all_colors = reportlab.lib.colors.getAllNamedColors().items()
+    all_colors = list(reportlab.lib.colors.getAllNamedColors().items())
     all_colors.sort() # alpha order by name
     c.setFont('Times-Roman', 12)
     c.drawString(72,730, 'This shows all the named colors in the HTML standard.')
--- a/demos/odyssey/dodyssey.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/demos/odyssey/dodyssey.py	Tue Apr 30 14:20:22 2013 +0100
@@ -74,7 +74,7 @@
 
 chNum = 0
 def myOnDrawCB(canv,kind,label):
-    print 'myOnDrawCB(%s)'%kind, 'Page number=', canv.getPageNumber(), 'label value=', label
+    print('myOnDrawCB(%s)'%kind, 'Page number=', canv.getPageNumber(), 'label value=', label)
 
 def chapter(txt, style=ChapterStyle):
     global chNum
@@ -113,7 +113,7 @@
     if _REDCAP:
         fs, fe = '<font color="red" size="+2">', '</font>'
         n = len(txt)
-        for i in xrange(n):
+        for i in range(n):
             if 'a'<=txt[i]<='z' or 'A'<=txt[i]<='Z':
                 txt = (txt[:i]+(fs+txt[i]+fe))+txt[i+1:]
                 break
@@ -125,7 +125,7 @@
         if _REDCAP==3 and n>20:
             n = len(txt)
             fs = '<font color="green" size="+1">'
-            for i in xrange(n-1,-1,-1):
+            for i in range(n-1,-1,-1):
                 if 'a'<=txt[i]<='z' or 'A'<=txt[i]<='Z':
                     txt = txt[:i]+((fs+txt[i]+fe)+txt[i+1:])
                     break
@@ -152,9 +152,9 @@
     i0 = text.index('Book I')
     endMarker = 'covenant of peace between the two contending parties.'
     i1 = text.index(endMarker)+len(endMarker)
-    PREAMBLE=map(str.strip,text[0:i0].split('\n'))
-    L=map(str.strip,text[i0:i1].split('\n'))
-    POSTAMBLE=map(str.strip,text[i1:].split('\n'))
+    PREAMBLE=list(map(str.strip,text[0:i0].split('\n')))
+    L=list(map(str.strip,text[i0:i1].split('\n')))
+    POSTAMBLE=list(map(str.strip,text[i1:].split('\n')))
 
     def ambleText(L):
         while L and not L[0]: L.pop(0)
@@ -184,7 +184,7 @@
             yield B,T,P
 
     t1 = time()
-    print "open(%s,'r').read() took %.4f seconds" %(fn,t1-t0)
+    print("open(%s,'r').read() took %.4f seconds" %(fn,t1-t0))
 
     E.append([spacer,2])
     E.append([fTitle,'<font color="red">%s</font>' % Title, InitialStyle])
@@ -203,24 +203,24 @@
         E.append([p,'\n'.join(T)])
 
     t3 = time()
-    print "Parsing into memory took %.4f seconds" %(t3-t1)
+    print("Parsing into memory took %.4f seconds" %(t3-t1))
     del L
     t4 = time()
-    print "Deleting list of lines took %.4f seconds" %(t4-t3)
-    for i in xrange(len(E)):
+    print("Deleting list of lines took %.4f seconds" %(t4-t3))
+    for i in range(len(E)):
         E[i][0](*E[i][1:])
     t5 = time()
-    print "Moving into platypus took %.4f seconds" %(t5-t4)
+    print("Moving into platypus took %.4f seconds" %(t5-t4))
     del E
     t6 = time()
-    print "Deleting list of actions took %.4f seconds" %(t6-t5)
+    print("Deleting list of actions took %.4f seconds" %(t6-t5))
     go()
     t7 = time()
-    print "saving to PDF took %.4f seconds" %(t7-t6)
-    print "Total run took %.4f seconds"%(t7-t0)
+    print("saving to PDF took %.4f seconds" %(t7-t6))
+    print("Total run took %.4f seconds"%(t7-t0))
 
     import md5
-    print 'file digest: %s' % md5.md5(open('dodyssey.pdf','rb').read()).hexdigest()
+    print('file digest: %s' % md5.md5(open('dodyssey.pdf','rb').read()).hexdigest())
 
 def run():
     for fn in ('odyssey.full.txt','odyssey.txt'):
--- a/demos/odyssey/fodyssey.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/demos/odyssey/fodyssey.py	Tue Apr 30 14:20:22 2013 +0100
@@ -86,9 +86,9 @@
     i0 = text.index('Book I')
     endMarker = 'covenant of peace between the two contending parties.'
     i1 = text.index(endMarker)+len(endMarker)
-    PREAMBLE=map(str.strip,text[0:i0].split('\n'))
-    L=map(str.strip,text[i0:i1].split('\n'))
-    POSTAMBLE=map(str.strip,text[i1:].split('\n'))
+    PREAMBLE=list(map(str.strip,text[0:i0].split('\n')))
+    L=list(map(str.strip,text[i0:i1].split('\n')))
+    POSTAMBLE=list(map(str.strip,text[i1:].split('\n')))
 
     def ambleText(L):
         while L and not L[0]: L.pop(0)
@@ -118,7 +118,7 @@
             yield B,T,P
 
     t1 = time()
-    print "open(%s,'r').read() took %.4f seconds" %(fn,t1-t0)
+    print("open(%s,'r').read() took %.4f seconds" %(fn,t1-t0))
 
     E.append([spacer,2])
     E.append([fTitle,'<font color=red>%s</font>' % Title, InitialStyle])
@@ -137,21 +137,21 @@
         E.append([p,'\n'.join(T)])
 
     t3 = time()
-    print "Parsing into memory took %.4f seconds" %(t3-t1)
+    print("Parsing into memory took %.4f seconds" %(t3-t1))
     del L
     t4 = time()
-    print "Deleting list of lines took %.4f seconds" %(t4-t3)
-    for i in xrange(len(E)):
+    print("Deleting list of lines took %.4f seconds" %(t4-t3))
+    for i in range(len(E)):
         E[i][0](*E[i][1:])
     t5 = time()
-    print "Moving into platypus took %.4f seconds" %(t5-t4)
+    print("Moving into platypus took %.4f seconds" %(t5-t4))
     del E
     t6 = time()
-    print "Deleting list of actions took %.4f seconds" %(t6-t5)
+    print("Deleting list of actions took %.4f seconds" %(t6-t5))
     go()
     t7 = time()
-    print "saving to PDF took %.4f seconds" %(t7-t6)
-    print "Total run took %.4f seconds"%(t7-t0)
+    print("saving to PDF took %.4f seconds" %(t7-t6))
+    print("Total run took %.4f seconds"%(t7-t0))
 
 for fn in ('odyssey.full.txt','odyssey.txt'):
     if os.path.isfile(fn):
--- a/demos/odyssey/odyssey.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/demos/odyssey/odyssey.py	Tue Apr 30 14:20:22 2013 +0100
@@ -67,7 +67,7 @@
         accelStr = 'with _rl_accel'
     else:
         accelStr = 'without _rl_accel'
-    print 'Benchmark of %s %s %s' % (impl, verStr, accelStr)
+    print('Benchmark of %s %s %s' % (impl, verStr, accelStr))
 
     started = time.time()
     canv = canvas.Canvas('odyssey.pdf', invariant=1)
@@ -119,7 +119,7 @@
             #page
             pg = canv.getPageNumber()
             if verbose and pg % 10 == 0:
-                print 'formatted page %d' % canv.getPageNumber()
+                print('formatted page %d' % canv.getPageNumber())
 
     if tx:
         canv.drawText(tx)
@@ -127,7 +127,7 @@
         drawPageFrame(canv)
 
     if verbose:
-        print 'about to write to disk...'
+        print('about to write to disk...')
 
     canv.save()
 
@@ -136,10 +136,10 @@
     pages = canv.getPageNumber()-1
     speed =  pages / elapsed
     fileSize = os.stat('odyssey.pdf')[6] / 1024
-    print '%d pages in %0.2f seconds = %0.2f pages per second, file size %d kb' % (
-                pages, elapsed, speed, fileSize)
+    print('%d pages in %0.2f seconds = %0.2f pages per second, file size %d kb' % (
+                pages, elapsed, speed, fileSize))
     import md5
-    print 'file digest: %s' % md5.md5(open('odyssey.pdf','rb').read()).hexdigest()
+    print('file digest: %s' % md5.md5(open('odyssey.pdf','rb').read()).hexdigest())
 
 if __name__=='__main__':
     quiet = ('-q' in sys.argv)
--- a/demos/rlzope/rlzope.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/demos/rlzope/rlzope.py	Tue Apr 30 14:20:22 2013 +0100
@@ -12,7 +12,7 @@
 #
 #
 
-import string, cStringIO
+import string, io
 try :
     from Shared.reportlab.platypus.paragraph import Paragraph
     from Shared.reportlab.platypus.doctemplate import *
@@ -55,7 +55,7 @@
                 return None
 
             # Convert it to PIL
-            image = ImageReader(cStringIO.StringIO(str(logo.data)))
+            image = ImageReader(io.StringIO(str(logo.data)))
             (width, height) = image.getSize()
 
             # scale it to be 0.75 inch high
@@ -84,7 +84,7 @@
 
         # we will build an in-memory document
         # instead of creating an on-disk file.
-        self.report = cStringIO.StringIO()
+        self.report = io.StringIO()
 
         # initialise a PDF document using ReportLab's platypus
         self.document = BaseDocTemplate(self.report)
@@ -158,7 +158,7 @@
         self.REQUEST.RESPONSE.setHeader('Content-Disposition', 'attachment; filename=%s' % filename)
     except:
         import traceback, sys, cgi
-        content = sys.stdout = sys.stderr = cStringIO.StringIO()
+        content = sys.stdout = sys.stderr = io.StringIO()
         self.REQUEST.RESPONSE.setHeader('Content-Type', 'text/html')
         traceback.print_exc()
         sys.stdout = sys.__stdout__
--- a/demos/stdfonts/stdfonts.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/demos/stdfonts/stdfonts.py	Tue Apr 30 14:20:22 2013 +0100
@@ -64,10 +64,10 @@
     if len(sys.argv)==2:
         mode = string.lower(sys.argv[1])
         if mode not in ['dec','oct','hex']:
-            print __doc__
+            print(__doc__)
 
     elif len(sys.argv) == 1:
         mode = 'dec'
         run(mode)
     else:
-        print __doc__
+        print(__doc__)
--- a/demos/tests/testdemos.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/demos/tests/testdemos.py	Tue Apr 30 14:20:22 2013 +0100
@@ -10,4 +10,4 @@
 for p in ('pythonpoint/pythonpoint.py','stdfonts/stdfonts.py','odyssey/odyssey.py', 'gadflypaper/gfe.py'):
     fn = os.path.normcase(os.path.normpath(os.path.join(os.path.dirname(pdfgen.__file__),'..','demos',p)))
     os.chdir(os.path.dirname(fn))
-    execfile(fn,_globals.copy())
+    exec(compile(open(fn).read(), fn, 'exec'),_globals.copy())
--- a/docs/genAll.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/docs/genAll.py	Tue Apr 30 14:20:22 2013 +0100
@@ -27,7 +27,7 @@
                 if verbose: traceback.print_exc()
         else:
             cmd = '"%s" %s %s' % (sys.executable,os.path.basename(p), not verbose and '-s' or '')
-            if verbose: print cmd
+            if verbose: print(cmd)
             os.system(cmd)
 
 """Runs the manual-building scripts"""
--- a/docs/reference/genreference.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/docs/reference/genreference.py	Tue Apr 30 14:20:22 2013 +0100
@@ -15,11 +15,11 @@
     sys.path.insert(0,topDir)
     from tools.docco import yaml2pdf
     yaml2pdf.run('reference.yml','reportlab-reference.pdf')
-    if verbose: print 'Saved reportlab-reference.pdf'
+    if verbose: print('Saved reportlab-reference.pdf')
     if not outDir: outDir = os.path.join(topDir,'docs')
     destfn = os.path.join(outDir,'reportlab-reference.pdf')
     shutil.copyfile('reportlab-reference.pdf', destfn)
-    if verbose: print 'copied to %s' % destfn
+    if verbose: print('copied to %s' % destfn)
 
 def makeSuite():
     "standard test harness support - run self as separate process"
--- a/docs/source/conf.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/docs/source/conf.py	Tue Apr 30 14:20:22 2013 +0100
@@ -37,8 +37,8 @@
 master_doc = 'index'
 
 # General information about the project.
-project = u'reportlab'
-copyright = u'2010, Robinson, Becker, Watters and many more'
+project = 'reportlab'
+copyright = '2010, Robinson, Becker, Watters and many more'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -172,8 +172,8 @@
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-  ('index', 'reportlab.tex', u'reportlab Documentation',
-   u'Robinson, Becker, Watters and many more', 'manual'),
+  ('index', 'reportlab.tex', 'reportlab Documentation',
+   'Robinson, Becker, Watters and many more', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
--- a/docs/userguide/ch2a_fonts.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/docs/userguide/ch2a_fonts.py	Tue Apr 30 14:20:22 2013 +0100
@@ -49,7 +49,7 @@
 
 
 
-disc(u"""
+disc("""
 If your data is not encoded as UTF8, you will get a UnicodeDecodeError as
 soon as you feed in a non-ASCII character.  For example, this snippet below is
 attempting to read in and print a series of names, including one with a French
@@ -57,7 +57,7 @@
 what character it doesn't like:
 """)
 
-eg(u"""
+eg("""
 >>> from reportlab.pdfgen.canvas import Canvas
 >>> c = Canvas('temp.pdf')
 >>> y = 700
--- a/docs/userguide/ch5_paragraphs.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/docs/userguide/ch5_paragraphs.py	Tue Apr 30 14:20:22 2013 +0100
@@ -188,14 +188,14 @@
 def getAttrs(A):
     _addAttributeNames(A)
     S={}
-    for k, v in A.items():
+    for k, v in list(A.items()):
         a = v[0]
         if a not in S:
             S[a] = k
         else:
             S[a] = "%s, %s" %(S[a],k)
 
-    K = S.keys()
+    K = list(S.keys())
     K.sort()
     D=[('Attribute','Synonyms')]
     for k in K:
--- a/docs/userguide/genuserguide.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/docs/userguide/genuserguide.py	Tue Apr 30 14:20:22 2013 +0100
@@ -26,7 +26,7 @@
     registerFontFamily('Vera',normal='Vera',bold='VeraBd',italic='VeraIt',boldItalic='VeraBI')
     from tools.docco.rl_doc_utils import setStory, getStory, RLDocTemplate, defaultPageSize, H1, H2, H3, H4
     from tools.docco import rl_doc_utils
-    exec 'from tools.docco.rl_doc_utils import *' in G, G
+    exec('from tools.docco.rl_doc_utils import *', G, G)
     destfn = os.path.join(outDir,'reportlab-userguide.pdf')
     doc = RLDocTemplate(destfn,pagesize = pagesize or defaultPageSize)
 
@@ -50,13 +50,13 @@
         'graph_widgets',
         'app_demos',
         ):
-        exec open_and_read(f+'.py',mode='t') in G, G
+        exec(open_and_read(f+'.py',mode='t'), G, G)
     del G
 
     story = getStory()
-    if verbose: print 'Built story contains %d flowables...' % len(story)
+    if verbose: print('Built story contains %d flowables...' % len(story))
     doc.multiBuild(story)
-    if verbose: print 'Saved "%s"' % destfn
+    if verbose: print('Saved "%s"' % destfn)
 
 def makeSuite():
     "standard test harness support - run self as separate process"
@@ -65,7 +65,7 @@
 
 def main():
     import sys
-    outDir = filter(lambda x: x[:9]=='--outdir=',sys.argv)
+    outDir = [x for x in sys.argv if x[:9]=='--outdir=']
     if outDir:
         outDir = outDir[0]
         sys.argv.remove(outDir)
@@ -83,10 +83,10 @@
         try:
             pagesize = (w,h) = eval(sys.argv[1])
         except:
-            print 'Expected page size in argument 1', sys.argv[1]
+            print('Expected page size in argument 1', sys.argv[1])
             raise
         if verbose:
-            print 'set page size to',sys.argv[1]
+            print('set page size to',sys.argv[1])
     else:
         pagesize = None
     if timing:
@@ -94,7 +94,7 @@
         t0 = time()
         run(pagesize, verbose,outDir)
         if verbose:
-            print 'Generation of userguide took %.2f seconds' % (time()-t0)
+            print('Generation of userguide took %.2f seconds' % (time()-t0))
     elif prof:
         import profile
         profile.run('run(pagesize,verbose,outDir)','genuserguide.stats')
--- a/setup.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/setup.py	Tue Apr 30 14:20:22 2013 +0100
@@ -1,7 +1,7 @@
 #Copyright ReportLab Europe Ltd. 2000-2012
 #see license.txt for license details
 __version__=''' $Id$ '''
-import os, sys, glob, ConfigParser, shutil
+import os, sys, glob, configparser, shutil
 platform = sys.platform
 pjoin = os.path.join
 abspath = os.path.abspath
@@ -19,7 +19,7 @@
 try:
     os.chdir(pkgDir)
 except:
-    print '!!!!! warning could not change directory to %r' % pkgDir
+    print('!!!!! warning could not change directory to %r' % pkgDir)
 daily=os.environ.get('RL_EXE_DAILY','')
 
 import distutils
@@ -50,7 +50,7 @@
     try:
         for l in open(pjoin(FN+'.py'),'r').readlines():
             if l.startswith('Version'):
-                exec l.strip()
+                exec(l.strip())
                 return Version
     except:
         pass
@@ -70,7 +70,7 @@
 class config:
     def __init__(self):
         try:
-            self.parser = ConfigParser.RawConfigParser()
+            self.parser = configparser.RawConfigParser()
             self.parser.read(pjoin(pkgDir,'setup.cfg'))
         except:
             self.parser = None
@@ -162,7 +162,7 @@
         if isfile(fn):
             _.append(x)
     if _:
-        _ = filter(_rl_dir_info(cn),_)
+        _ = list(filter(_rl_dir_info(cn),_))
         if len(_):
             _.sort(_cmp_rl_ccode_dirs)
             return abspath(_[0])
@@ -181,7 +181,7 @@
 
 INFOLINES=[]
 def infoline(t):
-    print t
+    print(t)
     INFOLINES.append(t)
 
 reportlab_files= [
@@ -216,7 +216,7 @@
         ]
 
 def get_fonts(PACKAGE_DIR, reportlab_files):
-    import sys, os, os.path, urllib2, zipfile, StringIO
+    import sys, os, os.path, urllib.request, urllib.error, urllib.parse, zipfile, io
     rl_dir = PACKAGE_DIR['reportlab']
     if not [x for x in reportlab_files if not os.path.isfile(pjoin(rl_dir,x))]:
         infoline("Standard T1 font curves already downloaded")
@@ -224,8 +224,8 @@
     try:
         infoline("Downloading standard T1 font curves")
 
-        remotehandle = urllib2.urlopen("http://www.reportlab.com/ftp/pfbfer-20070710.zip")
-        zipdata = StringIO.StringIO(remotehandle.read())
+        remotehandle = urllib.request.urlopen("http://www.reportlab.com/ftp/pfbfer-20070710.zip")
+        zipdata = io.StringIO(remotehandle.read())
         remotehandle.close()
         archive = zipfile.ZipFile(zipdata)
         dst = pjoin(rl_dir, 'fonts')
@@ -415,7 +415,7 @@
 
     #copy some special case files into place so package_data will treat them properly
     PACKAGE_DIR = {'reportlab': pjoin('src','reportlab')}
-    for fn,dst in SPECIAL_PACKAGE_DATA.iteritems():
+    for fn,dst in SPECIAL_PACKAGE_DATA.items():
         shutil.copyfile(fn,pjoin(PACKAGE_DIR['reportlab'],dst))
         reportlab_files.append(dst)
     get_fonts(PACKAGE_DIR, reportlab_files)
@@ -450,11 +450,11 @@
             package_data = {'reportlab': reportlab_files},
             ext_modules =   EXT_MODULES,
             )
-        print
-        print '########## SUMMARY INFO #########'
-        print '\n'.join(INFOLINES)
+        print()
+        print('########## SUMMARY INFO #########')
+        print('\n'.join(INFOLINES))
     finally:
-        for dst in SPECIAL_PACKAGE_DATA.itervalues():
+        for dst in SPECIAL_PACKAGE_DATA.values():
             os.remove(pjoin(PACKAGE_DIR['reportlab'],dst))
             reportlab_files.remove(dst)
 
--- a/src/reportlab/graphics/barcode/__init__.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/__init__.py	Tue Apr 30 14:20:22 2013 +0100
@@ -36,14 +36,14 @@
 def getCodes():
     """Returns a dict mapping code names to widgets"""
 
-    from widgets import BarcodeI2of5, BarcodeCode128, BarcodeStandard93,\
+    from .widgets import BarcodeI2of5, BarcodeCode128, BarcodeStandard93,\
                         BarcodeExtended93, BarcodeStandard39, BarcodeExtended39,\
                         BarcodeMSI, BarcodeCodabar, BarcodeCode11, BarcodeFIM,\
                         BarcodePOSTNET, BarcodeUSPS_4State
 
     #newer codes will typically get their own module
-    from eanbc import Ean13BarcodeWidget, Ean8BarcodeWidget, UPCA
-    from qr import QrCodeWidget
+    from .eanbc import Ean13BarcodeWidget, Ean8BarcodeWidget, UPCA
+    from .qr import QrCodeWidget
 
 
     #the module exports a dictionary of names to widgets, to make it easy for
@@ -87,7 +87,7 @@
     height = options.pop('height',None)
     isoScale = options.pop('isoScale',0)
     kw = {}
-    for k,v in options.iteritems():
+    for k,v in options.items():
         if k.startswith('_') or k in bcc._attrMap: kw[k] = v
     bc = bcc(**kw)
 
--- a/src/reportlab/graphics/barcode/code128.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/code128.py	Tue Apr 30 14:20:22 2013 +0100
@@ -31,7 +31,7 @@
 #
 
 from reportlab.lib.units import inch
-from common import MultiWidthBarcode
+from .common import MultiWidthBarcode
 from string import digits
 
 _patterns = {
@@ -166,7 +166,7 @@
     'START_B' : (startb, setb, seta),
     'START_C' : (startc, setc, None),
 }
-tos = setmap.keys()
+tos = list(setmap.keys())
 
 class Code128(MultiWidthBarcode):
     """
@@ -223,7 +223,7 @@
         if type(value) is type(1):
             value = str(value)
             
-        for (k, v) in args.items():
+        for (k, v) in list(args.items()):
             setattr(self, k, v)
 
         if self.quiet:
--- a/src/reportlab/graphics/barcode/code39.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/code39.py	Tue Apr 30 14:20:22 2013 +0100
@@ -31,7 +31,7 @@
 #
 
 from reportlab.lib.units import inch
-from common import Barcode
+from .common import Barcode
 import string
 
 _patterns = {
@@ -112,7 +112,7 @@
     bearers = 0.0
     stop = 1
     def __init__(self, value = "", **args):
-        for k, v in args.iteritems():
+        for k, v in args.items():
             setattr(self, k, v)
 
         if self.quiet:
--- a/src/reportlab/graphics/barcode/code93.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/code93.py	Tue Apr 30 14:20:22 2013 +0100
@@ -31,7 +31,7 @@
 #
 
 from reportlab.lib.units import inch
-from common import MultiWidthBarcode
+from .common import MultiWidthBarcode
 import string
 
 _patterns = {
@@ -55,7 +55,7 @@
 }
 
 _charsbyval = {}
-for k, v in _patterns.items():
+for k, v in list(_patterns.items()):
     _charsbyval[v[1]] = k
 
 _extended = {
@@ -85,7 +85,7 @@
 }
 
 def _encode93(str):
-    s = map(None, str)
+    s = list(str)
     s.reverse()
 
     # compute 'C' checksum
@@ -122,7 +122,7 @@
         if type(value) is type(1):
             value = str(value)
             
-        for (k, v) in args.iteritems():
+        for (k, v) in args.items():
             setattr(self, k, v)
 
         if self.quiet:
--- a/src/reportlab/graphics/barcode/common.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/common.py	Tue Apr 30 14:20:22 2013 +0100
@@ -60,7 +60,7 @@
         self.computeSize()
 
     def _setKeywords(self,**kwd):
-        for (k, v) in kwd.iteritems():
+        for (k, v) in kwd.items():
             setattr(self, k, v)
 
     def validate(self):
@@ -308,7 +308,7 @@
         if type(value) == type(1):
             value = str(value)
 
-        for (k, v) in args.items():
+        for (k, v) in list(args.items()):
             setattr(self, k, v)
 
         if self.quiet:
@@ -342,7 +342,7 @@
             c += 1
 
         if cs:
-            c = 3*sum([int(s[i]) for i in xrange(0,c,2)])+sum([int(s[i]) for i in xrange(1,c,2)])
+            c = 3*sum([int(s[i]) for i in range(0,c,2)])+sum([int(s[i]) for i in range(1,c,2)])
             s += str((10 - c) % 10)
 
         self.encoded = s
@@ -351,7 +351,7 @@
         dval = self.stop and [self.patterns['start']] or []
         a = dval.append
 
-        for i in xrange(0, len(self.encoded), 2):
+        for i in range(0, len(self.encoded), 2):
             b = self.patterns['B' + self.encoded[i]]
             s = self.patterns['S' + self.encoded[i+1]]
 
@@ -433,7 +433,7 @@
         if type(value) == type(1):
             value = str(value)
 
-        for (k, v) in args.items():
+        for (k, v) in list(args.items()):
             setattr(self, k, v)
 
         if self.quiet:
@@ -569,7 +569,7 @@
         if type(value) == type(1):
             value = str(value)
 
-        for (k, v) in args.items():
+        for (k, v) in list(args.items()):
             setattr(self, k, v)
 
         if self.quiet:
@@ -689,7 +689,7 @@
         if type(value) == type(1):
             value = str(value)
 
-        for (k, v) in args.items():
+        for (k, v) in list(args.items()):
             setattr(self, k, v)
 
         if self.quiet:
@@ -705,7 +705,7 @@
         vval = ""
         self.valid = 1
         s = string.strip(self.value)
-        for i in xrange(0, len(s)):
+        for i in range(0, len(s)):
             c = s[i]
             if c not in self.chars:
                 self.Valid = 0
--- a/src/reportlab/graphics/barcode/eanbc.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/eanbc.py	Tue Apr 30 14:20:22 2013 +0100
@@ -187,7 +187,7 @@
     y = 0
     def __init__(self,value='123456789012',**kw):
         self.value=max(self._digits-len(value),0)*'0'+value[:self._digits]
-        for k, v in kw.iteritems():
+        for k, v in kw.items():
             setattr(self, k, v)
 
     width = property(lambda self: self.barWidth*(self._nbars-18+self._calc_quiet(self.lquiet)+self._calc_quiet(self.rquiet)))
--- a/src/reportlab/graphics/barcode/fourstate.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/fourstate.py	Tue Apr 30 14:20:22 2013 +0100
@@ -31,7 +31,7 @@
 #
 
 from reportlab.lib.units import inch
-from common import Barcode
+from .common import Barcode
 import string
 
 # . 3 T Tracker
--- a/src/reportlab/graphics/barcode/lto.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/lto.py	Tue Apr 30 14:20:22 2013 +0100
@@ -3,7 +3,7 @@
 
 import string
 
-from code39 import Standard39
+from .code39 import Standard39
 from reportlab.lib import colors
 from reportlab.lib.units import cm
 
@@ -45,15 +45,15 @@
         self.border = border
         if (len(subtype) != 1) \
             or (subtype not in string.ascii_uppercase + string.digits) :
-            raise ValueError, "Invalid subtype '%s'" % subtype
+            raise ValueError("Invalid subtype '%s'" % subtype)
         if ((not number) and (len(prefix) > 6)) \
            or not prefix.isalnum() :
-            raise ValueError, "Invalid prefix '%s'" % prefix
+            raise ValueError("Invalid prefix '%s'" % prefix)
         label = "%sL%s" % ((prefix + str(number or 0).zfill(6 - len(prefix)))[:6],
                            subtype)
         if len(label) != 8 :
-            raise ValueError, "Invalid set of parameters (%s, %s, %s)" \
-                                % (prefix, number, subtype)
+            raise ValueError("Invalid set of parameters (%s, %s, %s)" \
+                                % (prefix, number, subtype))
         self.label = label
         Standard39.__init__(self,
                             label,
--- a/src/reportlab/graphics/barcode/qr.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/qr.py	Tue Apr 30 14:20:22 2013 +0100
@@ -63,7 +63,7 @@
 
     def __init__(self,value='Hello World',**kw):
         self.value=value
-        for k, v in kw.iteritems():
+        for k, v in kw.items():
             setattr(self, k, v)
 
     def wrap(self,aW,aH):
@@ -101,8 +101,8 @@
         offsetX = (barWidth - min(barWidth, barHeight)) / 2
         offsetY = (min(barWidth, barHeight) - barHeight) / 2
 
-        for r in xrange(moduleCount):
-            for c in xrange(moduleCount):
+        for r in range(moduleCount):
+            for c in range(moduleCount):
                 if (qr.isDark(r, c) ):
                     x = (c + barBorder) * boxsize
                     y = (r + barBorder+1) * boxsize
@@ -209,13 +209,13 @@
         if self.typeNumber is None:
             # Calculate typeNumber for data to fit the QR Code capacity
             errorCorrectLevel = self.errorCorrectLevel
-            for typeNumber in xrange(1, 40):
+            for typeNumber in range(1, 40):
                 rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel)
                 totalDataCount = 0;
-                for i in xrange(len(rsBlocks)):
+                for i in range(len(rsBlocks)):
                     totalDataCount += rsBlocks[i].dataCount
                 length = 0
-                for i in xrange(len(self.dataList)):
+                for i in range(len(self.dataList)):
                     data = self.dataList[i]
                     length += 4
                     length += QRUtil.getLengthInBits(data.mode, typeNumber)
@@ -227,10 +227,10 @@
 
     def makeImpl(self, test, maskPattern):
         self.moduleCount = self.typeNumber * 4 + 17
-        self.modules = [None for x in xrange(self.moduleCount)]
-        for row in xrange(self.moduleCount):
-            self.modules[row] = [None for x in xrange(self.moduleCount)]
-            for col in xrange(self.moduleCount):
+        self.modules = [None for x in range(self.moduleCount)]
+        for row in range(self.moduleCount):
+            self.modules[row] = [None for x in range(self.moduleCount)]
+            for col in range(self.moduleCount):
                 self.modules[row][col] = None #(col + row) % 3;
         self.setupPositionProbePattern(0, 0)
         self.setupPositionProbePattern(self.moduleCount - 7, 0)
@@ -245,9 +245,9 @@
         self.mapData(self.dataCache, maskPattern)
 
     def setupPositionProbePattern(self, row, col):
-        for r in xrange(-1, 8):
+        for r in range(-1, 8):
             if (row + r <= -1 or self.moduleCount <= row + r): continue
-            for c in xrange(-1, 8):
+            for c in range(-1, 8):
                 if (col + c <= -1 or self.moduleCount <= col + c): continue
                 if ( (0 <= r and r <= 6 and (c == 0 or c == 6) )
                         or (0 <= c and c <= 6 and (r == 0 or r == 6) )
@@ -259,7 +259,7 @@
     def getBestMaskPattern(self):
         minLostPoint = 0
         pattern = 0
-        for i in xrange(8):
+        for i in range(8):
             self.makeImpl(True, i);
             lostPoint = QRUtil.getLostPoint(self);
             if (i == 0 or minLostPoint > lostPoint):
@@ -268,25 +268,25 @@
         return pattern
 
     def setupTimingPattern(self):
-        for r in xrange(8, self.moduleCount - 8):
+        for r in range(8, self.moduleCount - 8):
             if (self.modules[r][6] != None):
                 continue
             self.modules[r][6] = (r % 2 == 0)
-        for c in xrange(8, self.moduleCount - 8):
+        for c in range(8, self.moduleCount - 8):
             if (self.modules[6][c] != None):
                 continue
             self.modules[6][c] = (c % 2 == 0)
 
     def setupPositionAdjustPattern(self):
         pos = QRUtil.getPatternPosition(self.typeNumber)
-        for i in xrange(len(pos)):
-            for j in xrange(len(pos)):
+        for i in range(len(pos)):
+            for j in range(len(pos)):
                 row = pos[i]
                 col = pos[j]
                 if (self.modules[row][col] != None):
                     continue
-                for r in xrange(-2, 3):
-                    for c in xrange(-2, 3):
+                for r in range(-2, 3):
+                    for c in range(-2, 3):
                         if (r == -2 or r == 2 or c == -2 or c == 2 or (r == 0 and c == 0) ):
                             self.modules[row + r][col + c] = True
                         else:
@@ -294,10 +294,10 @@
 
     def setupTypeNumber(self, test):
         bits = QRUtil.getBCHTypeNumber(self.typeNumber)
-        for i in xrange(18):
+        for i in range(18):
             mod = (not test and ( (bits >> i) & 1) == 1)
             self.modules[i // 3][i % 3 + self.moduleCount - 8 - 3] = mod;
-        for i in xrange(18):
+        for i in range(18):
             mod = (not test and ( (bits >> i) & 1) == 1)
             self.modules[i % 3 + self.moduleCount - 8 - 3][i // 3] = mod;
 
@@ -305,7 +305,7 @@
         data = (self.errorCorrectLevel << 3) | maskPattern
         bits = QRUtil.getBCHTypeInfo(data)
         # vertical
-        for i in xrange(15):
+        for i in range(15):
             mod = (not test and ( (bits >> i) & 1) == 1)
             if (i < 6):
                 self.modules[i][8] = mod
@@ -314,7 +314,7 @@
             else:
                 self.modules[self.moduleCount - 15 + i][8] = mod
         # horizontal
-        for i in xrange(15):
+        for i in range(15):
             mod = (not test and ( (bits >> i) & 1) == 1);
             if (i < 8):
                 self.modules[8][self.moduleCount - i - 1] = mod
@@ -330,10 +330,10 @@
         row = self.moduleCount - 1
         bitIndex = 7
         byteIndex = 0
-        for col in xrange(self.moduleCount - 1, 0, -2):
+        for col in range(self.moduleCount - 1, 0, -2):
             if (col == 6): col-=1
             while (True):
-                for c in xrange(2):
+                for c in range(2):
                     if (self.modules[row][col - c] == None):
                         dark = False
                         if (byteIndex < len(data)):
@@ -358,14 +358,14 @@
     def createData(typeNumber, errorCorrectLevel, dataList):
         rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel)
         buffer = QRBitBuffer();
-        for i in xrange(len(dataList)):
+        for i in range(len(dataList)):
             data = dataList[i]
             buffer.put(data.mode, 4)
             buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) )
             data.write(buffer)
         # calc num max data.
         totalDataCount = 0;
-        for i in xrange(len(rsBlocks)):
+        for i in range(len(rsBlocks)):
             totalDataCount += rsBlocks[i].dataCount
         if (buffer.getLengthInBits() > totalDataCount * 8):
             raise Exception("code length overflow. (%d > %d)" % (buffer.getLengthInBits(), totalDataCount * 8))
@@ -390,39 +390,39 @@
         offset = 0
         maxDcCount = 0
         maxEcCount = 0
-        dcdata = [0 for x in xrange(len(rsBlocks))]
-        ecdata = [0 for x in xrange(len(rsBlocks))]
-        for r in xrange(len(rsBlocks)):
+        dcdata = [0 for x in range(len(rsBlocks))]
+        ecdata = [0 for x in range(len(rsBlocks))]
+        for r in range(len(rsBlocks)):
             dcCount = rsBlocks[r].dataCount
             ecCount = rsBlocks[r].totalCount - dcCount
             maxDcCount = max(maxDcCount, dcCount)
             maxEcCount = max(maxEcCount, ecCount)
-            dcdata[r] = [0 for x in xrange(dcCount)]
-            for i in xrange(len(dcdata[r])):
+            dcdata[r] = [0 for x in range(dcCount)]
+            for i in range(len(dcdata[r])):
                 dcdata[r][i] = 0xff & buffer.buffer[i + offset]
             offset += dcCount
             rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount)
             rawPoly = QRPolynomial(dcdata[r], rsPoly.getLength() - 1)
             modPoly = rawPoly.mod(rsPoly)
-            ecdata[r] = [0 for x in xrange(rsPoly.getLength()-1)]
-            for i in xrange(len(ecdata[r])):
+            ecdata[r] = [0 for x in range(rsPoly.getLength()-1)]
+            for i in range(len(ecdata[r])):
                 modIndex = i + modPoly.getLength() - len(ecdata[r])
                 if (modIndex >= 0):
                     ecdata[r][i] = modPoly.get(modIndex)
                 else:
                     ecdata[r][i] = 0
         totalCodeCount = 0
-        for i in xrange(len(rsBlocks)):
+        for i in range(len(rsBlocks)):
             totalCodeCount += rsBlocks[i].totalCount
-        data = [None for x in xrange(totalCodeCount)]
+        data = [None for x in range(totalCodeCount)]
         index = 0
-        for i in xrange(maxDcCount):
-            for r in xrange(len(rsBlocks)):
+        for i in range(maxDcCount):
+            for r in range(len(rsBlocks)):
                 if (i < len(dcdata[r])):
                     data[index] = dcdata[r][i]
                     index+=1
-        for i in xrange(maxEcCount):
-            for r in xrange(len(rsBlocks)):
+        for i in range(maxEcCount):
+            for r in range(len(rsBlocks)):
                 if (i < len(ecdata[r])):
                     data[index] = ecdata[r][i]
                     index+=1
@@ -534,7 +534,7 @@
     @staticmethod
     def getErrorCorrectPolynomial(errorCorrectLength):
         a = QRPolynomial([1], 0);
-        for i in xrange(errorCorrectLength):
+        for i in range(errorCorrectLength):
             a = a.multiply(QRPolynomial([1, QRMath.gexp(i)], 0) )
         return a
 
@@ -569,14 +569,14 @@
         moduleCount = qrCode.getModuleCount();
         lostPoint = 0;
         # LEVEL1
-        for row in xrange(moduleCount):
-            for col in xrange(moduleCount):
+        for row in range(moduleCount):
+            for col in range(moduleCount):
                 sameCount = 0;
                 dark = qrCode.isDark(row, col);
-                for r in xrange(-1, 2):
+                for r in range(-1, 2):
                     if (row + r < 0 or moduleCount <= row + r):
                         continue
-                    for c in xrange(-1, 2):
+                    for c in range(-1, 2):
                         if (col + c < 0 or moduleCount <= col + c):
                             continue
                         if (r == 0 and c == 0):
@@ -586,8 +586,8 @@
                 if (sameCount > 5):
                     lostPoint += (3 + sameCount - 5)
         # LEVEL2
-        for row in xrange(moduleCount - 1):
-            for col in xrange(moduleCount - 1):
+        for row in range(moduleCount - 1):
+            for col in range(moduleCount - 1):
                 count = 0;
                 if (qrCode.isDark(row,     col    ) ): count+=1
                 if (qrCode.isDark(row + 1, col    ) ): count+=1
@@ -596,8 +596,8 @@
                 if (count == 0 or count == 4):
                     lostPoint += 3
         # LEVEL3
-        for row in xrange(moduleCount):
-            for col in xrange(moduleCount - 6):
+        for row in range(moduleCount):
+            for col in range(moduleCount - 6):
                 if (qrCode.isDark(row, col)
                         and not qrCode.isDark(row, col + 1)
                         and  qrCode.isDark(row, col + 2)
@@ -606,8 +606,8 @@
                         and not qrCode.isDark(row, col + 5)
                         and  qrCode.isDark(row, col + 6) ):
                     lostPoint += 40
-        for col in xrange(moduleCount):
-            for row in xrange(moduleCount - 6):
+        for col in range(moduleCount):
+            for row in range(moduleCount - 6):
                 if (qrCode.isDark(row, col)
                         and not qrCode.isDark(row + 1, col)
                         and  qrCode.isDark(row + 2, col)
@@ -618,8 +618,8 @@
                     lostPoint += 40
         # LEVEL4
         darkCount = 0;
-        for col in xrange(moduleCount):
-            for row in xrange(moduleCount):
+        for col in range(moduleCount):
+            for row in range(moduleCount):
                 if (qrCode.isDark(row, col) ):
                     darkCount+=1
         ratio = abs(100 * darkCount / moduleCount / moduleCount - 50) / 5
@@ -641,13 +641,13 @@
             n -= 255
         return EXP_TABLE[n];
 
-EXP_TABLE = [x for x in xrange(256)]
-LOG_TABLE = [x for x in xrange(256)]
-for i in xrange(8):
+EXP_TABLE = [x for x in range(256)]
+LOG_TABLE = [x for x in range(256)]
+for i in range(8):
     EXP_TABLE[i] = 1 << i;
-for i in xrange(8, 256):
+for i in range(8, 256):
     EXP_TABLE[i] = EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^ EXP_TABLE[i - 8]
-for i in xrange(255):
+for i in range(255):
     LOG_TABLE[EXP_TABLE[i] ] = i
 
 class QRPolynomial:
@@ -657,8 +657,8 @@
         offset = 0
         while offset < len(num) and num[offset] == 0:
             offset += 1
-        self.num = [0 for x in xrange(len(num)-offset+shift)]
-        for i in xrange(len(num) - offset):
+        self.num = [0 for x in range(len(num)-offset+shift)]
+        for i in range(len(num) - offset):
             self.num[i] = num[i + offset]
 
     def get(self, index):
@@ -668,9 +668,9 @@
         return len(self.num)
 
     def multiply(self, e):
-        num = [0 for x in xrange(self.getLength() + e.getLength() - 1)];
-        for i in xrange(self.getLength()):
-            for j in xrange(e.getLength()):
+        num = [0 for x in range(self.getLength() + e.getLength() - 1)];
+        for i in range(self.getLength()):
+            for j in range(e.getLength()):
                 num[i + j] ^= QRMath.gexp(QRMath.glog(self.get(i) ) + QRMath.glog(e.get(j) ) )
         return QRPolynomial(num, 0);
 
@@ -678,10 +678,10 @@
         if (self.getLength() - e.getLength() < 0):
             return self;
         ratio = QRMath.glog(self.get(0) ) - QRMath.glog(e.get(0) )
-        num = [0 for x in xrange(self.getLength())]
-        for i in xrange(self.getLength()):
+        num = [0 for x in range(self.getLength())]
+        for i in range(self.getLength()):
             num[i] = self.get(i);
-        for i in xrange(e.getLength()):
+        for i in range(e.getLength()):
             num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio)
         # recursive call
         return QRPolynomial(num, 0).mod(e);
@@ -946,11 +946,11 @@
             raise Exception("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel)
         length = len(rsBlock) / 3
         list = []
-        for i in xrange(length):
+        for i in range(length):
             count = rsBlock[i * 3 + 0]
             totalCount = rsBlock[i * 3 + 1]
             dataCount  = rsBlock[i * 3 + 2]
-            for j in xrange(count):
+            for j in range(count):
                 list.append(QRRSBlock(totalCount, dataCount))
         return list;
 
@@ -981,7 +981,7 @@
         return ( (self.buffer[bufIndex] >> (7 - index % 8) ) & 1) == 1
 
     def put(self, num, length):
-        for i in xrange(length):
+        for i in range(length):
             self.putBit( ( (num >> (length - i - 1) ) & 1) == 1)
 
     def getLengthInBits(self):
--- a/src/reportlab/graphics/barcode/test.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/test.py	Tue Apr 30 14:20:22 2013 +0100
@@ -79,7 +79,7 @@
     f = Frame(inch, inch, 6*inch, 9*inch, showBoundary=1)
     f.addFromList(story, c)
     c.save()
-    print 'saved out.pdf'
+    print('saved out.pdf')
 
 def fullTest(fileName="test_full.pdf"):
     """Creates large-ish test document with a variety of parameters"""
@@ -167,8 +167,8 @@
     if height: options['height'] = height[0]
     if isoScale: options['isoScale'] = isoScale[0]
     scales = [x[8:].split(',') for x in sys.argv if x.startswith('--scale=')]
-    scales = map(float,scales and flatten(scales) or [1])
-    scales = map(float,scales and flatten(scales) or [1])
+    scales = list(map(float,scales and flatten(scales) or [1]))
+    scales = list(map(float,scales and flatten(scales) or [1]))
     for scale in scales:
         story.append(PageBreak())
         story.append(Paragraph('Scale = %.1f'%scale, styleH2))
@@ -185,7 +185,7 @@
             story.append(KeepTogether(s))
 
     SimpleDocTemplate(fileName).build(story)
-    print 'created', fileName
+    print('created', fileName)
 
 if __name__=='__main__':
     run()
--- a/src/reportlab/graphics/barcode/usps.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/usps.py	Tue Apr 30 14:20:22 2013 +0100
@@ -31,7 +31,7 @@
 #
 
 from reportlab.lib.units import inch
-from common import Barcode
+from .common import Barcode
 import string
 
 _fim_patterns = {
@@ -97,7 +97,7 @@
     lquiet = inch * (15.0/32.0)
     quiet = 0
     def __init__(self, value='', **args):
-        for (k, v) in args.items():
+        for (k, v) in list(args.items()):
             setattr(self, k, v)
 
         Barcode.__init__(self, value)
@@ -114,7 +114,7 @@
                 self.valid = 0
 
         if len(self.validated) != 1:
-            raise ValueError, "Input must be exactly one character"
+            raise ValueError("Input must be exactly one character")
 
         return self.validated
 
@@ -162,7 +162,7 @@
     spaceWidth = inch * 0.0275
     def __init__(self, value='', **args):
 
-        for (k, v) in args.items():
+        for (k, v) in list(args.items()):
             setattr(self, k, v)
 
         Barcode.__init__(self, value)
@@ -197,7 +197,7 @@
             elif c == '-':
                 pass
             else:
-                raise ValueError, "Invalid character in input"
+                raise ValueError("Invalid character in input")
         check = (10 - check) % 10
         self.encoded = self.encoded + repr(check) + 'S'
         return self.encoded
--- a/src/reportlab/graphics/barcode/usps4s.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/barcode/usps4s.py	Tue Apr 30 14:20:22 2013 +0100
@@ -4,7 +4,7 @@
 __all__ = ('USPS_4State',)
 
 from reportlab.lib.colors import black
-from common import Barcode
+from .common import Barcode
 
 class USPS_4State(Barcode):
     ''' USPS 4-State OneView (TM) barcode. All info from USPS-B-3200A
@@ -125,7 +125,7 @@
                 svalue = tracking[j:i]
                 try:
                     if len(svalue)!=nd: raise ValueError
-                    for j in xrange(nd):
+                    for j in range(nd):
                         value *= 10
                         value += int(svalue[j])
                 except:
@@ -150,7 +150,7 @@
             A, D = divmod(A,1365)
             A, C = divmod(A,1365)
             A, B = divmod(A,1365)
-            assert 0<=A<=658, 'improper value %s passed to _2codewords A-->%s' % (hex(long(value)),A)
+            assert 0<=A<=658, 'improper value %s passed to _2codewords A-->%s' % (hex(int(value)),A)
             self._fcs = _crc11(value)
             if self._fcs&1024: A += 659
             J *= 2
@@ -181,7 +181,7 @@
             aC = C.append
             table1 = self.table1
             table2 = self.table2
-            for i in xrange(10):
+            for i in range(10):
                 cw = codewords[i]
                 if cw<=1286:
                     c = table1[cw]
@@ -313,12 +313,12 @@
     >>> print ' '.join(hex(_crc11(USPS_4State('01234567094987654321',x).binary)) for x in ('','01234','012345678','01234567891'))
     0x51 0x65 0x606 0x751
     '''
-    bytes = hex(long(value))[2:-1]
+    bytes = hex(int(value))[2:-1]
     bytes = '0'*(26-len(bytes))+bytes
     gp = 0x0F35
     fcs = 0x07FF
     data = int(bytes[:2],16)<<5
-    for b in xrange(2,8):
+    for b in range(2,8):
         if (fcs ^ data)&0x400:
             fcs = (fcs<<1)^gp
         else:
@@ -326,9 +326,9 @@
         fcs &= 0x7ff
         data <<= 1
 
-    for x in xrange(2,2*13,2):
+    for x in range(2,2*13,2):
         data = int(bytes[x:x+2],16)<<3
-        for b in xrange(8):
+        for b in range(8):
             if (fcs ^ data)&0x400:
                 fcs = (fcs<<1)^gp
             else:
@@ -343,7 +343,7 @@
     31 7936 7808 47
     '''
     r = 0
-    for x in xrange(13):
+    for x in range(13):
         r <<= 1
         r |= i & 1
         i >>= 1
@@ -358,9 +358,9 @@
     T = lenT*[None]
     l = 0
     u = lenT-1
-    for c in xrange(8192):
+    for c in range(8192):
         bc = 0
-        for b in xrange(13):
+        for b in range(13):
             bc += (c&(1<<b))!=0
         if bc!=N: continue
         r = _ru13(c)
--- a/src/reportlab/graphics/charts/axes.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/axes.py	Tue Apr 30 14:20:22 2013 +0100
@@ -44,6 +44,7 @@
 from reportlab.graphics.widgets.grids import ShadedRect
 from reportlab.lib.colors import Color
 import copy
+from functools import reduce
 
 
 # Helpers.
@@ -53,10 +54,10 @@
             f=lambda T,x=x,special=special,func=func: special(T,x,func)
         else:
             f=lambda T,x=x: T[x]
-        V=map(lambda e,f=f: map(f,e),V)
-    V = filter(len,map(lambda x: filter(lambda x: x is not None,x),V))
+        V=list(map(lambda e,f=f: list(map(f,e)),V))
+    V = list(filter(len,[[x for x in x if x is not None] for x in V]))
     if len(V)==0: return default
-    return func(map(func,V))
+    return func(list(map(func,V)))
 
 def _findMin(V, x, default,special=None):
     '''find minimum over V[i][x]'''
@@ -140,7 +141,7 @@
                     d = hi
                 axis._get_line_pos = lambda x: d
             L = func(v)
-            for k,v in kwds.iteritems():
+            for k,v in kwds.items():
                 setattr(L,k,v)
         finally:
             axis._get_line_pos = oaglp
@@ -185,7 +186,7 @@
         G = Group()
         ncolors = len(colors)
         v0 = axis._get_line_pos(tv[0])
-        for i in xrange(1,len(tv)):
+        for i in range(1,len(tv)):
             v1 = axis._get_line_pos(tv[i])
             c = colors[(i-1)%ncolors]
             if c:
@@ -294,7 +295,7 @@
                 L.strokeLineCap = strokeLineCap
                 L.strokeMiterLimit = strokeMiterLimit
                 if t in specials:
-                    for a,v in specials[t].iteritems():
+                    for a,v in specials[t].items():
                         setattr(L,a,v)
                 g.add(L)
 
@@ -517,7 +518,7 @@
         self._length = float(length)
 
     def configure(self, multiSeries,barWidth=None):
-        self._catCount = max(map(len,multiSeries))
+        self._catCount = max(list(map(len,multiSeries)))
         self._barWidth = barWidth or ((self._length-self.loPad-self.hiPad)/float(self._catCount or 1))
         self._calcTickmarkPositions()
         if self.labelAxisMode == 'axispmv':
@@ -526,12 +527,12 @@
     def _calcTickmarkPositions(self):
         n = self._catCount
         if self.tickShift:
-            self._tickValues = [t+0.5 for t in xrange(n)]
+            self._tickValues = [t+0.5 for t in range(n)]
         else:
             if self.reverseDirection:
-                self._tickValues = range(-1,n)
+                self._tickValues = list(range(-1,n))
             else:
-                self._tickValues = range(n+1)
+                self._tickValues = list(range(n+1))
 
     def _scale(self,idx):
         if self.reverseDirection: idx = self._catCount-idx-1
@@ -596,7 +597,7 @@
                 if OTV[-1]<vx: OTV.append(OTV[-1]+dst)
                 dst /= float(nst+1)
                 for i,x in enumerate(OTV[:-1]):
-                    for j in xrange(nst):
+                    for j in range(nst):
                         t = x+dCnv((j+1)*dst)
                         if t<=vn or t>=vx: continue
                         T(t)
@@ -744,7 +745,7 @@
             _x = self._x
             pmv = self._pmv if self.labelAxisMode=='axispmv' else None
 
-            for i in xrange(catCount):
+            for i in range(catCount):
                 if reverseDirection: ic = catCount-i-1
                 else: ic = i
                 if ic>=n: continue
@@ -856,7 +857,7 @@
             _y = self._y
             pmv = self._pmv if self.labelAxisMode=='axispmv' else None
 
-            for i in xrange(catCount):
+            for i in range(catCount):
                 if reverseDirection: ic = catCount-i-1
                 else: ic = i
                 if ic>=n: continue
@@ -1309,7 +1310,7 @@
         if rangeRound in ('both','ceiling'):
             if v<valueMax-fuzz: i1 += 1
         elif v>valueMax+fuzz: i1 -= 1
-        return valueStep,[i*valueStep for i in xrange(i0,i1+1)]
+        return valueStep,[i*valueStep for i in range(i0,i1+1)]
 
     def _calcTickPositions(self):
         return self._calcStepAndTickPositions()[1]
@@ -1397,7 +1398,7 @@
                         else:
                             txt = f(t)
                     else:
-                        raise ValueError, 'Invalid labelTextFormat %s' % f
+                        raise ValueError('Invalid labelTextFormat %s' % f)
                     if post: txt = post % txt
                     pos[d] = v
                     label.setOrigin(*pos)
@@ -1676,7 +1677,7 @@
         #specified the days of year to be ticked.  Other explicit routes may
         #be added.
         if self.forceDatesEachYear:
-            forcedPartialDates = map(parseDayAndMonth, self.forceDatesEachYear)
+            forcedPartialDates = list(map(parseDayAndMonth, self.forceDatesEachYear))
             #generate the list of dates in the range.
             #print 'dates range from %s to %s' % (firstDate, endDate)
             firstYear = firstDate.year()
@@ -1766,7 +1767,7 @@
 
         VC = self._valueClass
         for D in data:
-            for i in xrange(len(D)):
+            for i in range(len(D)):
                 x, y = D[i]
                 if not isinstance(x,VC):
                     D[i] = (VC(x),y)
@@ -1792,7 +1793,7 @@
     def configure(self, data):
         self._convertXV(data)
         from reportlab.lib.set_ops import union
-        xVals = reduce(union,map(lambda x: map(lambda dv: dv[0],x),data),[])
+        xVals = reduce(union,[[dv[0] for dv in x] for x in data],[])
         xVals.sort()
         steps,labels = self._getStepsAndLabels(xVals)
         valueMin, valueMax = self.valueMin, self.valueMax
@@ -1910,7 +1911,7 @@
         from reportlab.graphics.charts.utils import find_good_grid, ticks
         y_min, y_max = self._valueMin, self._valueMax
         m = self.maximumTicks
-        n = filter(lambda x,m=m: x<=m,[4,5,6,7,8,9])
+        n = list(filter(lambda x,m=m: x<=m,[4,5,6,7,8,9]))
         if not n: n = [m]
 
         valueStep, requiredRange = self.valueStep, self.requiredRange
--- a/src/reportlab/graphics/charts/barcharts.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/barcharts.py	Tue Apr 30 14:20:22 2013 +0100
@@ -160,7 +160,7 @@
     def demo(self):
         """Shows basic use of a bar chart"""
         if self.__class__.__name__=='BarChart':
-            raise NotImplementedError, 'Abstract Class BarChart has no demo'
+            raise NotImplementedError('Abstract Class BarChart has no demo')
         drawing = Drawing(200, 100)
         bc = self.__class__()
         drawing.add(bc)
@@ -171,9 +171,9 @@
         data = self.data
         if cA.style not in ('parallel','parallel_3d'):
             _data = data
-            data = max(map(len,_data))*[0]
+            data = max(list(map(len,_data)))*[0]
             for d in _data:
-                for i in xrange(len(d)):
+                for i in range(len(d)):
                     data[i] = data[i] + (d[i] or 0)
             data = list(_data) + [data]
         self._configureData = data
@@ -244,7 +244,7 @@
                 except:
                     raise ValueError('Bad zIndex value %r in clause %r of zIndex\nallowed variables are\n%s' % (v,z,zIndex,'\n'.join(['%s=%r'% (k,Z[k]) for k in sorted(Z.keys())])))
                 Z[k] = v
-            Z = [(v,k) for k,v in Z.iteritems()]
+            Z = [(v,k) for k,v in Z.items()]
             Z.sort()
             b = self.makeBars()
             bl = b.contents.pop(-1)
@@ -287,7 +287,7 @@
 
         data = self.data
         seriesCount = self._seriesCount = len(data)
-        self._rowLength = rowLength = max(map(len,data))
+        self._rowLength = rowLength = max(list(map(len,data)))
         wG = self.groupSpacing
         barSpacing = self.barSpacing
         barWidth = self.barWidth
@@ -358,7 +358,7 @@
             baseLine = vScale(vM)
         self._baseLine = baseLine
 
-        nC = max(map(len,data))
+        nC = max(list(map(len,data)))
 
         width = barWidth*fB
         offs = 0.5*wG*fG
@@ -375,7 +375,7 @@
         self._barPositions = []
         aBP = self._barPositions.append
         reversePlotOrder = self.reversePlotOrder
-        for rowNo in xrange(seriesCount):
+        for rowNo in range(seriesCount):
             barRow = []
             if reversePlotOrder:
                 xVal = seriesCount-1 - rowNo
@@ -383,7 +383,7 @@
                 xVal = rowNo
             xVal = offs + xVal*bGap
             row = data[rowNo]
-            for colNo in xrange(nC):
+            for colNo in range(nC):
                 datum = row[colNo]
 
                 # Ufff...
@@ -425,7 +425,7 @@
             labelText = labelFmt(self.data[rowNo][colNo])
         else:
             msg = "Unknown formatter type %s, expected string or function" % labelFmt
-            raise Exception, msg
+            raise Exception(msg)
         return labelText
 
     def _labelXY(self,label,x,y,width,height):
@@ -542,19 +542,19 @@
             CBL = []
             rowNoL = lenData - 1
             #find all the categories that have at least one value
-            for rowNo in xrange(lenData):
+            for rowNo in range(lenData):
                 row = BP[rowNo]
-                for colNo in xrange(len(row)):
+                for colNo in range(len(row)):
                     x, y, width, height = row[colNo]
                     if None not in (width,height):
                         catNNA[colNo] = 1
 
-        for rowNo in xrange(lenData):
+        for rowNo in range(lenData):
             row = BP[rowNo]
             styleCount = len(bars)
             styleIdx = rowNo % styleCount
             rowStyle = bars[styleIdx]
-            for colNo in xrange(len(row)):
+            for colNo in range(len(row)):
                 style = (styleIdx,colNo) in bars and bars[(styleIdx,colNo)] or rowStyle
                 x, y, width, height = row[colNo]
                 if None in (width,height):
@@ -664,7 +664,7 @@
             lo = self.x
             hi = lo + self.width
             end = self.y+self.height
-            for i in xrange(lenData):
+            for i in range(lenData):
                 for x, y, w, h in BP[i]:
                     v = x+w
                     z = y+h
@@ -673,7 +673,7 @@
             lo = self.y
             hi = lo + self.height
             end = self.x+self.width
-            for i in xrange(lenData):
+            for i in range(lenData):
                 for x, y, w, h in BP[i]:
                     v = y+h
                     z = x+w
@@ -727,7 +727,7 @@
         bars = self.bars
         R = [].append
         BP = self._barPositions
-        for rowNo in xrange(lenData):
+        for rowNo in range(lenData):
             row = BP[rowNo]
             C = [].append
             for colNo in range(len(row)):
@@ -763,7 +763,7 @@
         style = self.categoryAxis.style
         data = self.data
         n = len(data)
-        m = max(map(len,data))
+        m = max(list(map(len,data)))
         if style=='parallel':
             groupWidth = (n-1)*self.barSpacing+n*self.barWidth
         else:
@@ -872,7 +872,7 @@
         g.add((1,z0,z1,x,y,width,height,rowNo,colNo))
 
     def makeBars(self):
-        from utils3d import _draw_3d_bar
+        from .utils3d import _draw_3d_bar
         fg = _FakeGroup(cmp=self._cmpZ)
         self._makeBars(fg,fg)
         fg.sort()
@@ -1020,7 +1020,7 @@
     bc.categoryAxis.labels.angle = 30
 
     catNames = 'Jan Feb Mar Apr May Jun Jul Aug'.split(' ')
-    catNames = map(lambda n:n+'-99', catNames)
+    catNames = [n+'-99' for n in catNames]
     bc.categoryAxis.categoryNames = catNames
     drawing.add(bc)
 
@@ -1641,7 +1641,7 @@
 
     bc.categoryAxis.labels.boxAnchor = 'e'
     catNames = 'Jan Feb Mar Apr May Jun Jul Aug'.split(' ')
-    catNames = map(lambda n:n+'-99', catNames)
+    catNames = [n+'-99' for n in catNames]
     bc.categoryAxis.categoryNames = catNames
     drawing.add(bc, 'barchart')
 
--- a/src/reportlab/graphics/charts/doughnut.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/doughnut.py	Tue Apr 30 14:20:22 2013 +0100
@@ -30,6 +30,7 @@
 from reportlab.graphics.charts.piecharts import AbstractPieChart, WedgeProperties, _addWedgeLabel, fixLabelOverlaps
 from reportlab.graphics.charts.textlabels import Label
 from reportlab.graphics.widgets.markers import Marker
+from functools import reduce
 
 class SectorProperties(WedgeProperties):
     """This holds descriptive information about the sectors in a doughnut chart.
@@ -113,7 +114,7 @@
     def normalizeData(self, data=None):
         from operator import add
         sum = float(reduce(add,data,0))
-        return abs(sum)>=1e-8 and map(lambda x,f=360./sum: f*x, data) or len(data)*[0]
+        return abs(sum)>=1e-8 and list(map(lambda x,f=360./sum: f*x, data)) or len(data)*[0]
 
     def makeSectors(self):
         # normalize slice data
--- a/src/reportlab/graphics/charts/legends.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/legends.py	Tue Apr 30 14:20:22 2013 +0100
@@ -19,6 +19,7 @@
 from reportlab.graphics.widgets.markers import uSymbol2Symbol, isSymbol
 from reportlab.lib.utils import isSeqType, find_locals
 from reportlab.graphics.shapes import _baseGFontName
+from functools import reduce
 
 def _transMax(n,A):
     X = n*[0]
@@ -28,19 +29,19 @@
         for i,x in enumerate(a):
             X[i] = max(X[i],x)
     X = [0] + X[:m]
-    for i in xrange(m):
+    for i in range(m):
         X[i+1] += X[i]
     return X
 
 def _objStr(s):
-    if isinstance(s,basestring):
+    if isinstance(s,str):
         return s
     else:
         return str(s)
 
 def _getStr(s):
     if isSeqType(s):
-        return map(_getStr,s)
+        return list(map(_getStr,s))
     else:
         return _objStr(s)
 
@@ -239,7 +240,7 @@
             texts = [_getStr(p[1]) for p in colorNamePairs]
         else:
             chart = getattr(colorNamePairs,'chart',getattr(colorNamePairs,'obj',None))
-            texts = [chart.getSeriesName(i,'series %d' % i) for i in xrange(chart._seriesCount)]
+            texts = [chart.getSeriesName(i,'series %d' % i) for i in range(chart._seriesCount)]
         return texts
 
     def _calculateMaxBoundaries(self, colorNamePairs):
@@ -254,7 +255,7 @@
         n = max([len(m) for m in M])
         if self.variColumn:
             columnMaximum = self.columnMaximum
-            return [_transMax(n,M[r:r+columnMaximum]) for r in xrange(0,len(M),self.columnMaximum)]
+            return [_transMax(n,M[r:r+columnMaximum]) for r in range(0,len(M),self.columnMaximum)]
         else:
             return _transMax(n,M)
 
@@ -371,7 +372,7 @@
             dividerOffsX = self.dividerOffsX
             dividerOffsY = self.dividerOffsY
 
-        for i in xrange(n):
+        for i in range(n):
             if autoCP:
                 col = autoCP
                 col.index = i
@@ -400,7 +401,7 @@
                 x = thisx+dx+dxTextSpace
                 xn = thisx
             else:
-                raise ValueError, "bad alignment"
+                raise ValueError("bad alignment")
             if not isSeqType(name):
                 T = [T]
             yd = y
@@ -525,7 +526,7 @@
         legend.y = 100
         legend.dxTextSpace = 5
         items = 'red green blue yellow pink black white'.split()
-        items = map(lambda i:(getattr(colors, i), i), items)
+        items = [(getattr(colors, i), i) for i in items]
         legend.colorNamePairs = items
 
         d.add(legend, 'legend')
@@ -641,7 +642,7 @@
     legend.y = 100
     legend.dxTextSpace = 5
     items = 'red green blue yellow pink black white'.split()
-    items = map(lambda i:(getattr(colors, i), i), items)
+    items = [(getattr(colors, i), i) for i in items]
     legend.colorNamePairs = items
 
     d.add(legend, 'legend')
@@ -662,7 +663,7 @@
     legend.dxTextSpace = 10
     legend.columnMaximum = 4
     items = 'red green blue yellow pink black white'.split()
-    items = map(lambda i:(getattr(colors, i), i), items)
+    items = [(getattr(colors, i), i) for i in items]
     legend.colorNamePairs = items
 
     d.add(legend, 'legend')
@@ -682,7 +683,7 @@
     legend.dxTextSpace = 10
     legend.columnMaximum = 4
     items = 'red green blue yellow pink black white'.split()
-    items = map(lambda i:(getattr(colors, i), i), items)
+    items = [(getattr(colors, i), i) for i in items]
     legend.colorNamePairs = items
     d.add(legend, 'legend')
 
--- a/src/reportlab/graphics/charts/linecharts.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/linecharts.py	Tue Apr 30 14:20:22 2013 +0100
@@ -214,7 +214,7 @@
         """
 
         self._seriesCount = len(self.data)
-        self._rowLength = max(map(len,self.data))
+        self._rowLength = max(list(map(len,self.data)))
 
         if self.useAbsolute:
             # Dimensions are absolute.
@@ -285,7 +285,7 @@
         g = Group()
 
         labelFmt = self.lineLabelFormat
-        P = range(len(self._positions))
+        P = list(range(len(self._positions)))
         if self.reversePlotOrder: P.reverse()
         inFill = self.inFill
         if inFill:
@@ -453,7 +453,7 @@
 
     def makeLines(self):
         labelFmt = self.lineLabelFormat
-        P = range(len(self._positions))
+        P = list(range(len(self._positions)))
         if self.reversePlotOrder: P.reverse()
         inFill = self.inFill
         assert not inFill, "inFill not supported for 3d yet"
@@ -467,7 +467,7 @@
         theta_x = self.theta_x
         theta_y = self.theta_y
         F = _FakeGroup()
-        from utils3d import _make_3d_line_info
+        from .utils3d import _make_3d_line_info
         tileWidth = getattr(self,'_3d_tilewidth',None)
         if not tileWidth and self.categoryAxis.style!='parallel_3d': tileWidth = 1
 
@@ -494,7 +494,7 @@
             if self.joinedLines:
                 if n:
                     x0, y0 = row[0]
-                    for colNo in xrange(1,n):
+                    for colNo in range(1,n):
                         x1, y1 = row[colNo]
                         _make_3d_line_info( F, x0, x1, y0, y1, z0, z1,
                                 theta_x, theta_y,
@@ -511,14 +511,14 @@
                 uSymbol = None
 
             if uSymbol:
-                for colNo in xrange(n):
+                for colNo in range(n):
                     x1, y1 = row[colNo]
                     x1, y1 = _zadjust(x1,y1,z0)
                     symbol = uSymbol2Symbol(uSymbol,x1,y1,rowColor)
                     if symbol: F.add((2,z0,z0,x1,y1,symbol))
 
             # Draw item labels.
-            for colNo in xrange(n):
+            for colNo in range(n):
                 x1, y1 = row[colNo]
                 x1, y1 = _zadjust(x1,y1,z0)
                 L = self._innerDrawLabel(rowNo, colNo, x1, y1)
--- a/src/reportlab/graphics/charts/lineplots.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/lineplots.py	Tue Apr 30 14:20:22 2013 +0100
@@ -71,7 +71,7 @@
 class PolyFiller(Filler,Polygon):
     pass
 
-from linecharts import AbstractLineChart
+from .linecharts import AbstractLineChart
 class LinePlot(AbstractLineChart):
     """Line plot with multiple lines.
 
@@ -184,7 +184,7 @@
         """
 
         self._seriesCount = len(self.data)
-        self._rowLength = max(map(len,self.data))
+        self._rowLength = max(list(map(len,self.data)))
 
         self._positions = []
         for rowNo in range(len(self.data)):
@@ -249,7 +249,7 @@
 
         labelFmt = self.lineLabelFormat
 
-        P = range(len(self._positions))
+        P = list(range(len(self._positions)))
         if self.reversePlotOrder: P.reverse()
         inFill = getattr(self,'_inFill',None)
         styleCount = len(self.lines)
@@ -405,9 +405,9 @@
             x = xScale(xv)
             y = yScale(yv)
             g = Group()
-            xA = xScale.im_self #the x axis
+            xA = xScale.__self__ #the x axis
             g.add(Line(xA._x,y,xA._x+xA._length,y,strokeColor=strokeColor,strokeWidth=strokeWidth))
-            yA = yScale.im_self #the y axis
+            yA = yScale.__self__ #the y axis
             g.add(Line(x,yA._y,x,yA._y+yA._length,strokeColor=strokeColor,strokeWidth=strokeWidth))
             return g
         annotation.beforeLines = beforeLines
@@ -461,7 +461,7 @@
         labelFmt = self.lineLabelFormat
         positions = self._positions
 
-        P = range(len(positions))
+        P = list(range(len(positions)))
         if self.reversePlotOrder: P.reverse()
         inFill = getattr(self,'_inFill',None)
         assert not inFill, "inFill not supported for 3d yet"
@@ -474,15 +474,15 @@
         _zadjust = self._zadjust
         theta_x = self.theta_x
         theta_y = self.theta_y
-        from linecharts import _FakeGroup
+        from .linecharts import _FakeGroup
         F = _FakeGroup()
 
-        from utils3d import _make_3d_line_info, find_intersections
+        from .utils3d import _make_3d_line_info, find_intersections
         if self.xValueAxis.style!='parallel_3d':
             tileWidth = getattr(self,'_3d_tilewidth',1)
             if getattr(self,'_find_intersections',None):
                 from copy import copy
-                fpositions = map(copy,positions)
+                fpositions = list(map(copy,positions))
                 I = find_intersections(fpositions,small=tileWidth)
                 ic = None
                 for i,j,x,y in I:
@@ -522,7 +522,7 @@
                 if n:
                     frow = fpositions[rowNo]
                     x0, y0 = frow[0]
-                    for colNo in xrange(1,len(frow)):
+                    for colNo in range(1,len(frow)):
                         x1, y1 = frow[colNo]
                         _make_3d_line_info( F, x0, x1, y0, y1, z0, z1,
                                 theta_x, theta_y,
@@ -546,7 +546,7 @@
                     if symbol: F.add((1,z0,z0,x1,y1,symbol))
 
             # Draw data labels.
-            for colNo in xrange(n):
+            for colNo in range(n):
                 x1, y1 = row[colNo]
                 x1, y1 = _zadjust(x1,y1,z0)
                 L = self._innerDrawLabel(rowNo, colNo, x1, y1)
@@ -716,13 +716,13 @@
         back = self.background
         if isinstance(back, Grid):
             if back.orientation == 'vertical' and xva._tickValues:
-                xpos = map(xva.scale, [xva._valueMin] + xva._tickValues)
+                xpos = list(map(xva.scale, [xva._valueMin] + xva._tickValues))
                 steps = []
                 for i in range(len(xpos)-1):
                     steps.append(xpos[i+1] - xpos[i])
                 back.deltaSteps = steps
             elif back.orientation == 'horizontal' and yva._tickValues:
-                ypos = map(yva.scale, [yva._valueMin] + yva._tickValues)
+                ypos = list(map(yva.scale, [yva._valueMin] + yva._tickValues))
                 steps = []
                 for i in range(len(ypos)-1):
                     steps.append(ypos[i+1] - ypos[i])
@@ -740,25 +740,25 @@
 
             # some room left for optimization...
             if back.grid0.orientation == 'vertical' and xva._tickValues:
-                xpos = map(xva.scale, [xva._valueMin] + xva._tickValues)
+                xpos = list(map(xva.scale, [xva._valueMin] + xva._tickValues))
                 steps = []
                 for i in range(len(xpos)-1):
                     steps.append(xpos[i+1] - xpos[i])
                 back.grid0.deltaSteps = steps
             elif back.grid0.orientation == 'horizontal' and yva._tickValues:
-                ypos = map(yva.scale, [yva._valueMin] + yva._tickValues)
+                ypos = list(map(yva.scale, [yva._valueMin] + yva._tickValues))
                 steps = []
                 for i in range(len(ypos)-1):
                     steps.append(ypos[i+1] - ypos[i])
                 back.grid0.deltaSteps = steps
             if back.grid1.orientation == 'vertical' and xva._tickValues:
-                xpos = map(xva.scale, [xva._valueMin] + xva._tickValues)
+                xpos = list(map(xva.scale, [xva._valueMin] + xva._tickValues))
                 steps = []
                 for i in range(len(xpos)-1):
                     steps.append(xpos[i+1] - xpos[i])
                 back.grid1.deltaSteps = steps
             elif back.grid1.orientation == 'horizontal' and yva._tickValues:
-                ypos = map(yva.scale, [yva._valueMin] + yva._tickValues)
+                ypos = list(map(yva.scale, [yva._valueMin] + yva._tickValues))
                 steps = []
                 for i in range(len(ypos)-1):
                     steps.append(ypos[i+1] - ypos[i])
@@ -795,9 +795,9 @@
             m = len(odata[0])
             S = n*[0]
             self.data = []
-            for i in xrange(1,m):
+            for i in range(1,m):
                 D = []
-                for j in xrange(n):
+                for j in range(n):
                     S[j] = S[j] + odata[j][i]
                     D.append((odata[j][0],S[j]))
                 self.data.append(D)
@@ -822,8 +822,8 @@
 def _maxWidth(T, fontName, fontSize):
     '''return max stringWidth for the list of strings T'''
     if type(T) not in (type(()),type([])): T = (T,)
-    T = filter(None,T)
-    return T and max(map(lambda t,sW=stringWidth,fN=fontName, fS=fontSize: sW(t,fN,fS),T)) or 0
+    T = [_f for _f in T if _f]
+    return T and max(list(map(lambda t,sW=stringWidth,fN=fontName, fS=fontSize: sW(t,fN,fS),T))) or 0
 
 class ScatterPlot(LinePlot):
     """A scatter plot widget"""
@@ -1086,7 +1086,7 @@
 def preprocessData(series):
     "Convert date strings into seconds and multiply values by 100."
 
-    return map(lambda x: (str2seconds(x[0]), x[1]*100), series)
+    return [(str2seconds(x[0]), x[1]*100) for x in series]
 
 
 def sample2():
--- a/src/reportlab/graphics/charts/piecharts.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/piecharts.py	Tue Apr 30 14:20:22 2013 +0100
@@ -256,7 +256,7 @@
     '''determine a set of overlaps in bounding boxes B or return None'''
     n = len(B)
     if n>1:
-        for i in xrange(n-1):
+        for i in range(n-1):
             R = _findOverlapRun(B,i,wrap)
             if len(R)>1: return R
     return None
@@ -481,7 +481,7 @@
     vstar = len(data)*1e6
     rstar = 0
     delta = pi/36.0
-    for i in xrange(36):
+    for i in range(36):
         r = i*delta
         v = sum([abs(sin(r+a)) for a in hrads])
         if v < vstar:
@@ -658,7 +658,7 @@
         return PL(centerx,centery,xradius,yradius,G,lu,ru)
 
     def normalizeData(self,keepData=False):
-        data = map(abs,self.data)
+        data = list(map(abs,self.data))
         s = self._sum = float(sum(data))
         if s<=1e-8: s = 0
         f = 360./s
@@ -968,7 +968,7 @@
         self.legend1.columnMaximum = 7
         self.legend1.alignment = 'right'
         self.legend_names = ['AAA:','AA:','A:','BBB:','NR:']
-        for f in xrange(len(self.data)):
+        for f in range(len(self.data)):
             self.legend1.colorNamePairs.append((self.pieAndLegend_colors[f], self.legend_names[f]))
         self.legend1.fontName = "Helvetica-Bold"
         self.legend1.fontSize = 6
@@ -993,7 +993,7 @@
         if self.drawLegend:
             self.legend1.colorNamePairs = []
             self._legend2.colorNamePairs = []
-        for f in xrange(len(self.data)):
+        for f in range(len(self.data)):
             if self.legend_names == None:
                 self.slices[f].fillColor = self.pieAndLegend_colors[f]
                 self.legend1.colorNamePairs.append((self.pieAndLegend_colors[f], None))
@@ -1027,7 +1027,7 @@
                         ldf = lNF(ldf)
                     else:
                         msg = "Unknown formatter type %s, expected string or function" % self.legendNumberFormat
-                        raise Exception, msg
+                        raise Exception(msg)
                     self._legend2.colorNamePairs.append((None,ldf))
         p = Pie.draw(self)
         if self.drawLegend:
@@ -1243,7 +1243,7 @@
     
         checkLabelOverlap = self.checkLabelOverlap
 
-        for i in xrange(n):
+        for i in range(n):
             style = slices[i]
             if not style.visible: continue
             sl = _sl3d[i]
--- a/src/reportlab/graphics/charts/spider.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/spider.py	Tue Apr 30 14:20:22 2013 +0100
@@ -30,7 +30,7 @@
 from reportlab.graphics.widgetbase import Widget, TypedPropertyCollection, PropHolder
 from reportlab.graphics.charts.areas import PlotArea
 from reportlab.graphics.charts.legends import _objStr
-from piecharts import WedgeLabel
+from .piecharts import WedgeLabel
 from reportlab.graphics.widgets.markers import makeMarker, uSymbol2Symbol, isSymbol
 
 class StrandProperty(PropHolder):
@@ -75,7 +75,7 @@
 class SpokeLabel(WedgeLabel):
     def __init__(self,**kw):
         WedgeLabel.__init__(self,**kw)
-        if '_text' not in kw.keys(): self._text = ''
+        if '_text' not in list(kw.keys()): self._text = ''
 
 class StrandLabel(SpokeLabel):
     _attrMap = AttrMap(BASE=SpokeLabel,
@@ -189,8 +189,8 @@
         """Turns data into normalized ones where each datum is < 1.0,
         and 1.0 = maximum radius.  Adds 10% at outside edge by default"""
         data = self.data
-        assert min(map(min,data)) >=0, "Cannot do spider plots of negative numbers!"
-        norm = max(map(max,data))
+        assert min(list(map(min,data))) >=0, "Cannot do spider plots of negative numbers!"
+        norm = max(list(map(max,data)))
         norm *= (1.0+outer)
         if norm<1e-9: norm = 1.0
         self._norm = norm
@@ -259,7 +259,7 @@
         angleBetween = direction*(2 * pi)/float(n)
         spokes = self.spokes
         spokeLabels = self.spokeLabels
-        for i in xrange(n):
+        for i in range(n):
             car = cos(angle)*radius
             sar = sin(angle)*radius
             csa.append((car,sar,angle))
@@ -286,7 +286,7 @@
             r = row[-1]
             points.append(cx+car*r)
             points.append(cy+sar*r)
-            for i in xrange(n):
+            for i in range(n):
                 car, sar, angle = csa[i]
                 r = row[i]
                 points.append(cx+car*r)
--- a/src/reportlab/graphics/charts/textlabels.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/textlabels.py	Tue Apr 30 14:20:22 2013 +0100
@@ -35,14 +35,14 @@
             if O[0]=='moveToClosed':
                 O = O[1:]
                 if pathReverse:
-                    for i in xrange(0,len(P),2):
+                    for i in range(0,len(P),2):
                         P[i+1], P[i] = P[i:i+2]
                     P.reverse()
                     O.reverse()
                 O.insert(0,'moveTo')
                 O.append('closePath')
             i = 0
-            if truncate: P = map(_pathNumTrunc,P)
+            if truncate: P = list(map(_pathNumTrunc,P))
             for o in O:
                 j = i + _PATH_OP_ARG_COUNT[_PATH_OP_NAMES.index(o)]
                 if o=='closePath':
@@ -344,7 +344,7 @@
     def __init__(self):
         self.textAnchor = 'start'
         self.boxAnchor = 'w'
-        for a in self._attrMap.keys():
+        for a in list(self._attrMap.keys()):
             if not hasattr(self,a): setattr(self,a,None)
 
     def decorate(self,l,L):
@@ -355,7 +355,7 @@
     def __call__(self,l):
         from copy import deepcopy
         L = Label()
-        for a,v in self.__dict__.items():
+        for a,v in list(self.__dict__.items()):
             if v is None: v = getattr(l,a,None)
             setattr(L,a,v)
         self.decorate(l,L)
--- a/src/reportlab/graphics/charts/utils.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/utils.py	Tue Apr 30 14:20:22 2013 +0100
@@ -16,7 +16,7 @@
     "Convert a 'dd/mm/yyyy' formatted string to a tuple for use in the time module."
 
     list = [0] * 9
-    dd, mm, yyyy = map(int, timeString.split('/'))
+    dd, mm, yyyy = list(map(int, timeString.split('/')))
     list[:3] = [yyyy, mm, dd]
 
     return tuple(list)
@@ -84,7 +84,7 @@
                 lo = 0.9*lo
                 hi = 1.1*hi
         else:
-            raise ValueError, "lo>hi"
+            raise ValueError("lo>hi")
     x=(hi - lo)/float(I)
     b= (x>0 and (x<1 or x>10)) and 10**floor(log10(x)) or 1
     b = b
@@ -129,7 +129,7 @@
         try:
             n[0]
         except TypeError:
-            n = xrange(max(1,n-2),max(n+3,2))
+            n = range(max(1,n-2),max(n+3,2))
 
         w = 1e308
         for i in n:
@@ -166,13 +166,13 @@
     n = int(float(hi-t)/grid+0.1)+1
     if split:
         labels = []
-        for i in xrange(n):
+        for i in range(n):
             v = t+grid*i
             T.append(v)
             labels.append(format % (v+labelVOffset))
         return T, labels
     else:
-        for i in xrange(n):
+        for i in range(n):
             v = t+grid*i
             T.append((v, format % (v+labelVOffset)))
         return T
@@ -189,7 +189,7 @@
             l -= 1
         l+=1
         if b or l: data = data[b:l]
-        I = [i for i in xrange(len(data)) if data[i] is None]
+        I = [i for i in range(len(data)) if data[i] is None]
         for i in I:
             data[i] = 0.5*(data[i-1]+data[i+1])
         return b, l, data
@@ -206,7 +206,7 @@
 
 def maverage(data,n=6):
     data = (n-1)*[data[0]]+data
-    data = [float(sum(data[i-n:i]))/n for i in xrange(n,len(data)+1)]
+    data = [float(sum(data[i-n:i]))/n for i in range(n,len(data)+1)]
     return data
 
 def pairMaverage(data,n=6):
@@ -279,7 +279,7 @@
             p = [(x[1],x[2]) for x in p]
         else:
             p = node.asPolygon().points
-            p = [(p[i],p[i+1]) for i in xrange(0,len(p),2)]
+            p = [(p[i],p[i+1]) for i in range(0,len(p),2)]
 
         D = kwds.copy()
         D['poly'] = self.transformAndFlatten(A,p)
@@ -298,14 +298,18 @@
         finally:
             f.close()
 
-def xyDist( (x0,y0),(x1,y1) ):
+def xyDist(xxx_todo_changeme, xxx_todo_changeme1 ):
     '''return distance between two points'''
+    (x0,y0) = xxx_todo_changeme
+    (x1,y1) = xxx_todo_changeme1
     return hypot((x1-x0),(y1-y0))
 
-def lineSegmentIntersect(
-                (x00,y00),(x01,y01),
-                (x10,y10),(x11,y11)
+def lineSegmentIntersect(xxx_todo_changeme2, xxx_todo_changeme3, xxx_todo_changeme4, xxx_todo_changeme5
                 ):
+    (x00,y00) = xxx_todo_changeme2
+    (x01,y01) = xxx_todo_changeme3
+    (x10,y10) = xxx_todo_changeme4
+    (x11,y11) = xxx_todo_changeme5
     p = x00,y00
     r = x01-x00,y01-y00
 
@@ -373,7 +377,7 @@
             self.store = self._changer(obj)
             assert isinstance(self.store,dict), '%s.changer should return a dict of changed attributes' % self.__class__.__name__
         elif self.store is not None:
-            for a,v in self.store.iteritems():
+            for a,v in self.store.items():
                 setattr(obj,a,v)
             self.store = None
 
--- a/src/reportlab/graphics/charts/utils3d.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/charts/utils3d.py	Tue Apr 30 14:20:22 2013 +0100
@@ -83,7 +83,7 @@
             dy = float(y1-y0)/n
             D = []
             a = D.append
-            for i in xrange(1,n):
+            for i in range(1,n):
                 a((x0+dx*i,y0+dy*i))
 
     a = G.add
@@ -199,20 +199,20 @@
     #find all line segments
     S = []
     a = S.append
-    for s in xrange(len(data)):
+    for s in range(len(data)):
         ds = data[s]
         if not ds: continue
         n = len(ds)
         if n==1: continue
-        for i in xrange(1,n):
+        for i in range(1,n):
             seg = _Segment(s,i,data)
             if seg.a+abs(seg.b)>=small: a(seg)
     S.sort(_segCmp)
     I = []
     n = len(S)
-    for i in xrange(0,n-1):
+    for i in range(0,n-1):
         s = S[i]
-        for j in xrange(i+1,n):
+        for j in range(i+1,n):
             if s.intersect(S[j],I)==1: break
     I.sort()
     return I
@@ -226,8 +226,8 @@
 
     D.save(formats=['pdf'],outDir='.',fnRoot='_draw_3d_bar')
 
-    print find_intersections([[(0,0.5),(1,0.5),(0.5,0),(0.5,1)],[(.2666666667,0.4),(0.1,0.4),(0.1,0.2),(0,0),(1,1)],[(0,1),(0.4,0.1),(1,0.1)]])
-    print find_intersections([[(0.1, 0.2), (0.1, 0.4)], [(0, 1), (0.4, 0.1)]])
-    print find_intersections([[(0.2, 0.4), (0.1, 0.4)], [(0.1, 0.8), (0.4, 0.1)]])
-    print find_intersections([[(0,0),(1,1)],[(0.4,0.1),(1,0.1)]])
-    print find_intersections([[(0,0.5),(1,0.5),(0.5,0),(0.5,1)],[(0,0),(1,1)],[(0.1,0.8),(0.4,0.1),(1,0.1)]])
+    print(find_intersections([[(0,0.5),(1,0.5),(0.5,0),(0.5,1)],[(.2666666667,0.4),(0.1,0.4),(0.1,0.2),(0,0),(1,1)],[(0,1),(0.4,0.1),(1,0.1)]]))
+    print(find_intersections([[(0.1, 0.2), (0.1, 0.4)], [(0, 1), (0.4, 0.1)]]))
+    print(find_intersections([[(0.2, 0.4), (0.1, 0.4)], [(0.1, 0.8), (0.4, 0.1)]]))
+    print(find_intersections([[(0,0),(1,1)],[(0.4,0.1),(1,0.1)]]))
+    print(find_intersections([[(0,0.5),(1,0.5),(0.5,0),(0.5,1)],[(0,0),(1,1)],[(0.1,0.8),(0.4,0.1),(1,0.1)]]))
--- a/src/reportlab/graphics/renderPDF.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/renderPDF.py	Tue Apr 30 14:20:22 2013 +0100
@@ -20,7 +20,7 @@
 from reportlab.pdfbase.pdfmetrics import stringWidth
 from reportlab.lib.utils import getStringIO
 from reportlab import rl_config
-from renderbase import Renderer, StateTracker, getStateDelta, renderScaledDrawing
+from .renderbase import Renderer, StateTracker, getStateDelta, renderScaledDrawing
 
 # the main entry point for users...
 def draw(drawing, canvas, x, y, showBoundary=rl_config._unset_):
@@ -165,7 +165,7 @@
                 elif text_anchor=='numeric':
                     x -= numericXShift(text_anchor,text,textLen,font,font_size,enc)
                 else:
-                    raise ValueError, 'bad value for textAnchor '+str(text_anchor)
+                    raise ValueError('bad value for textAnchor '+str(text_anchor))
             t = self._canvas.beginText(x,y)
             t.textLine(text)
             self._canvas.drawText(t)
@@ -195,7 +195,7 @@
     def applyStateChanges(self, delta, newState):
         """This takes a set of states, and outputs the PDF operators
         needed to set those properties"""
-        for key, value in delta.items():
+        for key, value in list(delta.items()):
             if key == 'transform':
                 self._canvas.transform(value[0], value[1], value[2],
                                  value[3], value[4], value[5])
@@ -356,7 +356,7 @@
     if y!=740: c.showPage()
 
     c.save()
-    print 'saved renderPDF.pdf'
+    print('saved renderPDF.pdf')
 
 ##def testFlowable():
 ##    """Makes a platypus document"""
--- a/src/reportlab/graphics/renderPM.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/renderPM.py	Tue Apr 30 14:20:22 2013 +0100
@@ -26,10 +26,10 @@
 
 try:
     import _renderPM
-except ImportError, errMsg:
-    raise ImportError, "No module named _renderPM\n" + \
+except ImportError as errMsg:
+    raise ImportError("No module named _renderPM\n" + \
         (str(errMsg)!='No module named _renderPM' and "it may be the wrong version or badly installed!" or
-                                    "see https://www.reportlab.com/software/opensource/rl-addons/")
+                                    "see https://www.reportlab.com/software/opensource/rl-addons/"))
 
 def _getImage():
     try:
@@ -124,7 +124,7 @@
 
     def drawImage(self, image):
         path = image.path
-        if isinstance(path,basestring):
+        if isinstance(path,str):
             if not (path and os.path.isfile(path)): return
             im = _getImage().open(path).convert('RGB')
         elif hasattr(path,'convert'):
@@ -186,7 +186,7 @@
                 elif text_anchor=='numeric':
                     x -= numericXShift(text_anchor,text,textLen,fontName,fontSize,stringObj.encoding)
                 else:
-                    raise ValueError, 'bad value for textAnchor '+str(text_anchor)
+                    raise ValueError('bad value for textAnchor '+str(text_anchor))
             canv.drawString(x,y,text,_fontInfo=(fontName,fontSize))
 
     def drawPath(self, path):
@@ -216,7 +216,7 @@
 def _setFont(gs,fontName,fontSize):
     try:
         gs.setFont(fontName,fontSize)
-    except _renderPM.Error, errMsg:
+    except _renderPM.Error as errMsg:
         if errMsg.args[0]!="Can't find font!": raise
         #here's where we try to add a font to the canvas
         try:
@@ -226,8 +226,8 @@
             else:
                 _renderPM.makeT1Font(fontName,f.face.findT1File(),f.encoding.vector,open_and_read)
         except:
-            s1, s2 = map(str,sys.exc_info()[:2])
-            raise RenderPMError, "Can't setFont(%s) missing the T1 files?\nOriginally %s: %s" % (fontName,s1,s2)
+            s1, s2 = list(map(str,sys.exc_info()[:2]))
+            raise RenderPMError("Can't setFont(%s) missing the T1 files?\nOriginally %s: %s" % (fontName,s1,s2))
         gs.setFont(fontName,fontSize)
 
 def _convert2pilp(im):
@@ -274,11 +274,11 @@
         A = {'ctm':None, 'strokeWidth':None, 'strokeColor':None, 'lineCap':None, 'lineJoin':None, 'dashArray':None, 'fillColor':None}
         gs = self._gs
         fN,fS = gs.fontName, gs.fontSize
-        for k in A.keys():
+        for k in list(A.keys()):
             A[k] = getattr(gs,k)
         del gs, self._gs
         gs = self.__dict__['_gs'] = _renderPM.gstate(w,h,bg=bg)
-        for k in A.keys():
+        for k in list(A.keys()):
             setattr(self,k,A[k])
         gs.setFont(fN,fS)
 
@@ -291,7 +291,7 @@
         im = self.toPIL()
         if fmt is None:
             if type(fn) is not StringType:
-                raise ValueError, "Invalid type '%s' for fn when fmt is None" % type(fn)
+                raise ValueError("Invalid type '%s' for fn when fmt is None" % type(fn))
             fmt = os.path.splitext(fn)[1]
             if fmt.startswith('.'): fmt = fmt[1:]
         configPIL = self.configPIL or {}
@@ -328,7 +328,7 @@
         elif fmt in ('GIF',):
             pass
         else:
-            raise RenderPMError,"Unknown image kind %s" % fmt
+            raise RenderPMError("Unknown image kind %s" % fmt)
         if fmt=='TIFF':
             tc = configPIL.get('transparent',None)
             if tc:
@@ -489,14 +489,14 @@
             gfont = None
         font = getFont(fontName)
         if font._dynamicFont:
-            if isinstance(text,unicode): text = text.encode('utf8')
+            if isinstance(text,str): text = text.encode('utf8')
             gs.drawString(x,y,text)
         else:
             fc = font
-            if not isinstance(text,unicode):
+            if not isinstance(text,str):
                 try:
                     text = text.decode('utf8')
-                except UnicodeDecodeError,e:
+                except UnicodeDecodeError as e:
                     i,j = e.args[2:4]
                     raise UnicodeDecodeError(*(e.args[:4]+('%s\n%s-->%s<--%s' % (e.args[4],text[i-10:i],text[i:j],text[j:j+10]),)))
 
@@ -504,14 +504,14 @@
             n = len(FT)
             nm1 = n-1
             wscale = 0.001*fontSize
-            for i in xrange(n):
+            for i in range(n):
                 f, t = FT[i]
                 if f!=fc:
                     _setFont(gs,f.fontName,fontSize)
                     fc = f
                 gs.drawString(x,y,t)
                 if i!=nm1:
-                    x += wscale*sum(map(f.widths.__getitem__,map(ord,t)))
+                    x += wscale*sum(map(f.widths.__getitem__,list(map(ord,t))))
             if font!=fc:
                 _setFont(gs,fontName,fontSize)
 
@@ -728,9 +728,9 @@
                     html.append('<a href="%s">python source</a><br>\n' % filename)
                 elif k=='svg':
                     html.append('<a href="%s">SVG</a><br>\n' % filename)
-                if verbose: print 'wrote',fullpath
+                if verbose: print('wrote',fullpath)
             except AttributeError:
-                print 'Problem drawing %s file'%k
+                print('Problem drawing %s file'%k)
                 raise
         if os.environ.get('RL_NOEPSPREVIEW','0')=='1': drawing.__dict__['preview'] = 0
         drawing.save(formats=['eps','pdf'],outDir='pmout',fnRoot=fnRoot)
@@ -740,7 +740,7 @@
     if sys.platform=='mac':
         from reportlab.lib.utils import markfilename
         markfilename(htmlFileName,ext='HTML')
-    if verbose: print 'wrote %s' % htmlFileName
+    if verbose: print('wrote %s' % htmlFileName)
 
 if __name__=='__main__':
     test()
--- a/src/reportlab/graphics/renderPS.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/renderPS.py	Tue Apr 30 14:20:22 2013 +0100
@@ -15,7 +15,7 @@
 from operator import getitem
 from reportlab import rl_config
 _ESCAPEDICT={}
-for c in xrange(256):
+for c in range(256):
     if c<32 or c>=127:
         _ESCAPEDICT[chr(c)]= '\\%03o' % c
     elif c in (ord('\\'),ord('('),ord(')')):
@@ -243,10 +243,10 @@
         fontSize = self._fontSize
         fontsUsed = self._fontsUsed
         escape = self._escape
-        if not isinstance(s,unicode):
+        if not isinstance(s,str):
             try:
                 s = s.decode('utf8')
-            except UnicodeDecodeError,e:
+            except UnicodeDecodeError as e:
                 i,j = e.args[2:4]
                 raise UnicodeDecodeError(*(e.args[:4]+('%s\n%s-->%s<--%s' % (e.args[4],s[i-10:i],s[i:j],s[j:j+10]),)))
 
@@ -491,7 +491,7 @@
                     a("%s l" % fp_str(args[:2]))
                 a("%s curveto" % fp_str(args[2:]))
             else:
-                raise TypeError, "unknown figure operator: "+op
+                raise TypeError("unknown figure operator: "+op)
 
         if closed:
             a("closepath")
@@ -673,7 +673,7 @@
     from reportlab.graphics import renderPS
     renderPS.draw(drawing, canvas, x, y)
 Execute the script to see some test drawings."""
-from shapes import *
+from .shapes import *
 
 # hack so we only get warnings once each
 #warnOnce = WarnOnce()
@@ -691,7 +691,7 @@
     '''
     P=[]
     a = P.append
-    for i in xrange(0,len(L),2):
+    for i in range(0,len(L),2):
         a((L[i],L[i+1]))
     return P
 
@@ -726,7 +726,7 @@
         self._canvas._color = color
 
         #restore things we might have lost (without actually doing anything).
-        for k, v in rDeltas.items():
+        for k, v in list(rDeltas.items()):
             if k in self._restores:
                 setattr(self._canvas,self._restores[k],v)
 
@@ -801,7 +801,7 @@
                 elif text_anchor=='numeric':
                     x -= numericXShift(text_anchor,text,textLen,font,fontSize,encoding='winansi')
                 else:
-                    raise ValueError, 'bad value for text_anchor '+str(text_anchor)
+                    raise ValueError('bad value for text_anchor '+str(text_anchor))
             self._canvas.drawString(x,y,text)
 
     def drawPath(self, path):
@@ -816,7 +816,7 @@
     def applyStateChanges(self, delta, newState):
         """This takes a set of states, and outputs the operators
         needed to set those properties"""
-        for key, value in delta.items():
+        for key, value in list(delta.items()):
             if key == 'transform':
                 self._canvas.transform(value[0], value[1], value[2],
                                  value[3], value[4], value[5])
@@ -896,7 +896,7 @@
     if not os.path.isdir(outdir):
         os.mkdir(outdir)
     #grab all drawings from the test module
-    import testshapes
+    from . import testshapes
     drawings = []
 
     for funcname in dir(testshapes):
@@ -911,7 +911,7 @@
     for (d, docstring) in drawings:
         filename = outdir + os.sep + 'renderPS_%d.eps'%i
         drawToFile(d,filename)
-        print 'saved', filename
+        print('saved', filename)
         i = i + 1
 
 if __name__=='__main__':
--- a/src/reportlab/graphics/renderSVG.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/renderSVG.py	Tue Apr 30 14:20:22 2013 +0100
@@ -83,7 +83,7 @@
     """
 
     newNode = doc.createElement(newTag)
-    for newAttr, attr in attrDict.items():
+    for newAttr, attr in list(attrDict.items()):
         sattr =  str(attr)
         if not node:
             newNode.setAttribute(newAttr, sattr)
@@ -114,7 +114,7 @@
             self.write(self.BOMS[encoding])
 
     def write(self,s):
-        if isinstance(s,unicode):
+        if isinstance(s,str):
             s = s.encode(self.encoding)
         elif isinstance(s,str):
             try:
@@ -194,7 +194,7 @@
                     )
         svgAttrs["xmlns:xlink"] = "http://www.w3.org/1999/xlink"
         svgAttrs.update(kwds.pop('svgAttrs',{}))
-        for k,v in svgAttrs.iteritems():
+        for k,v in svgAttrs.items():
             self.svg.setAttribute(k,v)
 
         title = self.doc.createElement('title')
@@ -242,7 +242,7 @@
         writer = EncodedWriter(self.encoding,bom=self.bom)
         self.doc.writexml(writer,addindent="\t",newl="\n",encoding=self.encoding)
 
-        if type(fn) in types.StringTypes:
+        if type(fn) in str:
             f = open(fn, 'w')
         else:
             f = fn
@@ -268,7 +268,7 @@
     def _formatStyle(self, include=[], exclude='',**kwds):
         style = self.style.copy()
         style.update(kwds)
-        keys = style.keys()
+        keys = list(style.keys())
         if include:
             keys = [k for k in keys if k in include]
         if exclude:
@@ -387,9 +387,9 @@
                     del style[k]
             svgAttrs = self.fontHacks[font] if font in self.fontHacks else {}
             if isinstance(font,RLString):
-                svgAttrs.update(font.svgAttrs.iteritems())
+                svgAttrs.update(iter(font.svgAttrs.items()))
             if svgAttrs:
-                for k,v in svgAttrs.iteritems():
+                for k,v in svgAttrs.items():
                     a = 'font-'+k
                     if a in TEXT_STYLES:
                         style[a] = v
@@ -407,7 +407,7 @@
     def rect(self, x1,y1, x2,y2, rx=8, ry=8, link_info=None, **_svgAttrs):
         "Draw a rectangle between x1,y1 and x2,y2."
 
-        if self.verbose: print "+++ SVGCanvas.rect"
+        if self.verbose: print("+++ SVGCanvas.rect")
 
         x = min(x1,x2)
         y = min(y1,y2)
@@ -439,7 +439,7 @@
         self.currGroup.appendChild(rect)
 
     def drawString(self, s, x, y, angle=0, link_info=None,**_svgAttrs):
-        if self.verbose: print "+++ SVGCanvas.drawString"
+        if self.verbose: print("+++ SVGCanvas.drawString")
 
         if self._fillColor != None:
             self.setColor(self._fillColor)
@@ -462,7 +462,7 @@
             self.currGroup.appendChild(text)
 
     def drawCentredString(self, s, x, y, angle=0, text_anchor='middle', link_info=None):
-        if self.verbose: print "+++ SVGCanvas.drawCentredString"
+        if self.verbose: print("+++ SVGCanvas.drawCentredString")
 
         if self._fillColor != None:
             if not text_anchor in ['start', 'inherited']:
@@ -474,7 +474,7 @@
                 elif text_anchor=='numeric':
                     x -= numericXShift(text_anchor,s,textLen,self._font,self._fontSize)
                 else:
-                    raise ValueError, 'bad value for text_anchor ' + str(text_anchor)
+                    raise ValueError('bad value for text_anchor ' + str(text_anchor))
         self.drawString(x,y,text,angle=angle, link_info=link_info)
 
     def drawRightString(self, text, x, y, angle=0, link_info=None):
@@ -580,7 +580,7 @@
         if self._strokeColor != None:
             self.setColor(self._strokeColor)
             pairs = []
-            for i in xrange(len(points)):
+            for i in range(len(points)):
                 pairs.append("%f %f" % (points[i]))
             pts = ', '.join(pairs)
             polyline = transformNode(self.doc, "polygon",
@@ -609,7 +609,7 @@
         if self._strokeColor != None:
             self.setColor(self._strokeColor)
             pairs = []
-            for i in xrange(len(points)):
+            for i in range(len(points)):
                 pairs.append("%f %f" % (points[i]))
             pts = ', '.join(pairs)
             polyline = transformNode(self.doc, "polyline",
@@ -618,20 +618,20 @@
 
     ### groups ###
     def startGroup(self):
-        if self.verbose: print "+++ begin SVGCanvas.startGroup"
+        if self.verbose: print("+++ begin SVGCanvas.startGroup")
         currGroup, group = self.currGroup, transformNode(self.doc, "g", transform="")
         currGroup.appendChild(group)
         self.currGroup = group
-        if self.verbose: print "+++ end SVGCanvas.startGroup"
+        if self.verbose: print("+++ end SVGCanvas.startGroup")
         return currGroup
 
     def endGroup(self,currGroup):
-        if self.verbose: print "+++ begin SVGCanvas.endGroup"
+        if self.verbose: print("+++ begin SVGCanvas.endGroup")
         self.currGroup = currGroup
-        if self.verbose: print "+++ end SVGCanvas.endGroup"
+        if self.verbose: print("+++ end SVGCanvas.endGroup")
 
     def transform(self, a, b, c, d, e, f):
-        if self.verbose: print "!!! begin SVGCanvas.transform", a, b, c, d, e, f
+        if self.verbose: print("!!! begin SVGCanvas.transform", a, b, c, d, e, f)
         tr = self.currGroup.getAttribute("transform")
         t = 'matrix(%f, %f, %f, %f, %f, %f)' % (a,b,c,d,e,f)
         if (a, b, c, d, e, f) != (1, 0, 0, 1, 0, 0):
@@ -639,7 +639,7 @@
 
     def translate(self, x, y):
         # probably never used
-        print "!!! begin SVGCanvas.translate"
+        print("!!! begin SVGCanvas.translate")
         return
 
         tr = self.currGroup.getAttribute("transform")
@@ -648,7 +648,7 @@
 
     def scale(self, x, y):
         # probably never used
-        print "!!! begin SVGCanvas.scale"
+        print("!!! begin SVGCanvas.scale")
         return
 
         tr = self.groups[-1].getAttribute("transform")
@@ -686,7 +686,7 @@
         """This is the recursive method called for each node in the tree.
         """
 
-        if self.verbose: print "### begin _SVGRenderer.drawNode(%r)" % node
+        if self.verbose: print("### begin _SVGRenderer.drawNode(%r)" % node)
 
         self._canvas.comment('begin node %r'%node)
         color = self._canvas._color
@@ -709,12 +709,12 @@
         self._canvas._color = color
 
         #restore things we might have lost (without actually doing anything).
-        for k, v in rDeltas.items():
+        for k, v in list(rDeltas.items()):
             if k in self._restores:
                 setattr(self._canvas,self._restores[k],v)
         self._canvas.style = style
 
-        if self.verbose: print "### end _SVGRenderer.drawNode(%r)" % node
+        if self.verbose: print("### end _SVGRenderer.drawNode(%r)" % node)
 
     _restores = {'strokeColor':'_strokeColor','strokeWidth': '_lineWidth','strokeLineCap':'_lineCap',
                 'strokeLineJoin':'_lineJoin','fillColor':'_fillColor','fontName':'_font',
@@ -752,7 +752,7 @@
             return None
 
     def drawGroup(self, group):
-        if self.verbose: print "### begin _SVGRenderer.drawGroup"
+        if self.verbose: print("### begin _SVGRenderer.drawGroup")
 
         currGroup = self._canvas.startGroup()
         a, b, c, d, e, f = self._tracker.getState()['transform']
@@ -765,7 +765,7 @@
         self._canvas.transform(a, b, c, d, e, f)
         self._canvas.endGroup(currGroup)
 
-        if self.verbose: print "### end _SVGRenderer.drawGroup"
+        if self.verbose: print("### end _SVGRenderer.drawGroup")
 
     def drawRect(self, rect):
         link_info = self._get_link_info_dict(rect)
@@ -798,7 +798,7 @@
                 elif text_anchor=='numeric':
                     x -= numericXShift(text_anchor,text,textLen,font,fontSize)
                 else:
-                    raise ValueError, 'bad value for text_anchor ' + str(text_anchor)
+                    raise ValueError('bad value for text_anchor ' + str(text_anchor))
             self._canvas.drawString(text,x,y,link_info=self._get_link_info_dict(stringObj),**getattr(stringObj,'_svgAttrs',{}))
 
     def drawLine(self, line):
@@ -850,7 +850,7 @@
         """This takes a set of states, and outputs the operators
         needed to set those properties"""
 
-        for key, value in delta.items():
+        for key, value in list(delta.items()):
             if key == 'transform':
                 pass
                 #self._canvas.transform(value[0], value[1], value[2], value[3], value[4], value[5])
--- a/src/reportlab/graphics/renderbase.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/renderbase.py	Tue Apr 30 14:20:22 2013 +0100
@@ -37,7 +37,7 @@
     to set the pen color to red in between. Returns the effect
     the given shape would have on the graphics state"""
     delta = {}
-    for (prop, value) in shape.getProperties().items():
+    for (prop, value) in list(shape.getProperties().items()):
         if prop in STATE_DEFAULTS:
             delta[prop] = value
     return delta
@@ -72,7 +72,7 @@
         through getState()"""
 
         newstate = self._combined[-1].copy()
-        for (key, value) in delta.items():
+        for (key, value) in list(delta.items()):
             if key == 'transform':  #do cumulative matrix
                 newstate['transform'] = delta['transform']
                 newstate['ctm'] = mmult(self._combined[-1]['ctm'], delta['transform'])
@@ -97,7 +97,7 @@
         #need to diff this against the last one in the state
         reverseDelta = {}
         #print 'pop()...'
-        for key, curValue in lastDelta.items():
+        for key, curValue in list(lastDelta.items()):
             #print '   key=%s, value=%s' % (key, curValue)
             prevValue = newState[key]
             if prevValue != curValue:
@@ -125,7 +125,7 @@
         self._combined[-1][key] = value
 
 def testStateTracker():
-    print 'Testing state tracker'
+    print('Testing state tracker')
     defaults = {'fillColor':None, 'strokeColor':None,'fontName':None, 'transform':[1,0,0,1,0,0]}
     from reportlab.graphics.shapes import _baseGFontName
     deltas = [
@@ -137,16 +137,16 @@
         ]
 
     st = StateTracker(defaults)
-    print 'initial:', st.getState()
-    print
+    print('initial:', st.getState())
+    print()
     for delta in deltas:
-        print 'pushing:', delta
+        print('pushing:', delta)
         st.push(delta)
-        print 'state:  ',st.getState(),'\n'
+        print('state:  ',st.getState(),'\n')
 
     for delta in deltas:
-        print 'popping:',st.pop()
-        print 'state:  ',st.getState(),'\n'
+        print('popping:',st.pop())
+        print('state:  ',st.getState(),'\n')
 
 
 def _expandUserNode(node,canvas):
@@ -181,7 +181,7 @@
         self._nodeStack = []   #track nodes visited
 
     def undefined(self, operation):
-        raise ValueError, "%s operation not defined at superclass class=%s" %(operation, self.__class__)
+        raise ValueError("%s operation not defined at superclass class=%s" %(operation, self.__class__))
 
     def draw(self, drawing, canvas, x=0, y=0, showBoundary=rl_config._unset_):
         """This is the top level function, which draws the drawing at the given
@@ -230,7 +230,7 @@
         parent.
         
         """
-        for (key, value) in node.__dict__.items():
+        for (key, value) in list(node.__dict__.items()):
             if isinstance(value, DerivedValue):
                 #just replace with default for key?
                 #print '    fillDerivedValues(%s)' % key
@@ -281,7 +281,7 @@
             elif isinstance(node, Wedge):
                 self.drawWedge(node)
             else:
-                print 'DrawingError','Unexpected element %s in drawing!' % str(node)
+                print('DrawingError','Unexpected element %s in drawing!' % str(node))
         finally:
             if not ocanvas: del node._canvas
 
@@ -350,5 +350,5 @@
         self.undefined("applyStateChanges")
 
 if __name__=='__main__':
-    print "this file has no script interpretation"
-    print __doc__
+    print("this file has no script interpretation")
+    print(__doc__)
--- a/src/reportlab/graphics/samples/bubble.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/bubble.py	Tue Apr 30 14:20:22 2013 +0100
@@ -3,7 +3,7 @@
 from reportlab.graphics.charts.lineplots import ScatterPlot
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
-from excelcolors import *
+from .excelcolors import *
 
 class Bubble(_DrawingEditorMixin,Drawing):
     def __init__(self,width=200,height=150,*args,**kw):
--- a/src/reportlab/graphics/samples/clustered_bar.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/clustered_bar.py	Tue Apr 30 14:20:22 2013 +0100
@@ -1,6 +1,6 @@
 #Autogenerated by ReportLab guiedit do not edit
 from reportlab.graphics.charts.legends import Legend
-from excelcolors import *
+from .excelcolors import *
 from reportlab.graphics.charts.barcharts import HorizontalBarChart
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
--- a/src/reportlab/graphics/samples/clustered_column.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/clustered_column.py	Tue Apr 30 14:20:22 2013 +0100
@@ -1,6 +1,6 @@
 #Autogenerated by ReportLab guiedit do not edit
 from reportlab.graphics.charts.legends import Legend
-from excelcolors import *
+from .excelcolors import *
 from reportlab.graphics.charts.barcharts import VerticalBarChart
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
--- a/src/reportlab/graphics/samples/exploded_pie.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/exploded_pie.py	Tue Apr 30 14:20:22 2013 +0100
@@ -1,6 +1,6 @@
 #Autogenerated by ReportLab guiedit do not edit
 from reportlab.graphics.charts.piecharts import Pie
-from excelcolors import *
+from .excelcolors import *
 from reportlab.graphics.widgets.grids import ShadedRect
 from reportlab.graphics.charts.legends import Legend
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
--- a/src/reportlab/graphics/samples/filled_radar.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/filled_radar.py	Tue Apr 30 14:20:22 2013 +0100
@@ -3,7 +3,7 @@
 from reportlab.graphics.charts.spider import SpiderChart
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
-from excelcolors import *
+from .excelcolors import *
 
 class FilledRadarChart(_DrawingEditorMixin,Drawing):
     def __init__(self,width=200,height=150,*args,**kw):
--- a/src/reportlab/graphics/samples/line_chart.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/line_chart.py	Tue Apr 30 14:20:22 2013 +0100
@@ -3,7 +3,7 @@
 from reportlab.graphics.charts.lineplots import LinePlot
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
-from excelcolors import *
+from .excelcolors import *
 
 class LineChart(_DrawingEditorMixin,Drawing):
     def __init__(self,width=200,height=150,*args,**kw):
--- a/src/reportlab/graphics/samples/linechart_with_markers.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/linechart_with_markers.py	Tue Apr 30 14:20:22 2013 +0100
@@ -4,7 +4,7 @@
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.widgets.markers import makeMarker
 from reportlab.graphics.charts.textlabels import Label
-from excelcolors import *
+from .excelcolors import *
 
 class LineChartWithMarkers(_DrawingEditorMixin,Drawing):
     def __init__(self,width=200,height=150,*args,**kw):
--- a/src/reportlab/graphics/samples/radar.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/radar.py	Tue Apr 30 14:20:22 2013 +0100
@@ -1,6 +1,6 @@
 #Autogenerated by ReportLab guiedit do not edit
 from reportlab.graphics.charts.legends import Legend
-from excelcolors import *
+from .excelcolors import *
 from reportlab.graphics.charts.spider import SpiderChart
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
--- a/src/reportlab/graphics/samples/runall.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/runall.py	Tue Apr 30 14:20:22 2013 +0100
@@ -7,7 +7,7 @@
 import types
 
 def moduleClasses(mod):
-    def P(obj, m=mod.__name__, CT=types.ClassType):
+    def P(obj, m=mod.__name__, CT=type):
         return (type(obj)==CT and obj.__module__==m)
     try:
         return inspect.getmembers(mod, P)[0][1]
@@ -27,15 +27,15 @@
         f = string.split(fn, '.')[0]
         c = getclass(f)
         if c != None:
-            print c.__name__
+            print(c.__name__)
             try:
                 for fmt in formats:
                     if fmt:
                         c().save(formats=[fmt],outDir='.',fnRoot=c.__name__)
                         if VERBOSE:
-                            print "  %s.%s" % (c.__name__, fmt)
+                            print("  %s.%s" % (c.__name__, fmt))
             except:
-                print "  COULDN'T CREATE '%s.%s'!" % (c.__name__, format)
+                print("  COULDN'T CREATE '%s.%s'!" % (c.__name__, format))
 
 if __name__ == "__main__":
     if len(sys.argv) == 1:
@@ -43,17 +43,17 @@
     else:
         try:
             if sys.argv[1] == "-h":
-                print 'usage: runall.py [FORMAT] [-h]'
-                print '   if format is supplied is should be one or more of pdf,gif,eps,png etc'
-                print '   if format is missing the following formats are assumed: pdf,pict,png'
-                print '   -h prints this message'
+                print('usage: runall.py [FORMAT] [-h]')
+                print('   if format is supplied is should be one or more of pdf,gif,eps,png etc')
+                print('   if format is missing the following formats are assumed: pdf,pict,png')
+                print('   -h prints this message')
             else:
                 t = sys.argv[1:]
                 for f in t:
                     run(f)
         except:
-            print 'usage: runall.py [FORMAT][-h]'
-            print '   if format is supplied is should be one or more of pdf,gif,eps,png etc'
-            print '   if format is missing the following formats are assumed: pdf,pict,png'
-            print '   -h prints this message'
+            print('usage: runall.py [FORMAT][-h]')
+            print('   if format is supplied is should be one or more of pdf,gif,eps,png etc')
+            print('   if format is missing the following formats are assumed: pdf,pict,png')
+            print('   -h prints this message')
             raise
--- a/src/reportlab/graphics/samples/scatter.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/scatter.py	Tue Apr 30 14:20:22 2013 +0100
@@ -3,7 +3,7 @@
 from reportlab.graphics.charts.lineplots import ScatterPlot
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
-from excelcolors import *
+from .excelcolors import *
 
 class Scatter(_DrawingEditorMixin,Drawing):
     def __init__(self,width=200,height=150,*args,**kw):
--- a/src/reportlab/graphics/samples/scatter_lines.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/scatter_lines.py	Tue Apr 30 14:20:22 2013 +0100
@@ -3,7 +3,7 @@
 from reportlab.graphics.charts.lineplots import ScatterPlot
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
-from excelcolors import *
+from .excelcolors import *
 
 class ScatterLines(_DrawingEditorMixin,Drawing):
     def __init__(self,width=200,height=150,*args,**kw):
--- a/src/reportlab/graphics/samples/scatter_lines_markers.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/scatter_lines_markers.py	Tue Apr 30 14:20:22 2013 +0100
@@ -3,7 +3,7 @@
 from reportlab.graphics.charts.lineplots import ScatterPlot
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
-from excelcolors import *
+from .excelcolors import *
 
 class ScatterLinesMarkers(_DrawingEditorMixin,Drawing):
     def __init__(self,width=200,height=150,*args,**kw):
--- a/src/reportlab/graphics/samples/simple_pie.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/simple_pie.py	Tue Apr 30 14:20:22 2013 +0100
@@ -4,7 +4,7 @@
 from reportlab.graphics.charts.legends import Legend
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
-from excelcolors import *
+from .excelcolors import *
 
 class SimplePie(_DrawingEditorMixin,Drawing):
     def __init__(self,width=200,height=150,*args,**kw):
--- a/src/reportlab/graphics/samples/stacked_bar.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/stacked_bar.py	Tue Apr 30 14:20:22 2013 +0100
@@ -3,7 +3,7 @@
 from reportlab.graphics.charts.barcharts import HorizontalBarChart
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
-from excelcolors import *
+from .excelcolors import *
 
 class StackedBar(_DrawingEditorMixin,Drawing):
     def __init__(self,width=200,height=150,*args,**kw):
--- a/src/reportlab/graphics/samples/stacked_column.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/samples/stacked_column.py	Tue Apr 30 14:20:22 2013 +0100
@@ -3,7 +3,7 @@
 from reportlab.graphics.charts.barcharts import VerticalBarChart
 from reportlab.graphics.shapes import Drawing, _DrawingEditorMixin, String
 from reportlab.graphics.charts.textlabels import Label
-from excelcolors import *
+from .excelcolors import *
 
 class StackedColumn(_DrawingEditorMixin,Drawing):
     def __init__(self,width=200,height=150,*args,**kw):
--- a/src/reportlab/graphics/shapes.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/shapes.py	Tue Apr 30 14:20:22 2013 +0100
@@ -120,10 +120,10 @@
     return (A[0]*v[0]+A[2]*v[1]+A[4],A[1]*v[0]+A[3]*v[1]+A[5])
 
 def transformPoints(matrix, V):
-    return map(transformPoint, V)
+    return list(map(transformPoint, V))
 
 def zTransformPoints(matrix, V):
-    return map(lambda x,matrix=matrix: zTransformPoint(matrix,x), V)
+    return list(map(lambda x,matrix=matrix: zTransformPoint(matrix,x), V))
 
 def _textBoxLimits(text, font, fontSize, leading, textAnchor, boxAnchor):
     w = 0
@@ -165,8 +165,8 @@
     return the corner points and the min max points in the original space
     '''
     C = zTransformPoints(rotate(angle),((x,y),(x+w,y),(x+w,y+h),(x,y+h)))
-    X = map(lambda x: x[0], C)
-    Y = map(lambda x: x[1], C)
+    X = [x[0] for x in C]
+    Y = [x[1] for x in C]
     return min(X), max(X), min(Y), max(Y), C
 
 
@@ -183,7 +183,7 @@
 class _SetKeyWordArgs:
     def __init__(self, keywords={}):
         """In general properties may be supplied to the constructor."""
-        for key, value in keywords.items():
+        for key, value in list(keywords.items()):
             setattr(self, key, value)
 
 
@@ -195,7 +195,7 @@
 
 def getRectsBounds(rectList):
     # filter out any None objects, e.g. empty groups
-    L = filter(lambda x: x is not None, rectList)
+    L = [x for x in rectList if x is not None]
     if not L: return None
 
     xMin, yMin, xMax, yMax = L[0]
@@ -266,16 +266,16 @@
 def getPathBounds(points):
     n = len(points)
     f = lambda i,p = points: p[i]
-    xs = map(f,xrange(0,n,2))
-    ys = map(f,xrange(1,n,2))
+    xs = list(map(f,range(0,n,2)))
+    ys = list(map(f,range(1,n,2)))
     return (min(xs), min(ys), max(xs), max(ys))
 
 def getPointsBounds(pointList):
     "Helper function for list of points"
     first = pointList[0]
     if type(first) in (ListType, TupleType):
-        xs = map(lambda xy: xy[0],pointList)
-        ys = map(lambda xy: xy[1],pointList)
+        xs = [xy[0] for xy in pointList]
+        ys = [xy[1] for xy in pointList]
         return (min(xs), min(ys), max(xs), max(ys))
     else:
         return getPathBounds(pointList)
@@ -298,7 +298,7 @@
         """Return a clone of this shape."""
 
         # implement this in the descendants as they need the right init methods.
-        raise NotImplementedError, "No copy method implemented for %s" % self.__class__.__name__
+        raise NotImplementedError("No copy method implemented for %s" % self.__class__.__name__)
 
     def getProperties(self,recur=1):
         """Interface to make it easy to extract automatic
@@ -308,7 +308,7 @@
         #for more complex objects like widgets you
         #may need to override this.
         props = {}
-        for key, value in self.__dict__.items():
+        for key, value in list(self.__dict__.items()):
             if key[0:1] != '_':
                 props[key] = value
         return props
@@ -325,12 +325,12 @@
         may provide a prefix - mostly helps to generate code
         samples for documentation."""
 
-        propList = self.getProperties().items()
+        propList = list(self.getProperties().items())
         propList.sort()
         if prefix:
             prefix = prefix + '.'
         for (name, value) in propList:
-            print '%s%s = %s' % (prefix, name, value)
+            print('%s%s = %s' % (prefix, name, value))
 
     def verify(self):
         """If the programmer has provided the optional
@@ -341,10 +341,10 @@
         an informative exception."""
 
         if self._attrMap is not None:
-            for key in self.__dict__.keys():
+            for key in list(self.__dict__.keys()):
                 if key[0] != '_':
                     assert key in self._attrMap, "Unexpected attribute %s found in %s" % (key, self)
-            for (attr, metavalue) in self._attrMap.items():
+            for (attr, metavalue) in list(self._attrMap.items()):
                 assert hasattr(self, attr), "Missing attribute %s from %s" % (attr, self)
                 value = getattr(self, attr)
                 assert metavalue.validate(value), "Invalid value %s for attribute %s in class %s" % (value, attr, self.__class__.__name__)
@@ -396,7 +396,7 @@
     def _addNamedNode(self,name,node):
         'if name is not None add an attribute pointing to node and add to the attrMap'
         if name:
-            if name not in self._attrMap.keys():
+            if name not in list(self._attrMap.keys()):
                 self._attrMap[name] = AttrMapValue(isValidChild)
             setattr(self, name, node)
 
@@ -473,8 +473,8 @@
     def _copyNamedContents(self,obj,aKeys=None,noCopy=('contents',)):
         from copy import copy
         self_contents = self.contents
-        if not aKeys: aKeys = self._attrMap.keys()
-        for (k, v) in self.__dict__.items():
+        if not aKeys: aKeys = list(self._attrMap.keys())
+        for (k, v) in list(self.__dict__.items()):
             if v in self_contents:
                 pos = self_contents.index(v)
                 setattr(obj, k, obj.contents[pos])
@@ -571,14 +571,14 @@
         if I: _addObjImport(self,I)
         if isinstance(self,Shape):
             from inspect import getargs
-            args, varargs, varkw = getargs(self.__init__.im_func.func_code)
+            args, varargs, varkw = getargs(self.__init__.__func__.__code__)
             P = self.getProperties()
             s = self.__class__.__name__+'('
             for n in args[1:]:
                 v = P[n]
                 del P[n]
                 s = s + '%s,' % _repr(v,I)
-            for n,v in P.items():
+            for n,v in list(P.items()):
                 v = P[n]
                 s = s + '%s=%s,' % (n, _repr(v,I))
             return s[:-1]+')'
@@ -617,7 +617,7 @@
     kw.update(self.__dict__)
     R = {}
     n = len(pfx)
-    for k in kw.keys():
+    for k in list(kw.keys()):
         if k.startswith(pfx):
             R[k[n:]] = kw[k]
     return R
@@ -661,7 +661,7 @@
         G = _renderGroupPy(self._explode(),'self',I)
         n = 'ExplodedDrawing_' + self.__class__.__name__
         s = '#Autogenerated by ReportLab guiedit do not edit\n'
-        for m, o in I.items():
+        for m, o in list(I.items()):
             s = s + 'from %s import %s\n' % (m,string.replace(str(o)[1:-1],"'",""))
         s = s + '\nclass %s(_DrawingEditorMixin,Drawing):\n' % n
         s = s + '\tdef __init__(self,width=%s,height=%s,*args,**kw):\n' % (self.width,self.height)
@@ -674,7 +674,7 @@
         """This is used by the Platypus framework to let the document
         draw itself in a story.  It is specific to PDF and should not
         be used directly."""
-        import renderPDF
+        from . import renderPDF
         renderPDF.draw(self, self.canv, 0, 0, showBoundary=showBoundary)
 
     def wrap(self, availWidth, availHeight):
@@ -725,7 +725,7 @@
             else:
                 try:
                     fnRoot = fnRoot % chartId
-                except TypeError, err:
+                except TypeError as err:
                     #the exact error message changed from 2.2 to 2.3 so we need to
                     #check a substring
                     if str(err).find('not all arguments converted') < 0: raise
@@ -750,7 +750,7 @@
         if 'pdf' in plotMode:
             from reportlab.graphics import renderPDF
             filename = fnroot+'.pdf'
-            if verbose: print genFmt % ('PDF',filename)
+            if verbose: print(genFmt % ('PDF',filename))
             renderPDF.drawToFile(self, filename, title, showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderPDF_',**kw))
             ext = ext +  '/.pdf'
             if sys.platform=='mac':
@@ -762,7 +762,7 @@
             if bmFmt in plotMode:
                 from reportlab.graphics import renderPM
                 filename = '%s.%s' % (fnroot,bmFmt)
-                if verbose: print genFmt % (bmFmt,filename)
+                if verbose: print(genFmt % (bmFmt,filename))
                 dtc = getattr(self,'_drawTimeCollector',None)
                 if dtc:
                     dtcfmts = getattr(dtc,'formats',[bmFmt])
@@ -780,7 +780,7 @@
             except ImportError:
                 from reportlab.graphics import renderPS
             filename = fnroot+'.eps'
-            if verbose: print genFmt % ('EPS',filename)
+            if verbose: print(genFmt % ('EPS',filename))
             renderPS.drawToFile(self,
                                 filename,
                                 title = fnroot,
@@ -795,7 +795,7 @@
         if 'svg' in plotMode:
             from reportlab.graphics import renderSVG
             filename = fnroot+'.svg'
-            if verbose: print genFmt % ('SVG',filename)
+            if verbose: print(genFmt % ('SVG',filename))
             renderSVG.drawToFile(self,
                                 filename,
                                 showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderSVG_',**kw))
@@ -804,13 +804,13 @@
         if 'ps' in plotMode:
             from reportlab.graphics import renderPS
             filename = fnroot+'.ps'
-            if verbose: print genFmt % ('EPS',filename)
+            if verbose: print(genFmt % ('EPS',filename))
             renderPS.drawToFile(self, filename, showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderPS_',**kw))
             ext = ext +  '/.ps'
 
         if 'py' in plotMode:
             filename = fnroot+'.py'
-            if verbose: print genFmt % ('py',filename)
+            if verbose: print(genFmt % ('py',filename))
             open(filename,'w').write(self._renderPy())
             ext = ext +  '/.py'
 
@@ -885,7 +885,7 @@
         elif name:
             setattr(obj,name,value)
         else:
-            raise ValueError, "Can't add, need name"
+            raise ValueError("Can't add, need name")
 
 class LineShape(Shape):
     # base for types of lines
@@ -951,7 +951,7 @@
 
 
 # path operator  constants
-_MOVETO, _LINETO, _CURVETO, _CLOSEPATH = range(4)
+_MOVETO, _LINETO, _CURVETO, _CLOSEPATH = list(range(4))
 _PATH_OP_ARG_COUNT = (2, 2, 6, 0)  # [moveTo, lineTo, curveTo, closePath]
 _PATH_OP_NAMES=['moveTo','lineTo','curveTo','closePath']
 
@@ -1065,7 +1065,7 @@
         n = 1
         radiansdelta = 0
 
-    for angle in xrange(n):
+    for angle in range(n):
         angle = startangle+angle*radiansdelta
         a((centerx+radius*cos(angle),centery+yradius*sin(angle)))
 
@@ -1092,14 +1092,14 @@
             opName = seg[0]
             args = seg[1:]
         if opName not in _PATH_OP_NAMES:
-            raise ValueError, 'bad operator name %s' % opName
+            raise ValueError('bad operator name %s' % opName)
         op = _PATH_OP_NAMES.index(opName)
         if len(args)!=_PATH_OP_ARG_COUNT[op]:
-            raise ValueError, '%s bad arguments %s' % (opName,str(args))
+            raise ValueError('%s bad arguments %s' % (opName,str(args)))
         O.append(op)
         P.extend(list(args))
     for d,o in (dx,0), (dy,1):
-        for i in xrange(o,len(P),2):
+        for i in range(o,len(P),2):
             P[i] = P[i]+d
     return Path(P,O,isClipPath,**kw)
 
@@ -1272,7 +1272,7 @@
         CA = []
         CAA = CA.append
         a = points.append
-        for angle in xrange(n):
+        for angle in range(n):
             angle = startangle+angle*radiansdelta
             CAA((cos(angle),sin(angle)))
         for c,s in CA:
@@ -1423,24 +1423,24 @@
         added to drawings; they must create a shape (typically a group)
         so that the renderer can draw the custom node."""
 
-        raise NotImplementedError, "this method must be redefined by the user/programmer"
+        raise NotImplementedError("this method must be redefined by the user/programmer")
 
 
 def test():
     r = Rect(10,10,200,50)
     import pprint
     pp = pprint.pprint
-    print 'a Rectangle:'
+    print('a Rectangle:')
     pp(r.getProperties())
-    print
-    print 'verifying...',
+    print()
+    print('verifying...', end=' ')
     r.verify()
-    print 'OK'
+    print('OK')
     #print 'setting rect.z = "spam"'
     #r.z = 'spam'
-    print 'deleting rect.width'
+    print('deleting rect.width')
     del r.width
-    print 'verifying...',
+    print('verifying...', end=' ')
     r.verify()
 
 
--- a/src/reportlab/graphics/testdrawings.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/testdrawings.py	Tue Apr 30 14:20:22 2013 +0100
@@ -293,4 +293,4 @@
 
 
 if __name__=='__main__':
-    print __doc__
+    print(__doc__)
--- a/src/reportlab/graphics/testshapes.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/testshapes.py	Tue Apr 30 14:20:22 2013 +0100
@@ -384,7 +384,7 @@
 
     return D
 
-from widgets.signsandsymbols import SmileyFace
+from .widgets.signsandsymbols import SmileyFace
 def getDrawing11():
     '''test of anchoring'''
     def makeSmiley(x, y, size, color):
@@ -481,7 +481,7 @@
     funcNames = []
 
     # Here we get the names from the global name space.
-    symbols = globals().keys()
+    symbols = list(globals().keys())
     symbols.sort()
     for funcName in symbols:
         if funcName[0:10] == 'getDrawing':
@@ -534,7 +534,7 @@
         i = i + 1
 
     c.save()
-    print 'wrote %s ' % pdfPath
+    print('wrote %s ' % pdfPath)
 
 
 class ShapesTestCase(unittest.TestCase):
--- a/src/reportlab/graphics/widgetbase.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/widgetbase.py	Tue Apr 30 14:20:22 2013 +0100
@@ -27,11 +27,11 @@
         """
 
         if self._attrMap is not None:
-            for key in self.__dict__.keys():
+            for key in list(self.__dict__.keys()):
                 if key[0] != '_':
                     msg = "Unexpected attribute %s found in %s" % (key, self)
                     assert key in self._attrMap, msg
-            for (attr, metavalue) in self._attrMap.items():
+            for (attr, metavalue) in list(self._attrMap.items()):
                 msg = "Missing attribute %s from %s" % (attr, self)
                 assert hasattr(self, attr), msg
                 value = getattr(self, attr)
@@ -64,14 +64,14 @@
         # expose sequence contents?
 
         props = {}
-        for name in self.__dict__.keys():
+        for name in list(self.__dict__.keys()):
             if name[0:1] != '_':
                 component = getattr(self, name)
 
                 if recur and isValidChild(component):
                     # child object, get its properties too
                     childProps = component.getProperties(recur=recur)
-                    for (childKey, childValue) in childProps.items():
+                    for (childKey, childValue) in list(childProps.items()):
                         #key might be something indexed like '[2].fillColor'
                         #or simple like 'fillColor'; in the former case we
                         #don't need a '.' between me and my child.
@@ -98,7 +98,7 @@
         """
 
         childPropDicts = {}
-        for (name, value) in propDict.items():
+        for (name, value) in list(propDict.items()):
             parts = string.split(name, '.', 1)
             if len(parts) == 1:
                 #simple attribute, set it now
@@ -111,7 +111,7 @@
                     childPropDicts[childName] = {remains: value}
 
         # now assign to children
-        for (childName, childPropDict) in childPropDicts.items():
+        for (childName, childPropDict) in list(childPropDicts.items()):
             child = getattr(self, childName)
             child.setProperties(childPropDict)
 
@@ -122,12 +122,12 @@
         samples for documentation.
         """
 
-        propList = self.getProperties().items()
+        propList = list(self.getProperties().items())
         propList.sort()
         if prefix:
             prefix = prefix + '.'
         for (name, value) in propList:
-            print '%s%s = %s' % (prefix, name, value)
+            print('%s%s = %s' % (prefix, name, value))
 
 
 class Widget(PropHolder, shapes.UserNode):
@@ -136,17 +136,17 @@
     widgets and vice versa."""
 
     def _setKeywords(self,**kw):
-        for k,v in kw.items():
+        for k,v in list(kw.items()):
             if k not in self.__dict__:
                 setattr(self,k,v)
 
     def draw(self):
         msg = "draw() must be implemented for each Widget!"
-        raise shapes.NotImplementedError, msg
+        raise shapes.NotImplementedError(msg)
 
     def demo(self):
         msg = "demo() must be implemented for each Widget!"
-        raise shapes.NotImplementedError, msg
+        raise shapes.NotImplementedError(msg)
 
     def provideNode(self):
         return self.draw()
@@ -251,7 +251,7 @@
                     child._index = None
             else:
                 child._index = None
-            for i in filter(lambda x,K=child.__dict__.keys(): x in K,child._attrMap.keys()):
+            for i in filter(lambda x,K=list(child.__dict__.keys()): x in K,list(child._attrMap.keys())):
                 del child.__dict__[i]
 
             self._children[index] = child
@@ -266,27 +266,27 @@
         assert isinstance(value, self._value.__class__), msg
 
     def __len__(self):
-        return len(self._children.keys())
+        return len(list(self._children.keys()))
 
     def getProperties(self,recur=1):
         # return any children which are defined and whatever
         # differs from the parent
         props = {}
 
-        for (key, value) in self._value.getProperties(recur=recur).items():
+        for (key, value) in list(self._value.getProperties(recur=recur).items()):
             props['%s' % key] = value
 
-        for idx in self._children.keys():
+        for idx in list(self._children.keys()):
             childProps = self._children[idx].getProperties(recur=recur)
-            for (key, value) in childProps.items():
+            for (key, value) in list(childProps.items()):
                 if not hasattr(self,key) or getattr(self, key)!=value:
                     newKey = '[%s].%s' % (idx, key)
                     props[newKey] = value
         return props
 
     def setVector(self,**kw):
-        for name, value in kw.items():
-            for i in xrange(len(value)):
+        for name, value in list(kw.items()):
+            for i in range(len(value)):
                 setattr(self[i],name,value[i])
 
     def __getattr__(self,name):
@@ -333,7 +333,7 @@
     def __init__(self, **kwargs):
         "Initialize with attributes if any."
 
-        for k, v in kwargs.items():
+        for k, v in list(kwargs.items()):
             setattr(self, k, v)
 
 
@@ -456,7 +456,7 @@
     def _addNamedNode(self,name,node):
         'if name is not None add an attribute pointing to node and add to the attrMap'
         if name:
-            if name not in self._attrMap.keys():
+            if name not in list(self._attrMap.keys()):
                 self._attrMap[name] = AttrMapValue(isValidChild)
             setattr(self, name, node)
 
@@ -501,29 +501,29 @@
     wedges = TypedPropertyCollection(WedgeProperties)
     wedges.fillColor = colors.red
     wedges.setVector(fillColor=(colors.blue,colors.green,colors.white))
-    print len(_ItemWrapper)
+    print(len(_ItemWrapper))
 
     d = shapes.Drawing(400, 200)
     tc = TwoCircles()
     d.add(tc)
-    import renderPDF
+    from . import renderPDF
     renderPDF.drawToFile(d, 'sample_widget.pdf', 'A Sample Widget')
-    print 'saved sample_widget.pdf'
+    print('saved sample_widget.pdf')
 
     d = shapes.Drawing(400, 200)
     f = Face()
     f.skinColor = colors.yellow
     f.mood = "sad"
     d.add(f, name='theFace')
-    print 'drawing 1 properties:'
+    print('drawing 1 properties:')
     d.dumpProperties()
     renderPDF.drawToFile(d, 'face.pdf', 'A Sample Widget')
-    print 'saved face.pdf'
+    print('saved face.pdf')
 
     d2 = d.expandUserNodes()
     renderPDF.drawToFile(d2, 'face_copy.pdf', 'An expanded drawing')
-    print 'saved face_copy.pdf'
-    print 'drawing 2 properties:'
+    print('saved face_copy.pdf')
+    print('drawing 2 properties:')
     d2.dumpProperties()
 
 
--- a/src/reportlab/graphics/widgets/eventcal.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/widgets/eventcal.py	Tue Apr 30 14:20:22 2013 +0100
@@ -298,7 +298,7 @@
     for format in ['pdf']:#,'gif','png']:
         out = d.asString(format)
         open('eventcal.%s' % format, 'wb').write(out)
-        print 'saved eventcal.%s' % format
+        print('saved eventcal.%s' % format)
 
 if __name__=='__main__':
     test()
--- a/src/reportlab/graphics/widgets/flags.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/widgets/flags.py	Tue Apr 30 14:20:22 2013 +0100
@@ -36,7 +36,7 @@
 from reportlab.graphics.shapes import Line, Rect, Polygon, Drawing, Group, String, Circle, Wedge
 from reportlab.graphics.widgetbase import Widget
 from reportlab.graphics import renderPDF
-from signsandsymbols import _Symbol
+from .signsandsymbols import _Symbol
 import copy
 from math import sin, cos, pi
 
@@ -113,7 +113,7 @@
         r = R*sin(18*(pi/180.0))/cos(36*(pi/180.0))
         P = []
         angle = 90
-        for i in xrange(5):
+        for i in range(5):
             for radius in R, r:
                 theta = angle*(pi/180.0)
                 P.append(radius*cos(theta))
@@ -158,7 +158,7 @@
 
     def availableFlagNames(self):
         '''return a list of the things we can display'''
-        return filter(lambda x: x is not None, self._attrMap['kind'].validate._enum)
+        return [x for x in self._attrMap['kind'].validate._enum if x is not None]
 
     def _Flag_None(self):
         s = _size  # abbreviate as we will use this a lot
--- a/src/reportlab/graphics/widgets/grids.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/widgets/grids.py	Tue Apr 30 14:20:22 2013 +0100
@@ -452,10 +452,10 @@
     def orthogonalAxisDist(xy,s=s,c=c,x0=x0,y0=y0):
         x,y = xy
         return (c*(y-y0)+s*(x-x0))
-    L = map(parallelAxisDist,P)
+    L = list(map(parallelAxisDist,P))
     L.sort()
     a0, a1 = L[0], L[-1]
-    L = map(orthogonalAxisDist,P)
+    L = list(map(orthogonalAxisDist,P))
     L.sort()
     b0, b1 = L[0], L[-1]
     rect.x, rect.width = a0, a1-a0
@@ -485,8 +485,8 @@
 
     def draw(self):
         P = self.points
-        P = map(lambda i, P=P:(P[i],P[i+1]),xrange(0,len(P),2))
-        path = definePath([('moveTo',)+P[0]]+map(lambda x: ('lineTo',)+x,P[1:])+['closePath'],
+        P = list(map(lambda i, P=P:(P[i],P[i+1]),range(0,len(P),2)))
+        path = definePath([('moveTo',)+P[0]]+[('lineTo',)+x for x in P[1:]]+['closePath'],
             fillColor=None, strokeColor=None)
         path.isClipPath = 1
         g = Group()
--- a/src/reportlab/graphics/widgets/markers.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/widgets/markers.py	Tue Apr 30 14:20:22 2013 +0100
@@ -117,7 +117,7 @@
         r = R*sin(18*_toradians)/cos(36*_toradians)
         P = []
         angle = 90
-        for i in xrange(5):
+        for i in range(5):
             for radius in R, r:
                 theta = angle*_toradians
                 P.append(radius*cos(theta))
@@ -145,7 +145,7 @@
 
     def _doPolygon(self,P):
         x, y = self.x+self.dx, self.y+self.dy
-        if x or y: P = map(lambda i,P=P,A=[x,y]: P[i] + A[i&1], range(len(P)))
+        if x or y: P = list(map(lambda i,P=P,A=[x,y]: P[i] + A[i&1], list(range(len(P)))))
         return Polygon(P, strokeWidth =self.strokeWidth, strokeColor=self.strokeColor, fillColor=self.fillColor)
 
     def _doFill(self):
@@ -159,7 +159,7 @@
     def _doNgon(self,n):
         P = []
         size = float(self.size)/2
-        for i in xrange(n):
+        for i in range(n):
             r = (2.*i/n+0.5)*pi
             P.append(size*cos(r))
             P.append(size*sin(r))
@@ -237,7 +237,7 @@
         m.kind = name[:-5]
         m.size = 10
     else:
-        raise ValueError, "Invalid marker name %s" % name
+        raise ValueError("Invalid marker name %s" % name)
     return m
 
 if __name__=='__main__':
--- a/src/reportlab/graphics/widgets/signsandsymbols.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/widgets/signsandsymbols.py	Tue Apr 30 14:20:22 2013 +0100
@@ -927,7 +927,7 @@
                             fontSize=labelFontSize))
 
     renderPDF.drawToFile(D, 'signsandsymbols.pdf', 'signsandsymbols.py')
-    print 'wrote file: signsandsymbols.pdf'
+    print('wrote file: signsandsymbols.pdf')
 
 if __name__=='__main__':
     test()
--- a/src/reportlab/graphics/widgets/table.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/graphics/widgets/table.py	Tue Apr 30 14:20:22 2013 +0100
@@ -62,10 +62,10 @@
         self.textAnchor = 'start'
 
 
-        for k, v in kw.items():
-            if k in self.__class__._attrMap.keys():
+        for k, v in list(kw.items()):
+            if k in list(self.__class__._attrMap.keys()):
                 setattr(self, k, v)
-                print 'setting %s = %s'%(k, v)
+                print('setting %s = %s'%(k, v))
             else:
                 raise ValueError('invalid argument supplied for class %s'%self.__class__)
 
@@ -104,7 +104,7 @@
         #print "(row_step,col_step)=(%s, %s)"%(row_step,col_step)
         # draw the grid
         if self.horizontalDividerStrokeColor:
-            for i in xrange(rows): # make horizontal lines
+            for i in range(rows): # make horizontal lines
                 x1 = self.x
                 x2 = self.x + self.width
                 y = self.y + row_step*i
@@ -115,7 +115,7 @@
                 line.strokeColor = self.horizontalDividerStrokeColor
                 g.add(line)
         if self.verticalDividerStrokeColor:
-            for i in xrange(cols): # make vertical lines
+            for i in range(cols): # make vertical lines
                 x = self.x+col_step*i
                 y1 = self.y
                 y2 = self.y + self.height
--- a/src/reportlab/lib/PyFontify.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/PyFontify.py	Tue Apr 30 14:20:22 2013 +0100
@@ -157,4 +157,4 @@
     f.close()
     tags = fontify(text)
     for tag, start, end, sublist in tags:
-        print tag, repr(text[start:end])
+        print(tag, repr(text[start:end]))
--- a/src/reportlab/lib/abag.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/abag.py	Tue Apr 30 14:20:22 2013 +0100
@@ -25,12 +25,12 @@
 
     def __repr__(self):
         D = self.__dict__
-        K = D.keys()
+        K = list(D.keys())
         K.sort()
         return '%s(%s)' % (self.__class__.__name__,', '.join(['%s=%r' % (k,D[k]) for k in K]))
 
 if __name__=="__main__":
     AB = ABag(a=1, c="hello")
     CD = AB.clone()
-    print AB
-    print CD
+    print(AB)
+    print(CD)
--- a/src/reportlab/lib/arciv.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/arciv.py	Tue Apr 30 14:20:22 2013 +0100
@@ -22,8 +22,8 @@
 		#Initialize private key, k With the values of the key mod 256.
 		#and sbox With numbers 0 - 255. Then compute sbox
 		key = self._key
-		sbox = range(256)
-		k = range(256)
+		sbox = list(range(256))
+		k = list(range(256))
 		lk = len(key)
 		for i in sbox:
 			k[i] = ord(key[i % lk]) % 256
@@ -32,7 +32,7 @@
 		#Iterating each element of sbox re-calculate the counter j
 		#Then interchange the elements sbox[a] & sbox[b]
 		j = 0
-		for i in xrange(256):
+		for i in range(256):
 			j = (j+sbox[i]+k[i]) % 256
 			sbox[i], sbox[j] = sbox[j], sbox[i]
 		self._sbox, self._i, self._j = sbox, 0, 0
@@ -44,7 +44,7 @@
 		'''
 		sbox, i, j = self._sbox, self._i, self._j
 
-		C = type(B) is StringType and map(ord,B) or B[:]
+		C = type(B) is StringType and list(map(ord,B)) or B[:]
 		n = len(C)
 		p = 0
 		while p<n:
@@ -208,7 +208,7 @@
 	i = 0
 	for t in _TESTS:
 		o = ArcIV(t['key']).encode(t['input'])
-		print 'Forward test %d %s!' %(i,o!=t['output'] and 'failed' or 'succeeded')
+		print('Forward test %d %s!' %(i,o!=t['output'] and 'failed' or 'succeeded'))
 		o = ArcIV(t['key']).encode(t['output'])
-		print 'Reverse test %d %s!' %(i,o!=t['input'] and 'failed' or 'succeeded')
+		print('Reverse test %d %s!' %(i,o!=t['input'] and 'failed' or 'succeeded'))
 		i += 1
--- a/src/reportlab/lib/attrmap.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/attrmap.py	Tue Apr 30 14:20:22 2013 +0100
@@ -50,7 +50,7 @@
         self.desc = desc
         self._initial = initial
         self._advancedUsage = advancedUsage
-        for k,v in kw.items():
+        for k,v in list(kw.items()):
             setattr(self,k,v)
 
     def __getattr__(self,name):
@@ -60,10 +60,10 @@
             return self._initial
         elif name=='hidden':
             return 0
-        raise AttributeError, name
+        raise AttributeError(name)
 
     def __repr__(self):
-        return 'AttrMapValue(%s)' % ', '.join(['%s=%r' % i for i in self.__dict__.iteritems()])
+        return 'AttrMapValue(%s)' % ', '.join(['%s=%r' % i for i in self.__dict__.items()])
 
 class AttrMap(UserDict):
     def __init__(self,BASE=None,UNWANTED=[],**kw):
@@ -77,7 +77,7 @@
                     if hasattr(B,'_attrMap'):
                         data.update(getattr(B._attrMap,'data',{}))
                     else:
-                        raise ValueError, 'BASE=%s has wrong kind of value' % str(B)
+                        raise ValueError('BASE=%s has wrong kind of value' % str(B))
 
         UserDict.__init__(self,data)
         self.remove(UNWANTED)
@@ -113,9 +113,9 @@
                 try:
                     validate = map[name].validate
                     if not validate(value):
-                        raise AttributeError, "Illegal assignment of '%s' to '%s' in class %s" % (value, name, obj.__class__.__name__)
+                        raise AttributeError("Illegal assignment of '%s' to '%s' in class %s" % (value, name, obj.__class__.__name__))
                 except KeyError:
-                    raise AttributeError, "Illegal attribute '%s' in class %s" % (name, obj.__class__.__name__)
+                    raise AttributeError("Illegal attribute '%s' in class %s" % (name, obj.__class__.__name__))
     obj.__dict__[name] = value
 
 def _privateAttrMap(obj,ret=0):
--- a/src/reportlab/lib/codecharts.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/codecharts.py	Tue Apr 30 14:20:22 2013 +0100
@@ -150,7 +150,7 @@
 
     def draw(self):
         self.drawLabels()
-        charList = [None] * 32 + map(chr, range(32, 256))
+        charList = [None] * 32 + list(map(chr, list(range(32, 256))))
 
         #we need to convert these to Unicode, since ReportLab
         #2.0 can only draw in Unicode.
@@ -357,7 +357,7 @@
 ##    #Big5CodeChart(0xA1, 'MSungStd-Light-Acro','ETenms-B5-H').drawOn(c, 72, 500)
 
     c.save()
-    print 'saved codecharts.pdf'
+    print('saved codecharts.pdf')
 
 if __name__=='__main__':
     test()
--- a/src/reportlab/lib/colors.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/colors.py	Tue Apr 30 14:20:22 2013 +0100
@@ -41,6 +41,7 @@
 '''
 import math, re
 from reportlab.lib.utils import fp_str
+import collections
 
 class Color:
     """This class is used to represent color.  Components red, green, blue
@@ -85,10 +86,10 @@
         return (self.red, self.green, self.blue, self.alpha)
 
     def bitmap_rgb(self):
-        return tuple(map(lambda x: int(x*255)&255, self.rgb()))
+        return tuple([int(x*255)&255 for x in self.rgb()])
 
     def bitmap_rgba(self):
-        return tuple(map(lambda x: int(x*255)&255, self.rgba()))
+        return tuple([int(x*255)&255 for x in self.rgba()])
 
     def hexval(self):
         return '0x%02x%02x%02x' % self.bitmap_rgb()
@@ -118,7 +119,7 @@
 
     def _lookupName(self,D={}):
         if not D:
-            for n,v in getAllNamedColors().iteritems():
+            for n,v in getAllNamedColors().items():
                 if not isinstance(v,CMYKColor):
                     t = v.red,v.green,v.blue
                     if t in D:
@@ -190,7 +191,7 @@
         *NB* note this dosen't reach density zero'''
         scale = self._scale
         dd = scale/float(n)
-        L = [self.clone(density=scale - i*dd) for i in xrange(n)]
+        L = [self.clone(density=scale - i*dd) for i in range(n)]
         if reverse: L.reverse()
         return L
 
@@ -232,7 +233,7 @@
 
     def _lookupName(self,D={}):
         if not D:
-            for n,v in getAllNamedColors().iteritems():
+            for n,v in getAllNamedColors().items():
                 if isinstance(v,CMYKColor):
                     t = v.cyan,v.magenta,v.yellow,v.black
                     if t in D:
@@ -353,7 +354,7 @@
 
     """ #" for emacs
 
-    if isinstance(val,basestring):
+    if isinstance(val,str):
         b = 10
         if val[:1] == '#':
             val = val[1:]
@@ -385,7 +386,7 @@
     if x1<x0:
         x0,x1,c0,c1 = x1,x0,c1,c0 # normalized so x1>x0
     if x<x0-1e-8 or x>x1+1e-8: # fudge factor for numerical problems
-        raise ValueError, "Can't interpolate: x=%f is not between %f and %f!" % (x,x0,x1)
+        raise ValueError("Can't interpolate: x=%f is not between %f and %f!" % (x,x0,x1))
     if x<=x0:
         return c0
     elif x>=x1:
@@ -481,7 +482,7 @@
             a = c0.alpha+x*(c1.alpha - c0.alpha)/dx
             return PCMYKColor(c*100,m*100,y*100,k*100, density=d*100, alpha=a*100)
     else:
-        raise ValueError, "Can't interpolate: Unknown color class %s!" % cname
+        raise ValueError("Can't interpolate: Unknown color class %s!" % cname)
 
 def obj_R_G_B(c):
     '''attempt to convert an object to (red,green,blue)'''
@@ -703,9 +704,9 @@
     # uses a singleton for efficiency
     global _namedColors
     if _namedColors is not None: return _namedColors
-    import colors
+    from . import colors
     _namedColors = {}
-    for (name, value) in colors.__dict__.items():
+    for (name, value) in list(colors.__dict__.items()):
         if isinstance(value, Color):
             _namedColors[name] = value
 
@@ -719,18 +720,18 @@
     '''
     namedColors = getAllNamedColors()
     closest = (10, None, None)  #big number, name, color
-    for (name, color) in namedColors.items():
+    for (name, color) in list(namedColors.items()):
         distance = colorDistance(aColor, color)
         if distance < closest[0]:
             closest = (distance, name, color)
     if mode<=1:
         s = 'best match is %s, distance %0.4f' % (closest[1], closest[0])
-        if mode==0: print s
+        if mode==0: print(s)
         else: return s
     elif mode==2:
         return (closest[1], closest[0])
     else:
-        raise ValueError, "Illegal value for mode "+str(mode)
+        raise ValueError("Illegal value for mode "+str(mode))
 
 def hue2rgb(m1, m2, h):
     if h<0: h += 1
@@ -816,7 +817,7 @@
             if hsl:
                 R,G,B= hsl2rgb(self.hueVal(n[0]),self.pcVal(n[1]),self.pcVal(n[2]))
             else:
-                R,G,B = map('%' in n[0] and self.rgbPcVal or self.rgbVal,n)
+                R,G,B = list(map('%' in n[0] and self.rgbPcVal or self.rgbVal,n))
 
             return Color(R,G,B,a)
 
@@ -839,7 +840,7 @@
             assert 3<=len(arg)<=4, 'Can only convert 3 and 4 sequences to color'
             assert 0<=min(arg) and max(arg)<=1
             return len(arg)==3 and Color(arg[0],arg[1],arg[2]) or CMYKColor(arg[0],arg[1],arg[2],arg[3])
-        elif isinstance(arg,basestring):
+        elif isinstance(arg,str):
             C = cssParse(arg)
             if C: return C
             if arg in self.extraColorsNS: return self.extraColorsNS[arg]
@@ -873,9 +874,9 @@
     assigned = {}
     while kw and progress:
         progress = 0
-        for k, v in kw.items():
+        for k, v in list(kw.items()):
             if isinstance(v,(tuple,list)):
-                c = map(lambda x,UNDEF=UNDEF: toColor(x,UNDEF),v)
+                c = list(map(lambda x,UNDEF=UNDEF: toColor(x,UNDEF),v))
                 if isinstance(v,tuple): c = tuple(c)
                 ok = UNDEF not in c
             else:
@@ -888,7 +889,7 @@
 
     if kw: raise ValueError("Can't convert\n%s" % str(kw))
     getAllNamedColors()
-    for k, c in assigned.items():
+    for k, c in list(assigned.items()):
         globals()[k] = c
         if isinstance(c,Color): _namedColors[k] = c
 
@@ -1000,8 +1001,8 @@
     return tc
 
 def _chooseEnforceColorSpace(enforceColorSpace):
-    if enforceColorSpace is not None and not callable(enforceColorSpace):
-        if isinstance(enforceColorSpace,basestring): enforceColorSpace=enforceColorSpace.upper()
+    if enforceColorSpace is not None and not isinstance(enforceColorSpace, collections.Callable):
+        if isinstance(enforceColorSpace,str): enforceColorSpace=enforceColorSpace.upper()
         if enforceColorSpace=='CMYK':
             enforceColorSpace = _enforceCMYK
         elif enforceColorSpace=='RGB':
--- a/src/reportlab/lib/corp.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/corp.py	Tue Apr 30 14:20:22 2013 +0100
@@ -78,12 +78,12 @@
                         ] or []
         if _ocolors:
             g.add(definePath(OP,strokeColor=_ocolors[0],strokeWidth=strokeWidth,fillColor=_ocolors[1], dx=dx, dy=dy))
-            print '_ocolors',_ocolors
+            print('_ocolors',_ocolors)
         else:
             P += OP
         if self.showPage and _pagecolors:
             g.add(definePath(PP,strokeColor=_pagecolors[0],strokeWidth=strokeWidth,fillColor=_pagecolors[1], dx=dx, dy=dy))
-            print '_pagecolors',_pagecolors
+            print('_pagecolors',_pagecolors)
         else:
             P += PP
         g.add(definePath(P,strokeColor=strokeColor,strokeWidth=strokeWidth,fillColor=fillColor, dx=dx, dy=dy))
--- a/src/reportlab/lib/extformat.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/extformat.py	Tue Apr 30 14:20:22 2013 +0100
@@ -71,15 +71,15 @@
 	percent=79.2
 	class dingo:
 		a=3
-	print(magicformat('''
+	print((magicformat('''
 $%%(df(x,dp=3))s --> $%(df(x,dp=3))s
 $%%(df(x,dp=2,ds=',',ts='.'))s --> $%(df(x,dp=2,ds=',',ts='.'))s
 %%(percent).2f%%%% --> %(percent).2f%%
 %%(dingo.a)s --> %(dingo.a)s
 %%(Z['abc'][0])s --> %(Z['abc'][0])s
-'''))
+''')))
 	def func0(aa=1):
 		def func1(bb=2):
-			print(magicformat('bb=%(bb)s Z=%(Z)r'))
+			print((magicformat('bb=%(bb)s Z=%(Z)r')))
 		func1('BB')
 	func0('AA')
--- a/src/reportlab/lib/fontfinder.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/fontfinder.py	Tue Apr 30 14:20:22 2013 +0100
@@ -58,7 +58,7 @@
 Future plans might include using this to auto-register fonts; and making it
 update itself smartly on repeated instantiation.
 """
-import sys, time, os, cPickle, tempfile
+import sys, time, os, pickle, tempfile
 from xml.sax.saxutils import quoteattr
 try:
     from hashlib import md5
@@ -105,7 +105,7 @@
     def getTag(self):
         "Return an XML tag representation"
         attrs = []
-        for (k, v) in self.__dict__.items():
+        for (k, v) in list(self.__dict__.items()):
             if k not in ['timeModified']:
                 if v:
                     attrs.append('%s=%s' % (k, quoteattr(str(v))))
@@ -148,7 +148,7 @@
                     self._fontsByFamily[fam].append(font)
                 else:
                     self._fontsByFamily[fam] = [font]
-        names = self._fontsByFamily.keys()
+        names = list(self._fontsByFamily.keys())
         names.sort()
         return names
 
@@ -178,7 +178,7 @@
         selected = []
         for font in self._fonts:
             OK = True
-            for (k, v) in kwds.items():
+            for (k, v) in list(kwds.items()):
                 if getattr(font, k, None) != v:
                     OK = False
             if OK:
@@ -206,12 +206,12 @@
 
     def save(self, fileName):
         f = open(fileName, 'w')
-        cPickle.dump(self, f)
+        pickle.dump(self, f)
         f.close()
 
     def load(self, fileName):
         f = open(fileName, 'r')
-        finder2 = cPickle.load(f)
+        finder2 = pickle.load(f)
         f.close()
         self.__dict__.update(finder2.__dict__)
 
@@ -310,25 +310,25 @@
     ff.addDirectory(rlFontDir)
     ff.search()
 
-    print 'cache file name...'
-    print ff._getCacheFileName()
+    print('cache file name...')
+    print(ff._getCacheFileName())
 
-    print 'families...'
+    print('families...')
     for familyName in ff.getFamilyNames():
-        print '\t%s' % familyName
+        print('\t%s' % familyName)
 
-    print
-    print 'fonts called Vera:',
+    print()
+    print('fonts called Vera:', end=' ')
     for font in ff.getFontsInFamily('Bitstream Vera Sans'):
-        print '\t%s' % font.name
+        print('\t%s' % font.name)
 
-    print
-    print 'Bold fonts\n\t'
+    print()
+    print('Bold fonts\n\t')
     for font in ff.getFontsWithAttributes(isBold=True, isItalic=False):
-        print font.fullName ,
+        print(font.fullName, end=' ')
 
-    print 'family report'
-    print ff.getFamilyXmlReport()
+    print('family report')
+    print(ff.getFamilyXmlReport())
 
 if __name__=='__main__':
     test()
--- a/src/reportlab/lib/fonts.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/fonts.py	Tue Apr 30 14:20:22 2013 +0100
@@ -63,7 +63,7 @@
             }
 
 _ps2tt_map={}
-for k,v in _tt2ps_map.items():
+for k,v in list(_tt2ps_map.items()):
     if k not in _ps2tt_map:
         _ps2tt_map[v.lower()] = k
 
--- a/src/reportlab/lib/formatters.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/formatters.py	Tue Apr 30 14:20:22 2013 +0100
@@ -94,7 +94,7 @@
     def t(n, s, places=2, decimalSep='.', thousandSep=None, prefix=None, suffix=None):
         f=DecimalFormatter(places,decimalSep,thousandSep,prefix,suffix)
         r = f(n)
-        print "places=%2d dot=%-4s comma=%-4s prefix=%-4s suffix=%-4s result=%10s %s" %(f.places, f.dot, f.comma, f.prefix, f.suffix,r, r==s and 'OK' or 'BAD')
+        print("places=%2d dot=%-4s comma=%-4s prefix=%-4s suffix=%-4s result=%10s %s" %(f.places, f.dot, f.comma, f.prefix, f.suffix,r, r==s and 'OK' or 'BAD'))
     t(1000.9,'1,000.9',1,thousandSep=',')
     t(1000.95,'1,001.0',1,thousandSep=',')
     t(1000.95,'1,001',-1,thousandSep=',')
--- a/src/reportlab/lib/normalDate.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/normalDate.py	Tue Apr 30 14:20:22 2013 +0100
@@ -33,16 +33,16 @@
 _iso_re = re.compile(r'(\d\d\d\d|\d\d)-(\d\d)-(\d\d)')
 
 def getStdMonthNames():
-    return map(string.lower,_monthName)
+    return list(map(string.lower,_monthName))
 
 def getStdShortMonthNames():
-    return map(lambda x: x[:3],getStdMonthNames())
+    return [x[:3] for x in getStdMonthNames()]
 
 def getStdDayNames():
-    return map(string.lower,_dayOfWeekName)
+    return list(map(string.lower,_dayOfWeekName))
 
 def getStdShortDayNames():
-    return map(lambda x: x[:3],getStdDayNames())
+    return [x[:3] for x in getStdDayNames()]
 
 def isLeapYear(year):
     """determine if specified year is leap year, returns Python boolean"""
@@ -183,7 +183,7 @@
         else:
             daysByMonth = _daysInMonthNormal
         priorMonthDays = 0
-        for m in xrange(self.month() - 1):
+        for m in range(self.month() - 1):
             priorMonthDays = priorMonthDays + daysByMonth[m]
         return self.day() + priorMonthDays
 
@@ -390,14 +390,14 @@
         else:
             daysByMonth = _daysInMonthNormal
         dc = 0; month = 12
-        for m in xrange(len(daysByMonth)):
+        for m in range(len(daysByMonth)):
             dc = dc + daysByMonth[m]
             if dc >= days:
                 month = m + 1
                 break
         # add up the days in prior months
         priorMonthDays = 0
-        for m in xrange(month - 1):
+        for m in range(month - 1):
             priorMonthDays = priorMonthDays + daysByMonth[m]
         day = days - priorMonthDays
         self.setNormalDate((year, month, day))
@@ -427,10 +427,10 @@
         (year, month, day) = self.toTuple()
         days = firstDayOfYear(year) + day - 1
         if self.isLeapYear():
-            for m in xrange(month - 1):
+            for m in range(month - 1):
                 days = days + _daysInMonthLeapYear[m]
         else:
-            for m in xrange(month - 1):
+            for m in range(month - 1):
                 days = days + _daysInMonthNormal[m]
         if year == 1582:
             if month > 10 or (month == 10 and day > 4):
@@ -459,7 +459,7 @@
         (year, month, day, ...)"""
         if isinstance(normalDate,int):
             self.normalDate = normalDate
-        elif isinstance(normalDate,basestring):
+        elif isinstance(normalDate,str):
             try:
                 self.normalDate = int(normalDate)
             except:
@@ -599,20 +599,20 @@
 
 if __name__ == '__main__':
     today = NormalDate()
-    print "NormalDate test:"
-    print "  Today (%s) is: %s %s" % (today, today.dayOfWeekAbbrev(), today.localeFormat())
+    print("NormalDate test:")
+    print("  Today (%s) is: %s %s" % (today, today.dayOfWeekAbbrev(), today.localeFormat()))
     yesterday = today - 1
-    print "  Yesterday was: %s %s" % (yesterday.dayOfWeekAbbrev(), yesterday.localeFormat())
+    print("  Yesterday was: %s %s" % (yesterday.dayOfWeekAbbrev(), yesterday.localeFormat()))
     tomorrow = today + 1
-    print "  Tomorrow will be: %s %s" % (tomorrow.dayOfWeekAbbrev(), tomorrow.localeFormat())
-    print "  Days between tomorrow and yesterday: %d" % (tomorrow - yesterday)
-    print today.formatMS('{d}/{m}/{yy}')
-    print today.formatMS('{dd}/{m}/{yy}')
-    print today.formatMS('{ddd} {d}/{m}/{yy}')
-    print today.formatMS('{dddd} {d}/{m}/{yy}')
-    print today.formatMS('{d}/{mm}/{yy}')
-    print today.formatMS('{d}/{mmm}/{yy}')
-    print today.formatMS('{d}/{mmmm}/{yy}')
-    print today.formatMS('{d}/{m}/{yyyy}')
+    print("  Tomorrow will be: %s %s" % (tomorrow.dayOfWeekAbbrev(), tomorrow.localeFormat()))
+    print("  Days between tomorrow and yesterday: %d" % (tomorrow - yesterday))
+    print(today.formatMS('{d}/{m}/{yy}'))
+    print(today.formatMS('{dd}/{m}/{yy}'))
+    print(today.formatMS('{ddd} {d}/{m}/{yy}'))
+    print(today.formatMS('{dddd} {d}/{m}/{yy}'))
+    print(today.formatMS('{d}/{mm}/{yy}'))
+    print(today.formatMS('{d}/{mmm}/{yy}'))
+    print(today.formatMS('{d}/{mmmm}/{yy}'))
+    print(today.formatMS('{d}/{m}/{yyyy}'))
     b = BusinessDate('20010116')
-    print 'b=',b,'b.scalar()', b.scalar()
+    print('b=',b,'b.scalar()', b.scalar())
--- a/src/reportlab/lib/pdfencrypt.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/pdfencrypt.py	Tue Apr 30 14:20:22 2013 +0100
@@ -77,15 +77,15 @@
     def encode(self, t):
         "encode a string, stream, text"
         if not self.prepared:
-            raise ValueError, "encryption not prepared!"
+            raise ValueError("encryption not prepared!")
         if self.objnum is None:
-            raise ValueError, "not registered in PDF object"
+            raise ValueError("not registered in PDF object")
         return encodePDF(self.key, self.objnum, self.version, t, revision=self.revision)
     def prepare(self, document, overrideID=None):
         # get ready to do encryption
-        if DEBUG: print 'StandardEncryption.prepare(...) - revision %d' % self.revision
+        if DEBUG: print('StandardEncryption.prepare(...) - revision %d' % self.revision)
         if self.prepared:
-            raise ValueError, "encryption already prepared!"
+            raise ValueError("encryption already prepared!")
         # get the unescaped string value of the document id (first array element).
         # we allow one to be passed in instead to permit reproducible tests
         # of our algorithm, but in real life overrideID will always be None
@@ -99,36 +99,36 @@
                 internalID = "xxxxxxxxxxxxxxxx"
 
         if DEBUG:
-            print 'userPassword    = %s' % self.userPassword
-            print 'ownerPassword   = %s' % self.ownerPassword
-            print 'internalID      = %s' % internalID
-        self.P = int(self.permissionBits() - 2**31L)
+            print('userPassword    = %s' % self.userPassword)
+            print('ownerPassword   = %s' % self.ownerPassword)
+            print('internalID      = %s' % internalID)
+        self.P = int(self.permissionBits() - 2**31)
         if CLOBBERPERMISSIONS: self.P = -44 # AR hack
         if DEBUG:
-            print "self.P          = %s" % repr(self.P)
+            print("self.P          = %s" % repr(self.P))
         self.O = computeO(self.userPassword, self.ownerPassword, self.revision)
         if DEBUG:
-            print "self.O (as hex) = %s" % hexText(self.O)
+            print("self.O (as hex) = %s" % hexText(self.O))
 
         #print "\nself.O", self.O, repr(self.O)
         self.key = encryptionkey(self.userPassword, self.O, self.P, internalID, revision=self.revision)
         if DEBUG:
-            print "self.key (hex)  = %s" % hexText(self.key)
+            print("self.key (hex)  = %s" % hexText(self.key))
         self.U = computeU(self.key, revision=self.revision, documentId=internalID)
         if DEBUG:
-            print "self.U (as hex) = %s" % hexText(self.U)
+            print("self.U (as hex) = %s" % hexText(self.U))
         self.objnum = self.version = None
         self.prepared = 1
     def register(self, objnum, version):
         # enter a new direct object
         if not self.prepared:
-            raise ValueError, "encryption not prepared!"
+            raise ValueError("encryption not prepared!")
         self.objnum = objnum
         self.version = version
     def info(self):
         # the representation of self in file if any (should be None or PDFDict)
         if not self.prepared:
-            raise ValueError, "encryption not prepared!"
+            raise ValueError("encryption not prepared!")
         return StandardEncryptionDictionary(O=self.O, U=self.U, P=self.P, revision=self.revision)
 
 class StandardEncryptionDictionary:
@@ -165,7 +165,7 @@
         "xor's each bytes of the key with the number, which is <256"
         if num==0: return key
         from operator import xor
-        return ''.join(map(chr,map(xor,len(key)*[num],map(ord,key))))
+        return ''.join(map(chr,list(map(xor,len(key)*[num],list(map(ord,key))))))
 else:
     def xorKey(num, key):
         "xor's each bytes of the key with the number, which is <256"
@@ -196,7 +196,7 @@
         out = out + char
     return out
 
-PadString = string.join(map(hexchar, string.split(string.strip(padding))), "")
+PadString = string.join(list(map(hexchar, string.split(string.strip(padding)))), "")
 
 def encryptionkey(password, OwnerKey, Permissions, FileId1, revision=2):
     # FileId1 is first string of the fileid array
@@ -227,7 +227,7 @@
         for x in range(50):
             md5output = md5(md5output).digest()
         key = md5output[:16]
-    if DEBUG: print 'encryptionkey(%s,%s,%s,%s,%s)==>%s' % tuple(map(lambda x: hexText(str(x)),(password, OwnerKey, Permissions, FileId1, revision, key)))
+    if DEBUG: print('encryptionkey(%s,%s,%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (password, OwnerKey, Permissions, FileId1, revision, key)]))
     return key
 
 def computeO(userPassword, ownerPassword, revision):
@@ -254,7 +254,7 @@
         for i in range(20):
             thisKey = xorKey(i, digest)
             O = ArcIV(thisKey).encode(O)
-    if DEBUG: print 'computeO(%s,%s,%s)==>%s' % tuple(map(lambda x: hexText(str(x)),(userPassword, ownerPassword, revision,O)))
+    if DEBUG: print('computeO(%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (userPassword, ownerPassword, revision,O)]))
     return O
 
 def computeU(encryptionkey, encodestring=PadString,revision=2,documentId=None):
@@ -273,7 +273,7 @@
         while len(tmp) < 32:
             tmp = tmp + '\000'
         result = tmp
-    if DEBUG: print 'computeU(%s,%s,%s,%s)==>%s' % tuple(map(lambda x: hexText(str(x)),(encryptionkey, encodestring,revision,documentId,result)))
+    if DEBUG: print('computeU(%s,%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (encryptionkey, encodestring,revision,documentId,result)]))
     return result
 
 def checkU(encryptionkey, U):
@@ -281,8 +281,8 @@
     #print len(decoded), len(U), len(PadString)
     if decoded!=PadString:
         if len(decoded)!=len(PadString):
-            raise ValueError, "lengths don't match! (password failed)"
-        raise ValueError, "decode of U doesn't match fixed padstring (password failed)"
+            raise ValueError("lengths don't match! (password failed)")
+        raise ValueError("decode of U doesn't match fixed padstring (password failed)")
 
 def encodePDF(key, objectNumber, generationNumber, string, revision=2):
     "Encodes a string or stream"
@@ -306,7 +306,7 @@
     from reportlab.lib.arciv import ArcIV
     encrypted = ArcIV(key).encode(string)
     #print 'encrypted=', hexText(encrypted)
-    if DEBUG: print 'encodePDF(%s,%s,%s,%s,%s)==>%s' % tuple(map(lambda x: hexText(str(x)),(key, objectNumber, generationNumber, string, revision,encrypted)))
+    if DEBUG: print('encodePDF(%s,%s,%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (key, objectNumber, generationNumber, string, revision,encrypted)]))
     return encrypted
 
     ######################################################################
@@ -403,7 +403,7 @@
 See http://developer.reportlab.com''')
 
     (bboxInfo, pickledForms) = storeFormsInMemory(inputPDF, all=1, BBoxes=1)
-    names = bboxInfo.keys()
+    names = list(bboxInfo.keys())
 
     firstPageSize = bboxInfo['PageForms0'][2:]
 
@@ -503,7 +503,7 @@
     argv = list(sys_argv)[1:]
     if len(argv)>0:
         if argv[0] == '-h' or argv[0] == 'help':
-            print usage
+            print(usage)
             return
         if len(argv)<2:
             raise ValueError("Must include a filename and one or more arguments!")
@@ -575,7 +575,7 @@
                         else:
                             exec(thisarg[1] +' = argv[pos+1]')
                         if verbose:
-                            print "%s set to: '%s'." % (thisarg[3], argv[pos+1])
+                            print("%s set to: '%s'." % (thisarg[3], argv[pos+1]))
                         argv.remove(argv[pos+1])
                         argv.remove(thisarg[0])
                 except:
@@ -583,17 +583,17 @@
 
         if verbose>4:
             #useful if feeling paranoid and need to double check things at this point...
-            print "\ninfile:", infile
-            print "STRENGTH:", STRENGTH
-            print "SAVEFILE:", SAVEFILE
-            print "USER:", USER
-            print "OWNER:", OWNER
-            print "PRINTABLE:", PRINTABLE
-            print "MODIFIABLE:", MODIFIABLE
-            print "COPYPASTABLE:", COPYPASTABLE
-            print "ANNOTATABLE:", ANNOTATABLE
-            print "SAVEFILE:", SAVEFILE
-            print "VERBOSE:", verbose
+            print("\ninfile:", infile)
+            print("STRENGTH:", STRENGTH)
+            print("SAVEFILE:", SAVEFILE)
+            print("USER:", USER)
+            print("OWNER:", OWNER)
+            print("PRINTABLE:", PRINTABLE)
+            print("MODIFIABLE:", MODIFIABLE)
+            print("COPYPASTABLE:", COPYPASTABLE)
+            print("ANNOTATABLE:", ANNOTATABLE)
+            print("SAVEFILE:", SAVEFILE)
+            print("VERBOSE:", verbose)
 
 
         if SAVEFILE == 'encrypted.pdf':
@@ -608,21 +608,21 @@
                                     strength=STRENGTH)
 
         if verbose:
-            print "wrote output file '%s'(%s bytes)\n  owner password is '%s'\n  user password is '%s'" % (SAVEFILE, filesize, OWNER, USER)
+            print("wrote output file '%s'(%s bytes)\n  owner password is '%s'\n  user password is '%s'" % (SAVEFILE, filesize, OWNER, USER))
 
         if len(argv)>0:
             raise "\nUnrecognised arguments : %s\nknown arguments are:\n%s" % (str(argv)[1:-1], known_modes)
     else:
-        print usage
+        print(usage)
 
 def main():
     from reportlab.rl_config import verbose
     scriptInterp()
 
 if __name__=="__main__": #NO RUNTESTS
-    a = filter(lambda x: x[:7]=='--debug',sys.argv)
+    a = [x for x in sys.argv if x[:7]=='--debug']
     if a:
-        sys.argv = filter(lambda x: x[:7]!='--debug',sys.argv)
+        sys.argv = [x for x in sys.argv if x[:7]!='--debug']
         DEBUG = len(a)
     if '--test' in sys.argv: test()
     else: main()
--- a/src/reportlab/lib/pygments2xpre.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/pygments2xpre.py	Tue Apr 30 14:20:22 2013 +0100
@@ -33,11 +33,11 @@
     l = get_lexer_by_name(language)
     
     h = HtmlFormatter()
-    from StringIO import StringIO
+    from io import StringIO
     out = StringIO()
     highlight(s,l,h,out)
     styles = [(cls, style.split(';')[0].split(':')[1].strip())
-                for cls, (style, ttype, level) in h.class2style.iteritems()
+                for cls, (style, ttype, level) in h.class2style.items()
                 if cls and style and style.startswith('color:')]
     return _2xpre(out.getvalue(),styles)
 
@@ -57,12 +57,12 @@
         fmt = pygments2xpre(src)
         S(XPreformatted(fmt, style=styC))
     doc.build(S.__self__)
-    print 'saved pygments2xpre.pdf'
+    print('saved pygments2xpre.pdf')
 
 if __name__=='__main__':
     import sys
     filenames = sys.argv[1:]
     if not filenames:
-        print 'usage:  pygments2xpre.py file1.py [file2.py] [...]'
+        print('usage:  pygments2xpre.py file1.py [file2.py] [...]')
         sys.exit(0)
     convertSourceFiles(filenames)
--- a/src/reportlab/lib/randomtext.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/randomtext.py	Tue Apr 30 14:20:22 2013 +0100
@@ -305,7 +305,7 @@
     prevparts = []
     newparts = []
     output = []
-    for i in xrange(times):
+    for i in range(times):
         for partlist in (leadins, subjects, verbs, objects):
             while 1:
                 part = random.choice(partlist)
@@ -322,7 +322,7 @@
     if not getattr(rl_config,'_random',None):
         rl_config._random = 1
         import random
-        random.seed(2342471922L)
+        random.seed(2342471922)
         del random
 del rl_config
 
@@ -362,10 +362,10 @@
         else:
             sentences = 5
         try:
-            print randomText(theme,sentences)
+            print(randomText(theme,sentences))
         except:
-            print>>sys.stderr,"Usage: randomtext.py [theme [#sentences]]"
-            print>>sys.stderr," theme in chomsky|STARTUP|COMPUTERS|BLAH|BUZZWORD|STARTREK|PRINTING|PYTHON"
+            print("Usage: randomtext.py [theme [#sentences]]", file=sys.stderr)
+            print(" theme in chomsky|STARTUP|COMPUTERS|BLAH|BUZZWORD|STARTREK|PRINTING|PYTHON", file=sys.stderr)
             raise
     else:
-        print chomsky(5)
+        print(chomsky(5))
--- a/src/reportlab/lib/rparsexml.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/rparsexml.py	Tue Apr 30 14:20:22 2013 +0100
@@ -61,7 +61,7 @@
     simpleparse = 0
     import pyRXPU
     def warnCB(s):
-        print s
+        print(s)
     pyRXP_parser = pyRXPU.Parser(
                         ErrorOnValidityErrors=1,
                         NoNoDTDWarning=1,
@@ -99,7 +99,7 @@
 def parsexmlSimple(xmltext, oneOutermostTag=0,eoCB=None,entityReplacer=unEscapeContentList):
     """official interface: discard unused cursor info"""
     if RequirePyRXP:
-        raise ImportError, "pyRXP not found, fallback parser disabled"
+        raise ImportError("pyRXP not found, fallback parser disabled")
     (result, cursor) = parsexml0(xmltext,entityReplacer=entityReplacer)
     if oneOutermostTag:
         return result[2][0]
@@ -133,7 +133,7 @@
                 found = 1
                 cursor = find(text, ">", past)
                 if cursor<0:
-                    raise ValueError, "can't close prologue %r" % e
+                    raise ValueError("can't close prologue %r" % e)
                 cursor = cursor+1
         if found is None:
             done=1
@@ -177,7 +177,7 @@
                 if entityReplacer: ContentList = entityReplacer(ContentList)
                 return (NameString, AttDict, ContentList, ExtraStuff), len(xmltext)
             else:
-                raise ValueError, "no tags at non-toplevel %s" % repr(xmltext[cursor:cursor+20])
+                raise ValueError("no tags at non-toplevel %s" % repr(xmltext[cursor:cursor+20]))
     #D = {}
     L = []
     # look for start tag
@@ -190,7 +190,7 @@
             cursor = skip_prologue(xmltext, cursor)
             #break
     elif firstbracket<0:
-            raise ValueError, "non top level entry should be at start tag: %s" % repr(xmltext[:10])
+            raise ValueError("non top level entry should be at start tag: %s" % repr(xmltext[:10]))
     # special case: CDATA
     elif afterbracket2char=="![" and xmltext[firstbracket:firstbracket+9]=="<![CDATA[":
             #print "in CDATA", cursor
@@ -198,7 +198,7 @@
             startcdata = firstbracket+9
             endcdata = find(xmltext, CDATAENDMARKER, startcdata)
             if endcdata<0:
-                raise ValueError, "unclosed CDATA %s" % repr(xmltext[cursor:cursor+20])
+                raise ValueError("unclosed CDATA %s" % repr(xmltext[cursor:cursor+20]))
             NameString = CDATAMARKER
             ContentList = [xmltext[startcdata: endcdata]]
             cursor = endcdata+len(CDATAENDMARKER)
@@ -208,10 +208,10 @@
             #print "in COMMENT"
             endcommentdashes = find(xmltext, "--", firstbracket+4)
             if endcommentdashes<firstbracket:
-                raise ValueError, "unterminated comment %s" % repr(xmltext[cursor:cursor+20])
+                raise ValueError("unterminated comment %s" % repr(xmltext[cursor:cursor+20]))
             endcomment = endcommentdashes+2
             if xmltext[endcomment]!=">":
-                raise ValueError, "invalid comment: contains double dashes %s" % repr(xmltext[cursor:cursor+20])
+                raise ValueError("invalid comment: contains double dashes %s" % repr(xmltext[cursor:cursor+20]))
             return (None, endcomment+1) # shortcut exit
     else:
             # get the rest of the tag
@@ -248,7 +248,7 @@
                         if noclose or len(split(tagcontent+".", '"'))% 2:
                             stop=1
                 if noclose:
-                    raise ValueError, "unclosed start tag %s" % repr(xmltext[firstbracket:firstbracket+20])
+                    raise ValueError("unclosed start tag %s" % repr(xmltext[firstbracket:firstbracket+20]))
                 cursor = startsearch
                 #cursor = closebracket+1
                 # handle simple tag /> syntax
@@ -283,11 +283,11 @@
                     taglistindex = taglistindex+1
                     attentry = strip(attentry)
                     if attentry[0]!='"':
-                        raise ValueError, "attribute value must start with double quotes" + repr(attentry)
+                        raise ValueError("attribute value must start with double quotes" + repr(attentry))
                     while '"' not in attentry[1:]:
                         # must have an = inside the attribute value...
                         if taglistindex>lasttaglistindex:
-                            raise ValueError, "unclosed value " + repr(attentry)
+                            raise ValueError("unclosed value " + repr(attentry))
                         nextattentry = taglist[taglistindex]
                         taglistindex = taglistindex+1
                         attentry = "%s=%s" % (attentry, nextattentry)
@@ -299,7 +299,7 @@
                     try:
                         first = attvalue[0]; last=attvalue[-1]
                     except:
-                        raise ValueError, "attvalue,attentry,attlist="+repr((attvalue, attentry,attlist))
+                        raise ValueError("attvalue,attentry,attlist="+repr((attvalue, attentry,attlist)))
                     if first==last=='"' or first==last=="'":
                         attvalue = attvalue[1:-1]
                     #print attributename, "=", attvalue
@@ -321,13 +321,13 @@
                     if remainder:
                         L.append(remainder)
                 else:
-                    raise ValueError, "no close bracket for %s found after %s" % (name,repr(xmltext[cursor: cursor+20]))
+                    raise ValueError("no close bracket for %s found after %s" % (name,repr(xmltext[cursor: cursor+20])))
             # is it a close bracket?
             elif xmltext[nextopenbracket+1]=="/":
                 #print "found close bracket", repr(xmltext[nextopenbracket:nextopenbracket+20])
                 nextclosebracket = find(xmltext, ">", nextopenbracket)
                 if nextclosebracket<nextopenbracket:
-                    raise ValueError, "unclosed close tag %s" % repr(xmltext[nextopenbracket: nextopenbracket+20])
+                    raise ValueError("unclosed close tag %s" % repr(xmltext[nextopenbracket: nextopenbracket+20]))
                 closetagcontents = xmltext[nextopenbracket+2: nextclosebracket]
                 closetaglist = split(closetagcontents)
                 #if len(closetaglist)!=1:
@@ -341,9 +341,8 @@
                     endlinenum = len(split(prefix, "\n"))
                     prefix = xmltext[:startingat]
                     linenum = len(split(prefix, "\n"))
-                    raise ValueError, \
-                       "at lines %s...%s close tag name doesn't match %s...%s %s" %(
-                       linenum, endlinenum, repr(name), repr(closename), repr(xmltext[cursor: cursor+100]))
+                    raise ValueError("at lines %s...%s close tag name doesn't match %s...%s %s" %(
+                       linenum, endlinenum, repr(name), repr(closename), repr(xmltext[cursor: cursor+100])))
                 remainder = xmltext[cursor:nextopenbracket]
                 if remainder:
                     #if verbose: print "remainder", repr(remainder)
@@ -376,22 +375,22 @@
 import types
 def pprettyprint(parsedxml):
     """pretty printer mainly for testing"""
-    st = types.StringType
+    st = bytes
     if type(parsedxml) is st:
         return parsedxml
     (name, attdict, textlist, extra) = parsedxml
     if not attdict: attdict={}
     join = string.join
     attlist = []
-    for k in attdict.keys():
+    for k in list(attdict.keys()):
         v = attdict[k]
         attlist.append("%s=%s" % (k, repr(v)))
     attributes = join(attlist, " ")
     if not name and attributes:
-        raise ValueError, "name missing with attributes???"
+        raise ValueError("name missing with attributes???")
     if textlist is not None:
         # with content
-        textlistpprint = map(pprettyprint, textlist)
+        textlistpprint = list(map(pprettyprint, textlist))
         textpprint = join(textlistpprint, "\n")
         if not name:
             return textpprint # no outer tag
@@ -408,14 +407,14 @@
     from pprint import pprint
     now = time()
     D = parsexmlSimple(s)
-    print "DONE", time()-now
+    print("DONE", time()-now)
     if dump&4:
         pprint(D)
     #pprint(D)
     if dump&1:
-        print "============== reformatting"
+        print("============== reformatting")
         p = pprettyprint(D)
-        print p
+        print(p)
 
 def test():
     testparse("""<this type="xml">text &lt;&gt;<b>in</b> <funnytag foo="bar"/> xml</this>
@@ -437,6 +436,6 @@
     now = time()
     for f in filenames:
         t = open(f).read()
-        print "parsing", f
+        print("parsing", f)
         testparse(t)
-    print "elapsed", time()-now
+    print("elapsed", time()-now)
--- a/src/reportlab/lib/sequencer.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/sequencer.py	Tue Apr 30 14:20:22 2013 +0100
@@ -12,12 +12,12 @@
 # fredrik@pythonware.com
 # http://www.pythonware.com
 
-_RN_TEMPLATES = [ 0, 01, 011, 0111, 012, 02, 021, 0211, 02111, 013 ]
+_RN_TEMPLATES = [ 0, 0o1, 0o11, 0o111, 0o12, 0o2, 0o21, 0o211, 0o2111, 0o13 ]
 _RN_LETTERS = "IVXLCDM"
 
 def _format_I(value):
     if value < 0 or value > 3999:
-        raise ValueError, "illegal value"
+        raise ValueError("illegal value")
     str = ""
     base = -1
     while value:
@@ -77,7 +77,7 @@
         else:
             self._value = self._base
 
-    def next(self):
+    def __next__(self):
         self._value = self._value + 1
         v = self._value
         for counter in self._resets:
@@ -89,7 +89,7 @@
 
     def nextf(self):
         """Returns next value formatted"""
-        return self._formatter(self.next())
+        return self._formatter(next(self))
 
     def thisf(self):
         return self._formatter(self._this())
@@ -164,7 +164,7 @@
         increments it by one.  New counters start at one."""
         if not counter:
             counter = self._defaultCounter
-        return self._getCounter(counter).next()
+        return next(self._getCounter(counter))
 
     def thisf(self, counter=None):
         if not counter:
@@ -219,12 +219,12 @@
 
     def dump(self):
         """Write current state to stdout for diagnostics"""
-        counters = self._counters.items()
+        counters = list(self._counters.items())
         counters.sort()
-        print 'Sequencer dump:'
+        print('Sequencer dump:')
         for (key, counter) in counters:
-            print '    %s: value = %d, base = %d, format example = %s' % (
-                key, counter._this(), counter._base, counter.thisf())
+            print('    %s: value = %d, base = %d, format example = %s' % (
+                key, counter._this(), counter._base, counter.thisf()))
 
 """Your story builder needs to set this to"""
 _sequencer = None
@@ -252,52 +252,52 @@
 
 def test():
     s = Sequencer()
-    print 'Counting using default sequence: %d %d %d' % (s.next(),s.next(), s.next())
-    print 'Counting Figures: Figure %d, Figure %d, Figure %d' % (
-        s.next('figure'), s.next('figure'), s.next('figure'))
-    print 'Back to default again: %d' % s.next()
+    print('Counting using default sequence: %d %d %d' % (next(s),next(s), next(s)))
+    print('Counting Figures: Figure %d, Figure %d, Figure %d' % (
+        s.next('figure'), s.next('figure'), s.next('figure')))
+    print('Back to default again: %d' % next(s))
     s.setDefaultCounter('list1')
-    print 'Set default to list1: %d %d %d' % (s.next(),s.next(), s.next())
+    print('Set default to list1: %d %d %d' % (next(s),next(s), next(s)))
     s.setDefaultCounter()
-    print 'Set default to None again: %d %d %d' % (s.next(),s.next(), s.next())
-    print
-    print 'Creating Appendix counter with format A, B, C...'
+    print('Set default to None again: %d %d %d' % (next(s),next(s), next(s)))
+    print()
+    print('Creating Appendix counter with format A, B, C...')
     s.setFormat('Appendix', 'A')
-    print '    Appendix %s, Appendix %s, Appendix %s' % (
-        s.nextf('Appendix'),    s.nextf('Appendix'),s.nextf('Appendix'))
+    print('    Appendix %s, Appendix %s, Appendix %s' % (
+        s.nextf('Appendix'),    s.nextf('Appendix'),s.nextf('Appendix')))
 
     def format_french(num):
         return ('un','deux','trois','quatre','cinq')[(num-1)%5]
-    print
-    print 'Defining a custom format with french words:'
+    print()
+    print('Defining a custom format with french words:')
     s.registerFormat('french', format_french)
     s.setFormat('FrenchList', 'french')
-    print '   ',
+    print('   ', end=' ')
     for i in range(1,6):
-        print s.nextf('FrenchList'),
-    print
-    print 'Chaining H1 and H2 - H2 goes back to one when H1 increases'
+        print(s.nextf('FrenchList'), end=' ')
+    print()
+    print('Chaining H1 and H2 - H2 goes back to one when H1 increases')
     s.chain('H1','H2')
-    print '    H1 = %d' % s.next('H1')
-    print '      H2 = %d' % s.next('H2')
-    print '      H2 = %d' % s.next('H2')
-    print '      H2 = %d' % s.next('H2')
-    print '    H1 = %d' % s.next('H1')
-    print '      H2 = %d' % s.next('H2')
-    print '      H2 = %d' % s.next('H2')
-    print '      H2 = %d' % s.next('H2')
-    print
-    print 'GetItem notation - append a plus to increment'
-    print '    seq["Appendix"] = %s' % s["Appendix"]
-    print '    seq["Appendix+"] = %s' % s["Appendix+"]
-    print '    seq["Appendix+"] = %s' % s["Appendix+"]
-    print '    seq["Appendix"] = %s' % s["Appendix"]
-    print
-    print 'Finally, string format notation for nested lists.  Cool!'
-    print 'The expression ("Figure %(Chapter)s.%(Figure+)s" % seq) gives:'
-    print '    Figure %(Chapter)s.%(Figure+)s' % s
-    print '    Figure %(Chapter)s.%(Figure+)s' % s
-    print '    Figure %(Chapter)s.%(Figure+)s' % s
+    print('    H1 = %d' % s.next('H1'))
+    print('      H2 = %d' % s.next('H2'))
+    print('      H2 = %d' % s.next('H2'))
+    print('      H2 = %d' % s.next('H2'))
+    print('    H1 = %d' % s.next('H1'))
+    print('      H2 = %d' % s.next('H2'))
+    print('      H2 = %d' % s.next('H2'))
+    print('      H2 = %d' % s.next('H2'))
+    print()
+    print('GetItem notation - append a plus to increment')
+    print('    seq["Appendix"] = %s' % s["Appendix"])
+    print('    seq["Appendix+"] = %s' % s["Appendix+"])
+    print('    seq["Appendix+"] = %s' % s["Appendix+"])
+    print('    seq["Appendix"] = %s' % s["Appendix"])
+    print()
+    print('Finally, string format notation for nested lists.  Cool!')
+    print('The expression ("Figure %(Chapter)s.%(Figure+)s" % seq) gives:')
+    print('    Figure %(Chapter)s.%(Figure+)s' % s)
+    print('    Figure %(Chapter)s.%(Figure+)s' % s)
+    print('    Figure %(Chapter)s.%(Figure+)s' % s)
 
 
 if __name__=='__main__':
--- a/src/reportlab/lib/set_ops.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/set_ops.py	Tue Apr 30 14:20:22 2013 +0100
@@ -9,11 +9,11 @@
 import string
 
 def __set_coerce(t, S):
-    if t is types.ListType:
+    if t is list:
         return list(S)
-    elif t is types.TupleType:
+    elif t is tuple:
         return tuple(S)
-    elif t is types.StringType:
+    elif t is bytes:
         return string.join(S, '')
     return S
 
@@ -26,7 +26,7 @@
 
 def intersect(seq1, seq2):
     result = []
-    if type(seq1) != type(seq2) and type(seq2) == types.StringType: seq2 = list(seq2)
+    if type(seq1) != type(seq2) and type(seq2) == bytes: seq2 = list(seq2)
     for i in seq1:
         if i in seq2 and i not in result: result.append(i)
     return __set_coerce(type(seq1), result)
@@ -34,8 +34,8 @@
 def union(seq1, seq2):
     if type(seq1) == type(seq2):
         return unique(seq1 + seq2)
-    if type(seq1) == types.ListType or type(seq2) == types.ListType:
+    if type(seq1) == list or type(seq2) == list:
         return unique(list(seq1) + list(seq2))
-    if type(seq1) == types.TupleType or type(seq2) == types.TupleType:
+    if type(seq1) == tuple or type(seq2) == tuple:
         return unique(tuple(seq1) + tuple(seq2))
     return unique(list(seq1) + list(seq2))
--- a/src/reportlab/lib/styles.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/styles.py	Tue Apr 30 14:20:22 2013 +0100
@@ -62,7 +62,7 @@
 
     def _setKwds(self,**kw):
         #step three - copy keywords if any
-        for (key, value) in kw.items():
+        for (key, value) in list(kw.items()):
              self.__dict__[key] = value
 
     def __repr__(self):
@@ -73,20 +73,20 @@
         use if you have been hacking the styles.  This is
         used by __init__"""
         if self.parent:
-            for (key, value) in self.parent.__dict__.items():
+            for (key, value) in list(self.parent.__dict__.items()):
                 if (key not in ['name','parent']):
                     self.__dict__[key] = value
 
     def listAttrs(self, indent=''):
-        print indent + 'name =', self.name
-        print indent + 'parent =', self.parent
-        keylist = self.__dict__.keys()
+        print(indent + 'name =', self.name)
+        print(indent + 'parent =', self.parent)
+        keylist = list(self.__dict__.keys())
         keylist.sort()
         keylist.remove('name')
         keylist.remove('parent')
         for key in keylist:
             value = self.__dict__.get(key, None)
-            print indent + '%s = %s' % (key, value)
+            print(indent + '%s = %s' % (key, value))
 
     def clone(self, name, parent=None, **kwds):
         r = self.__class__(name,parent)
@@ -220,16 +220,16 @@
             self.byAlias[alias] = style
 
     def list(self):
-        styles = self.byName.items()
+        styles = list(self.byName.items())
         styles.sort()
         alii = {}
-        for (alias, style) in self.byAlias.items():
+        for (alias, style) in list(self.byAlias.items()):
             alii[style] = alias
         for (name, style) in styles:
             alias = alii.get(style, None)
-            print name, alias
+            print(name, alias)
             style.listAttrs('    ')
-            print
+            print()
 
 def testStyles():
     pNormal = ParagraphStyle('Normal',None)
@@ -238,7 +238,7 @@
     pNormal.leading = 14.4
 
     pNormal.listAttrs()
-    print
+    print()
     pPre = ParagraphStyle('Literal', pNormal)
     pPre.fontName = 'Courier'
     pPre.listAttrs()
--- a/src/reportlab/lib/testutils.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/testutils.py	Tue Apr 30 14:20:22 2013 +0100
@@ -10,7 +10,7 @@
 """
 
 import sys, os, string, fnmatch, copy, re
-from ConfigParser import ConfigParser
+from configparser import ConfigParser
 import unittest
 
 # Helper functions.
@@ -85,7 +85,7 @@
     if sys._getframe(depth).f_locals.get('__name__')=='__main__':
         outDir = outputfile('')
         if outDir!=_OUTDIR:
-            print 'Logs and output files written to folder "%s"' % outDir
+            print('Logs and output files written to folder "%s"' % outDir)
 
 def makeSuiteForClasses(*classes):
     "Return a test suite with tests loaded from provided classes."
@@ -167,7 +167,7 @@
             self.directory = directory[len(__loader__.archive)+len(os.sep):]
             pfx = self.directory+os.sep
             n = len(pfx)
-            self.files = map(lambda x, n=n: x[n:],filter(lambda x,pfx=pfx: x.startswith(pfx),__loader__._files.keys()))
+            self.files = list(map(lambda x, n=n: x[n:],list(filter(lambda x,pfx=pfx: x.startswith(pfx),list(__loader__._files.keys())))))
             self.stack = []
 
     def __getitem__(self, index):
@@ -216,7 +216,7 @@
         "Filters all items from files matching patterns to ignore."
 
         indicesToDelete = []
-        for i in xrange(len(files)):
+        for i in range(len(files)):
             f = files[i]
             for p in self.ignoredPatterns:
                 if fnmatch.fnmatch(f, p):
@@ -243,7 +243,7 @@
         cvsFiles = getCVSEntries(folder)
         if cvsFiles:
             indicesToDelete = []
-            for i in xrange(len(files)):
+            for i in range(len(files)):
                 f = files[i]
                 if join(folder, f) not in cvsFiles:
                     indicesToDelete.append(i)
@@ -327,7 +327,7 @@
         p = os.popen(fmt % (sys.executable,self.scriptName),'r')
         out = p.read()
         if self.verbose:
-            print out
+            print(out)
         status = p.close()
         assert os.path.isfile(self.outFileName), "File %s not created!" % self.outFileName
 
--- a/src/reportlab/lib/textsplit.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/textsplit.py	Tue Apr 30 14:20:22 2013 +0100
@@ -19,22 +19,22 @@
 
 CANNOT_START_LINE = [
     #strongly prohibited e.g. end brackets, stop, exclamation...
-    u'!\',.:;?!")]\u3001\u3002\u300d\u300f\u3011\u3015\uff3d\u3011\uff09',
+    '!\',.:;?!")]\u3001\u3002\u300d\u300f\u3011\u3015\uff3d\u3011\uff09',
     #middle priority e.g. continuation small vowels - wrapped on two lines but one string...
-    u'\u3005\u2015\u3041\u3043\u3045\u3047\u3049\u3063\u3083\u3085\u3087\u308e\u30a1\u30a3'
-    u'\u30a5\u30a7\u30a9\u30c3\u30e3\u30e5\u30e7\u30ee\u30fc\u30f5\u30f6',
+    '\u3005\u2015\u3041\u3043\u3045\u3047\u3049\u3063\u3083\u3085\u3087\u308e\u30a1\u30a3'
+    '\u30a5\u30a7\u30a9\u30c3\u30e3\u30e5\u30e7\u30ee\u30fc\u30f5\u30f6',
     #weakly prohibited - continuations, celsius symbol etc.
-    u'\u309b\u309c\u30fb\u30fd\u30fe\u309d\u309e\u2015\u2010\xb0\u2032\u2033\u2103\uffe0\uff05\u2030'
+    '\u309b\u309c\u30fb\u30fd\u30fe\u309d\u309e\u2015\u2010\xb0\u2032\u2033\u2103\uffe0\uff05\u2030'
     ]
 
-ALL_CANNOT_START = u''.join(CANNOT_START_LINE)
+ALL_CANNOT_START = ''.join(CANNOT_START_LINE)
 CANNOT_END_LINE = [
     #strongly prohibited
-    u'\u2018\u201c\uff08[{\uff08\u3014\uff3b\uff5b\u3008\u300a\u300c\u300e\u3010',
+    '\u2018\u201c\uff08[{\uff08\u3014\uff3b\uff5b\u3008\u300a\u300c\u300e\u3010',
     #weaker - currency symbols, hash, postcode - prefixes
-    u'$\u00a3@#\uffe5\uff04\uffe1\uff20\u3012\u00a7'
+    '$\u00a3@#\uffe5\uff04\uffe1\uff20\u3012\u00a7'
     ]
-ALL_CANNOT_END = u''.join(CANNOT_END_LINE)
+ALL_CANNOT_END = ''.join(CANNOT_END_LINE)
 
 def is_multi_byte(ch):
     "Is this an Asian character?"
@@ -141,7 +141,7 @@
                 #  - reversion to Kanji (which would be a good split point)
                 #  - in the worst case, roughly half way back along the line
                 limitCheck = (lineStartPos+i)>>1        #(arbitrary taste issue)
-                for j in xrange(i-1,limitCheck,-1):
+                for j in range(i-1,limitCheck,-1):
                     cj = word[j]
                     if category(cj)=='Zs' or ord(cj)>=0x3000:
                         k = j+1
@@ -224,7 +224,7 @@
 #
 #  http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061
 import re
-rx=re.compile(u"([\u2e80-\uffff])", re.UNICODE)
+rx=re.compile("([\u2e80-\uffff])", re.UNICODE)
 def cjkwrap(text, width, encoding="utf8"):
      return reduce(lambda line, word, width=width: '%s%s%s' %
                 (line,
@@ -232,10 +232,10 @@
                        + len(word.split('\n',1)[0] ) >= width) or
                       line[-1:] == '\0' and 2],
                  word),
-                rx.sub(r'\1\0 ', unicode(text,encoding)).split(' ')
+                rx.sub(r'\1\0 ', str(text,encoding)).split(' ')
             ).replace('\0', '').encode(encoding)
 
 if __name__=='__main__':
     import doctest
-    import textsplit
+    from . import textsplit
     doctest.testmod(textsplit)
--- a/src/reportlab/lib/units.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/units.py	Tue Apr 30 14:20:22 2013 +0100
@@ -27,4 +27,4 @@
         if s[-4:]=='pica': return float(s[:-4])*pica
         return float(s)
     except:
-        raise ValueError, "Can't convert '%s' to length" % s
+        raise ValueError("Can't convert '%s' to length" % s)
--- a/src/reportlab/lib/utils.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/utils.py	Tue Apr 30 14:20:22 2013 +0100
@@ -10,7 +10,7 @@
 except:
     from md5 import md5
 from reportlab.lib.logger import warnOnce
-from rltempfile import get_rl_tempfile, get_rl_tempdir, _rl_getuid
+from .rltempfile import get_rl_tempfile, get_rl_tempdir, _rl_getuid
 
 def isSeqType(v,_st=(tuple,list)):
     return isinstance(v,_st)
@@ -25,7 +25,7 @@
 else:
     # hexdigest not available in 1.5
     def _digester(s):
-        return join(map(lambda x : "%02x" % ord(x), md5(s).digest()), '')
+        return join(["%02x" % ord(x) for x in md5(s).digest()], '')
 
 def _findFiles(dirList,ext='.ttf'):
     from os.path import isfile, isdir, join as path_join
@@ -51,7 +51,7 @@
         self.update(kwds)
 
     def update(self,D):
-        for k,v in D.items(): self[k] = v
+        for k,v in list(D.items()): self[k] = v
 
     def __setitem__(self,k,v):
         try:
@@ -189,7 +189,7 @@
         c, pfn = __startswith_rl(pattern)
         r = glob(pfn)
         if c or r==[]:
-            r += map(lambda x,D=_archivepfx,pjoin=pjoin: pjoin(_archivepfx,x),filter(lambda x,pfn=pfn,fnmatch=fnmatch: fnmatch(x,pfn),__loader__._files.keys()))
+            r += list(map(lambda x,D=_archivepfx,pjoin=pjoin: pjoin(_archivepfx,x),list(filter(lambda x,pfn=pfn,fnmatch=fnmatch: fnmatch(x,pfn),list(__loader__._files.keys())))))
         return r
 except:
     _isFSD = os.path.isfile(__file__)   #slight risk of wrong path
@@ -244,7 +244,7 @@
                     try:
                         if n[-1]=='.': n = n[:-1]
                     except:
-                        print i, n
+                        print(i, n)
                         raise
                 A((n[0]!='0' or len(n)==1) and n or n[1:])
         return ' '.join(s)
@@ -258,12 +258,12 @@
 def recursiveImport(modulename, baseDir=None, noCWD=0, debug=0):
     """Dynamically imports possible packagized module, or raises ImportError"""
     normalize = lambda x: os.path.normcase(os.path.abspath(os.path.normpath(x)))
-    path = map(normalize,sys.path)
+    path = list(map(normalize,sys.path))
     if baseDir:
         if not isSeqType(baseDir):
             tp = [baseDir]
         else:
-            tp = filter(None,list(baseDir))
+            tp = [_f for _f in list(baseDir) if _f]
         for p in tp:
             p = normalize(p)
             if p not in path: path.insert(0,p)
@@ -271,7 +271,7 @@
     if noCWD:
         for p in ('','.',normalize('.')):
             while p in path:
-                if debug: print 'removed "%s" from path' % p
+                if debug: print('removed "%s" from path' % p)
                 path.remove(p)
     elif '.' not in path:
             path.insert(0,'.')
@@ -279,14 +279,14 @@
     if debug:
         import pprint
         pp = pprint.pprint
-        print 'path=',
+        print('path=', end=' ')
         pp(path)
 
     #make import errors a bit more informative
     opath = sys.path
     try:
         sys.path = path
-        exec 'import %s\nm = %s\n' % (modulename,modulename) in locals()
+        exec('import %s\nm = %s\n' % (modulename,modulename), locals())
         sys.path = opath
         return m
     except ImportError:
@@ -294,11 +294,11 @@
         msg = "Could not import '%s'" % modulename
         if baseDir:
             msg = msg + " under %s" % baseDir
-        raise ImportError, msg
+        raise ImportError(msg)
 
     except Exception, e:
         msg = "Exception raised while importing '%s': %s" % (modulename, e.message)
-        raise ImportError, msg
+        raise ImportError(msg)
         
 
 def recursiveGetAttr(obj, name):
@@ -348,9 +348,9 @@
     haveImages = Image is not None
 
 try:
-    from cStringIO import StringIO as __StringIO
+    from io import StringIO as __StringIO
 except ImportError:
-    from StringIO import StringIO as __StringIO
+    from io import StringIO as __StringIO
 def getStringIO(buf=None):
     '''unified StringIO instance interface'''
     return buf is not None and __StringIO(buf) or __StringIO()
@@ -371,8 +371,8 @@
         if func:
             v = func(av)
         else:
-            if isinstance(v,basestring):
-                if isinstance(v,unicode): v = v.encode('utf8')
+            if isinstance(v,str):
+                if isinstance(v,str): v = v.encode('utf8')
                 v = av
             elif isinstance(v,float):
                 v = float(av)
@@ -388,7 +388,7 @@
 
     A = sys.argv[1:]
     R = {}
-    for k, v in kw.items():
+    for k, v in list(kw.items()):
         if isinstance(v,ArgvDictValue):
             v, func = v.value, v.func
         else:
@@ -412,7 +412,7 @@
         from reportlab.lib.pyHnj import Hyphen
         if hDict is None: hDict=os.path.join(os.path.dirname(__file__),'hyphen.mashed')
         return Hyphen(hDict)
-    except ImportError, errMsg:
+    except ImportError as errMsg:
         if str(errMsg)!='No module named pyHnj': raise
         return None
 
@@ -439,8 +439,8 @@
         if 'b' not in mode and os.linesep!='\n': s = s.replace(os.linesep,'\n')
         return getStringIO(s)
 
-import urllib2
-def open_for_read(name,mode='b', urlopen=urllib2.urlopen):
+import urllib.request, urllib.error, urllib.parse
+def open_for_read(name,mode='b', urlopen=urllib.request.urlopen):
     '''attempt to open a file or URL for reading'''
     if hasattr(name,'read'): return name
     try:
@@ -463,20 +463,20 @@
     if os_path_isfile(fn): return True
     if _isFSD or __loader__ is None: return False
     fn = _startswith_rl(fn)
-    return fn in __loader__._files.keys()
+    return fn in list(__loader__._files.keys())
 
 def rl_isdir(pn,os_path_isdir=os.path.isdir,os_path_normpath=os.path.normpath):
     if os_path_isdir(pn): return True
     if _isFSD or __loader__ is None: return False
     pn = _startswith_rl(os_path_normpath(pn))
     if not pn.endswith(os.sep): pn += os.sep
-    return len(filter(lambda x,pn=pn: x.startswith(pn),__loader__._files.keys()))>0
+    return len(list(filter(lambda x,pn=pn: x.startswith(pn),list(__loader__._files.keys()))))>0
 
 def rl_listdir(pn,os_path_isdir=os.path.isdir,os_path_normpath=os.path.normpath,os_listdir=os.listdir):
     if os_path_isdir(pn) or _isFSD or __loader__ is None: return os_listdir(pn)
     pn = _startswith_rl(os_path_normpath(pn))
     if not pn.endswith(os.sep): pn += os.sep
-    return [x[len(pn):] for x in __loader__._files.keys() if x.startswith(pn)]
+    return [x[len(pn):] for x in list(__loader__._files.keys()) if x.startswith(pn)]
 
 def rl_getmtime(pn,os_path_isfile=os.path.isfile,os_path_normpath=os.path.normpath,os_path_getmtime=os.path.getmtime,time_mktime=time.mktime):
     if os_path_isfile(pn) or _isFSD or __loader__ is None: return os_path_getmtime(pn)
@@ -561,7 +561,7 @@
                             register_reset(self._cache.clear)
                         data=self._cache.setdefault(md5(data).digest(),data)
                     self.fp=getStringIO(data)
-                elif imageReaderFlags==-1 and isinstance(fileName,(str,unicode)):
+                elif imageReaderFlags==-1 and isinstance(fileName,str):
                     #try Ralf Schmitt's re-opening technique of avoiding too many open files
                     self.fp.close()
                     del self.fp #will become a property in the next statement
@@ -587,7 +587,7 @@
     def identity(self):
         '''try to return information that will identify the instance'''
         fn = self.fileName
-        if not isinstance(fn,basestring):
+        if not isinstance(fn,str):
             fn = getattr(getattr(self,'fp',None),'name',None)
         ident = self._ident
         return '[%s@%s%s%s]' % (self.__class__.__name__,hex(id(self)),ident and (' ident=%r' % ident) or '',fn and (' filename=%r' % fn) or '')
@@ -670,7 +670,7 @@
                     palette = palette.palette
                 except:
                     palette = palette.data
-                return map(ord, palette[transparency:transparency+3])
+                return list(map(ord, palette[transparency:transparency+3]))
             else:
                 return None
 
@@ -747,7 +747,7 @@
         except:
             pass
         env = os.environ
-        K=env.keys()
+        K=list(env.keys())
         K.sort()
         store.update({  'gmt': time.asctime(time.gmtime(time.time())),
                         'platform': sys.platform,
@@ -763,7 +763,7 @@
                         'lcwd': lcwd,
                         'lpcwd': lpcwd,
                         'byteorder': sys.byteorder,
-                        'maxint': sys.maxint,
+                        'maxint': sys.maxsize,
                         'maxint': getattr(sys,'maxunicode','????'),
                         'api_version': getattr(sys,'api_version','????'),
                         'version_info': getattr(sys,'version_info','????'),
@@ -798,11 +798,11 @@
                 except:
                     pass
         module_versions = {}
-        for n,m in sys.modules.items():
+        for n,m in list(sys.modules.items()):
             if n=='reportlab' or n=='rlextra' or n[:10]=='reportlab.' or n[:8]=='rlextra.':
                 v = [getattr(m,x,None) for x in ('__version__','__path__','__file__')]
-                if filter(None,v):
-                    v = [v[0]] + filter(None,v[1:])
+                if [_f for _f in v if _f]:
+                    v = [v[0]] + [_f for _f in v[1:] if _f]
                     module_versions[n] = tuple(v)
         store['__module_versions'] = module_versions
         self.store['__payload'] = {}
@@ -810,7 +810,7 @@
 
     def _add(self,D):
         payload = self.store['__payload']
-        for k, v in D.items():
+        for k, v in list(D.items()):
             payload[k] = v
 
     def add(self,**kw):
@@ -824,7 +824,7 @@
         except:
             S=self.store.copy()
             ff=getStringIO()
-            for k,v in S.iteritems():
+            for k,v in S.items():
                 try:
                     pickle.dump({k:v},ff)
                 except:
@@ -860,7 +860,7 @@
 
     def _show_module_versions(self,k,v):
         self._writeln(k[2:])
-        K = v.keys()
+        K = list(v.keys())
         K.sort()
         for k in K:
             vk = vk0 = v[k]
@@ -917,12 +917,12 @@
                 '__script': _show_file,
                 }
     def show(self):
-        K = self.store.keys()
+        K = list(self.store.keys())
         K.sort()
         for k in K:
-            if k not in self.specials.keys(): self._writeln('%-15s = %s' % (k,self.store[k]))
+            if k not in list(self.specials.keys()): self._writeln('%-15s = %s' % (k,self.store[k]))
         for k in K:
-            if k in self.specials.keys(): self.specials[k](self,k,self.store[k])
+            if k in list(self.specials.keys()): self.specials[k](self,k,self.store[k])
         self._show_extensions()
 
     def payload(self,name):
@@ -1044,12 +1044,12 @@
     extend = itertools.chain([None], items, [None])
     prev, this, next = itertools.tee(extend, 3)
     try:
-        this.next()
-        next.next()
-        next.next()
+        next(this)
+        next(next)
+        next(next)
     except StopIteration:
         pass
-    return itertools.izip(prev, this, next)
+    return zip(prev, this, next)
 
 def commasplit(s):
     '''
@@ -1118,15 +1118,15 @@
     e = -1
     A = list(v.args)
     for i,a in enumerate(A):
-        if isinstance(a,basestring):
+        if isinstance(a,str):
             e = i
             break
     if e>=0:
-        if isinstance(a,unicode):
-            if not isinstance(msg,unicode):
+        if isinstance(a,str):
+            if not isinstance(msg,str):
                 msg=msg.decode(enc)
         else:
-            if isinstance(msg,unicode):
+            if isinstance(msg,str):
                 msg=msg.encode(enc)
             else:
                 msg = str(msg)
@@ -1137,7 +1137,7 @@
     else:
         A.append(msg)
     v.args = tuple(A)
-    raise t,v,b
+    raise t(v).with_traceback(b)
     
 def escapeOnce(data):
     """Ensure XML output is escaped just once, irrespective of input
@@ -1187,7 +1187,7 @@
     '''
     def __new__(cls,v,**kwds):
         self = str.__new__(cls,v)
-        for k,v in kwds.iteritems():
+        for k,v in kwds.items():
             setattr(self,k,v)
         return self
 
--- a/src/reportlab/lib/validators.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/validators.py	Tue Apr 30 14:20:22 2013 +0100
@@ -57,14 +57,14 @@
         try:
             S = string.upper(x)
         except:
-            raise ValueError, 'Must be boolean'
+            raise ValueError('Must be boolean')
         if S in ('YES','TRUE'): return True
         if S in ('NO','FALSE',None): return False
-        raise ValueError, 'Must be boolean'
+        raise ValueError('Must be boolean')
 
 class _isString(Validator):
     def test(self,x):
-        return isinstance(x,(str,unicode))
+        return isinstance(x,str)
 
 class _isCodec(Validator):
     def test(self,x):
@@ -210,7 +210,7 @@
     def __init__(self, enum,*args):
         if type(enum) in [ListType,TupleType]:
             if args!=():
-                raise ValueError, "Either all singleton args or a single sequence argument"
+                raise ValueError("Either all singleton args or a single sequence argument")
             self._enum = tuple(enum)+args
         else:
             self._enum = (enum,)+args
@@ -280,7 +280,7 @@
         self._pattern = re.compile(pattern)
 
     def test(self,x):
-        print 'testing %s against %s' % (x, self._pattern)
+        print('testing %s against %s' % (x, self._pattern))
         if type(x) is StringType:
             text = x
         else:
--- a/src/reportlab/lib/xmllib.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/xmllib.py	Tue Apr 30 14:20:22 2013 +0100
@@ -237,7 +237,7 @@
                     self.lineno = self.lineno + string.count(res.group(0), '\n')
                     continue
             else:
-                raise RuntimeError, 'neither < nor & ??'
+                raise RuntimeError('neither < nor & ??')
             # We get here only if incomplete matches but
             # nothing else
             res = incomplete.match(rawdata, i)
@@ -268,7 +268,7 @@
     def parse_comment(self, i):
         rawdata = self.rawdata
         if rawdata[i:i+4] != '<!--':
-            raise RuntimeError, 'unexpected call to handle_comment'
+            raise RuntimeError('unexpected call to handle_comment')
         res = commentclose.search(rawdata, i+4)
         if not res:
             return -1
@@ -282,7 +282,7 @@
     def parse_cdata(self, i):
         rawdata = self.rawdata
         if rawdata[i:i+9] != '<![CDATA[':
-            raise RuntimeError, 'unexpected call to handle_cdata'
+            raise RuntimeError('unexpected call to handle_cdata')
         res = cdataclose.search(rawdata, i+9)
         if not res:
             return -1
@@ -292,7 +292,7 @@
     def parse_proc(self, i, res):
         rawdata = self.rawdata
         if not res:
-            raise RuntimeError, 'unexpected call to parse_proc'
+            raise RuntimeError('unexpected call to parse_proc')
         name = res.group('proc')
         res = procclose.search(rawdata, res.end(0))
         if not res:
@@ -312,7 +312,7 @@
         attrdict = {}
         res = tagfind.match(rawdata, i+1)
         if not res:
-            raise RuntimeError, 'unexpected call to parse_starttag'
+            raise RuntimeError('unexpected call to parse_starttag')
         k = res.end(0)
         tag = res.group(0)
         if hasattr(self, tag + '_attributes'):
@@ -469,7 +469,7 @@
 
     # Example -- handle relatively harmless syntax errors, could be overridden
     def syntax_error(self, lineno, message):
-        raise RuntimeError, 'Syntax error at line %d: %s' % (lineno, message)
+        raise RuntimeError('Syntax error at line %d: %s' % (lineno, message))
 
     # To be overridden -- handlers for unknown objects
     def unknown_starttag(self, tag, attrs): pass
@@ -648,7 +648,7 @@
 
     # Example -- handle relatively harmless syntax errors, could be overridden
     def syntax_error(self, lineno, message):
-        raise RuntimeError, 'Syntax error at line %d: %s' % (lineno, message)
+        raise RuntimeError('Syntax error at line %d: %s' % (lineno, message))
 
     # To be overridden -- handlers for unknown objects
     def unknown_starttag(self, tag, attrs): pass
@@ -683,51 +683,51 @@
         data = self.testdata
         if data:
             self.testdata = ""
-            print 'data:', repr(data)
+            print('data:', repr(data))
 
     def handle_cdata(self, data):
         self.flush()
-        print 'cdata:', repr(data)
+        print('cdata:', repr(data))
 
     def handle_proc(self, name, data):
         self.flush()
-        print 'processing:',name,repr(data)
+        print('processing:',name,repr(data))
 
     def handle_special(self, data):
         self.flush()
-        print 'special:',repr(data)
+        print('special:',repr(data))
 
     def handle_comment(self, data):
         self.flush()
         r = repr(data)
         if len(r) > 68:
             r = r[:32] + '...' + r[-32:]
-        print 'comment:', r
+        print('comment:', r)
 
     def syntax_error(self, lineno, message):
-        print 'error at line %d:' % lineno, message
+        print('error at line %d:' % lineno, message)
 
     def unknown_starttag(self, tag, attrs):
         self.flush()
         if not attrs:
-            print 'start tag: <' + tag + '>'
+            print('start tag: <' + tag + '>')
         else:
-            print 'start tag: <' + tag,
-            for name, value in attrs.items():
-                print name + '=' + '"' + value + '"',
-            print '>'
+            print('start tag: <' + tag, end=' ')
+            for name, value in list(attrs.items()):
+                print(name + '=' + '"' + value + '"', end=' ')
+            print('>')
 
     def unknown_endtag(self, tag):
         self.flush()
-        print 'end tag: </' + tag + '>'
+        print('end tag: </' + tag + '>')
 
     def unknown_entityref(self, ref):
         self.flush()
-        print '*** unknown entity ref: &' + ref + ';'
+        print('*** unknown entity ref: &' + ref + ';')
 
     def unknown_charref(self, ref):
         self.flush()
-        print '*** unknown char ref: &#' + ref + ';'
+        print('*** unknown char ref: &#' + ref + ';')
 
     def close(self):
         XMLParser.close(self)
@@ -755,8 +755,8 @@
     else:
         try:
             f = open(file, 'r')
-        except IOError, msg:
-            print file, ":", msg
+        except IOError as msg:
+            print(file, ":", msg)
             sys.exit(1)
 
     data = f.read()
--- a/src/reportlab/lib/yaml.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/lib/yaml.py	Tue Apr 30 14:20:22 2013 +0100
@@ -105,7 +105,7 @@
                 #we have to hack the traceback
                 try:
                     getattr(self,cmd)(*args)
-                except TypeError, err:
+                except TypeError as err:
                     sys.stderr.write("Parser method: %s(*%s) %s at line %d\n" % (cmd, args, err, self._lineNo))
                     raise
             else:
--- a/src/reportlab/pdfbase/_can_cmap_data.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/_can_cmap_data.py	Tue Apr 30 14:20:22 2013 +0100
@@ -29,8 +29,8 @@
 
     buf = []
     buf.append('widthsByUnichar = {}')
-    for (fontName, (language, encName)) in defaultUnicodeEncodings.items():
-        print 'handling %s : %s : %s' % (fontName, language, encName)
+    for (fontName, (language, encName)) in list(defaultUnicodeEncodings.items()):
+        print('handling %s : %s : %s' % (fontName, language, encName))
 
         #this does just about all of it for us, as all the info
         #we need is present.
@@ -39,21 +39,21 @@
         widthsByCID = font.face._explicitWidths
         cmap = font.encoding._cmap
         nonStandardWidthsByUnichar = {}
-        for (codePoint, cid) in cmap.items():
+        for (codePoint, cid) in list(cmap.items()):
             width = widthsByCID.get(cid, 1000)
             if width != 1000:
-                nonStandardWidthsByUnichar[unichr(codePoint)] = width
+                nonStandardWidthsByUnichar[chr(codePoint)] = width
         
 
         
-        print 'created font width map (%d items).  ' % len(nonStandardWidthsByUnichar)
+        print('created font width map (%d items).  ' % len(nonStandardWidthsByUnichar))
 
         buf.append('widthsByUnichar["%s"] = %s' % (fontName, repr(nonStandardWidthsByUnichar)))
         
         
     src = '\n'.join(buf) + '\n'
     open('canned_widths.py','w').write(src)
-    print 'wrote canned_widths.py'
+    print('wrote canned_widths.py')
 
 if __name__=='__main__':
     run()
--- a/src/reportlab/pdfbase/_cidfontdata.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/_cidfontdata.py	Tue Apr 30 14:20:22 2013 +0100
@@ -460,12 +460,12 @@
 
 #this data was derived from the above width information and removes all dependency on CMAP files as long as we only use the unicode fonts.
 widthsByUnichar = {}
-widthsByUnichar["MSung-Light"] = {u' ': 250, u'$': 490, u'(': 240, u',': 250, u'0': 500, u'4': 500, u'8': 500, u'<': 667, u'@': 921, u'D': 760, u'H': 802, u'L': 604, u'P': 563, u'T': 698, u'X': 771, u'\\': 520, u'`': 250, u'd': 521, u'h': 531, u'l': 240, u'p': 521, u't': 292, u'x': 479, u'|': 496, u'#': 668, u"'": 250, u'+': 667, u'/': 520, u'3': 500, u'7': 500, u';': 250, u'?': 396, u'C': 719, u'G': 771, u'K': 781, u'O': 823, u'S': 542, u'W': 948, u'[': 344, u'_': 500, u'c': 427, u'g': 469, u'k': 458, u'o': 500, u's': 333, u'w': 677, u'{': 480, u'"': 408, u'&': 698, u'*': 417, u'.': 250, u'2': 500, u'6': 500, u':': 250, u'>': 667, u'B': 615, u'F': 552, u'J': 354, u'N': 750, u'R': 729, u'V': 729, u'Z': 635, u'^': 469, u'b': 521, u'f': 271, u'j': 250, u'n': 531, u'r': 365, u'v': 458, u'z': 427, u'~': 667, u'!': 250, u'%': 875, u')': 240, u'-': 313, u'1': 500, u'5': 500, u'9': 500, u'=': 667, u'A': 677, u'E': 625, u'I': 354, u'M': 927, u'Q': 823, u'U': 771, u'Y': 677, u']': 344, u'a': 469, u'e': 438, u'i': 250, u'm': 802, u'q': 521, u'u': 521, u'y': 458, u'}': 480}
-widthsByUnichar["HeiseiKakuGo-W5"] = {u'\uff81': 500, u'\uff85': 500, u'\uff89': 500, u'\uff8d': 500, u'\uff91': 500, u'\uff95': 500, u'\uff99': 500, u'\uff9d': 500, u' ': 277, u'$': 668, u'(': 445, u',': 305, u'0': 668, u'\u0332': 668, u'4': 668, u'8': 668, u'<': 668, u'@': 871, u'D': 699, u'H': 687, u'L': 582, u'P': 582, u'T': 641, u'X': 609, u'`': 590, u'\uff62': 500, u'd': 602, u'\uff66': 500, u'h': 582, u'\uff6a': 500, u'l': 234, u'\uff6e': 500, u'p': 602, u'\uff72': 500, u't': 441, u'\uff76': 500, u'x': 531, u'\uff7a': 500, u'|': 246, u'\uff7e': 500, u'\uff82': 500, u'\uff86': 500, u'\uff8a': 500, u'\uff8e': 500, u'\uff92': 500, u'\uff96': 500, u'\uff9a': 500, u'\uff9e': 500, u'#': 668, u"'": 305, u'+': 668, u'/': 539, u'3': 668, u'7': 668, u';': 305, u'?': 566, u'C': 652, u'G': 676, u'K': 664, u'O': 734, u'S': 605, u'W': 945, u'[': 445, u'_': 668, u'\uff61': 500, u'c': 547, u'\uff65': 500, u'g': 609, u'\uff69': 500, u'k': 539, u'\uff6d': 500, u'o': 605, u'\uff71': 500, u's': 508, u'\uff75': 500, u'w': 781, u'\uff79': 500, u'{': 449, u'\uff7d': 500, u'\u0300': 590, u'\uff83': 500, u'\u2002': 500, u'\uff87': 500, u'\uff8b': 500, u'\uff8f': 500, u'\uff93': 500, u'\uff97': 500, u'\uff9b': 500, u'\uff9f': 500, u'"': 500, u'\xa5': 668, u'&': 727, u'*': 508, u'.': 305, u'2': 668, u'6': 668, u':': 305, u'>': 668, u'B': 637, u'F': 555, u'J': 492, u'N': 707, u'\u203e': 500, u'R': 605, u'V': 727, u'Z': 574, u'^': 668, u'b': 609, u'\uff64': 500, u'f': 391, u'\uff68': 500, u'j': 277, u'\uff6c': 500, u'n': 582, u'\uff70': 500, u'r': 387, u'\uff74': 500, u'v': 562, u'\uff78': 500, u'z': 555, u'\uff7c': 500, u'~': 668, u'\uff80': 500, u'\u0303': 668, u'\uff84': 500, u'\uff88': 500, u'\uff8c': 500, u'\u2011': 379, u'\uff90': 500, u'\uff94': 500, u'\uff98': 500, u'\uff9c': 500, u'!': 305, u'%': 906, u')': 445, u'-': 379, u'1': 668, u'5': 668, u'9': 668, u'=': 668, u'A': 727, u'E': 574, u'I': 242, u'M': 789, u'Q': 734, u'U': 668, u'Y': 609, u']': 445, u'a': 555, u'\uff63': 500, u'e': 574, u'\uff67': 500, u'i': 234, u'\uffe8': 500, u'\uff6b': 500, u'm': 895, u'\uff6f': 500, u'q': 602, u'\uff73': 500, u'u': 582, u'\uff77': 500, u'y': 570, u'\uff7b': 500, u'}': 449, u'\uff7f': 500}
-widthsByUnichar["HYSMyeongJo-Medium"] = {u' ': 333, u'$': 625, u'(': 500, u',': 291, u'0': 625, u'4': 625, u'8': 625, u'<': 833, u'D': 750, u'H': 791, u'L': 666, u'P': 666, u'T': 791, u'X': 708, u'\\': 375, u'`': 333, u'd': 583, u'h': 583, u'l': 291, u'p': 583, u't': 375, u'x': 625, u'|': 583, u'#': 833, u"'": 250, u'+': 833, u'/': 375, u'3': 625, u'7': 625, u';': 333, u'?': 500, u'C': 708, u'G': 750, u'K': 791, u'O': 750, u'S': 666, u'[': 500, u'_': 500, u'c': 541, u'g': 583, u'k': 583, u'o': 583, u's': 541, u'w': 833, u'{': 583, u'"': 416, u'&': 833, u'*': 500, u'.': 291, u'2': 625, u'6': 625, u':': 333, u'>': 916, u'B': 708, u'F': 666, u'J': 500, u'N': 791, u'R': 708, u'V': 750, u'Z': 666, u'^': 500, u'b': 583, u'f': 375, u'j': 333, u'n': 583, u'r': 458, u'v': 583, u'z': 500, u'~': 750, u'!': 416, u'%': 916, u')': 500, u'-': 833, u'1': 625, u'5': 625, u'9': 625, u'=': 833, u'A': 791, u'E': 708, u'I': 375, u'M': 916, u'Q': 750, u'U': 791, u'Y': 708, u']': 500, u'a': 541, u'e': 583, u'i': 291, u'm': 875, u'q': 583, u'u': 583, u'y': 625, u'}': 583}
-widthsByUnichar["STSong-Light"] = {u' ': 207, u'$': 462, u'(': 374, u',': 238, u'0': 462, u'4': 462, u'8': 462, u'<': 605, u'@': 748, u'D': 739, u'H': 793, u'L': 526, u'P': 544, u'T': 607, u'X': 647, u'\\': 333, u'`': 239, u'd': 529, u'h': 518, u'l': 228, u'p': 524, u't': 277, u'x': 466, u'|': 258, u'#': 467, u"'": 239, u'+': 605, u'/': 334, u'3': 462, u'7': 462, u';': 238, u'?': 344, u'C': 695, u'G': 729, u'K': 666, u'O': 772, u'S': 465, u'W': 972, u'[': 374, u'_': 500, u'c': 427, u'g': 444, u'k': 495, u'o': 524, u's': 336, u'w': 652, u'{': 370, u'"': 342, u'&': 710, u'*': 423, u'.': 238, u'2': 462, u'6': 462, u':': 238, u'>': 605, u'B': 560, u'F': 511, u'J': 312, u'N': 758, u'R': 628, u'V': 711, u'Z': 607, u'^': 606, u'b': 503, u'f': 264, u'j': 230, u'n': 527, u'r': 338, u'v': 450, u'z': 407, u'~': 605, u'!': 270, u'%': 797, u')': 374, u'-': 375, u'1': 462, u'5': 462, u'9': 462, u'=': 605, u'A': 684, u'E': 563, u'I': 318, u'M': 896, u'Q': 772, u'U': 753, u'Y': 620, u']': 374, u'a': 417, u'e': 415, u'i': 241, u'm': 793, u'q': 504, u'u': 517, u'y': 452, u'}': 370}
-widthsByUnichar["HeiseiMin-W3"] = {u'\uff81': 500, u'\u0302': 333, u'\uff85': 500, u'\u0306': 333, u'\uff89': 500, u'\u030a': 333, u'\uff8d': 500, u'\uff91': 500, u'\ufb02': 556, u'\uff95': 500, u'\uff99': 500, u'\uff9d': 500, u' ': 250, u'\xa3': 500, u'\u2122': 980, u'$': 500, u'(': 333, u'\xab': 500, u',': 250, u'\xaf': 333, u'0': 500, u'\xb3': 300, u'\u0332': 500, u'4': 500, u'\xb7': 250, u'8': 500, u'\xbb': 500, u'<': 564, u'\xbf': 444, u'@': 921, u'\xc3': 722, u'\u0142': 278, u'D': 722, u'\xc7': 667, u'H': 722, u'\xcb': 611, u'L': 611, u'\xcf': 333, u'P': 556, u'\xd3': 722, u'\u0152': 889, u'T': 611, u'X': 722, u'\xdb': 722, u'\\': 278, u'\xdf': 500, u'\uff64': 500, u'`': 333, u'\xe3': 444, u'\uff62': 500, u'd': 500, u'\xe7': 444, u'\uff66': 500, u'h': 500, u'\xeb': 444, u'\uff6a': 500, u'l': 278, u'\xef': 278, u'\uff6e': 500, u'p': 500, u'\xf3': 500, u'\uff72': 500, u't': 278, u'\uff76': 500, u'x': 500, u'\xfb': 500, u'\uff7a': 500, u'|': 200, u'\xff': 500, u'\u017e': 444, u'\u0301': 333, u'\uff82': 500, u'\u0305': 500, u'\uff86': 500, u'\uff8a': 500, u'\uff8e': 500, u'\u2013': 500, u'\uff92': 500, u'\uff96': 500, u'\uff9a': 500, u'\uff9e': 500, u'#': 500, u'\xa4': 500, u"'": 180, u'\u203a': 333, u'+': 564, u'\xac': 564, u'/': 278, u'\u0131': 278, u'3': 500, u'7': 500, u'\xb8': 333, u';': 278, u'\xbc': 750, u'?': 444, u'\u0141': 611, u'\xc0': 722, u'C': 667, u'\xc4': 722, u'G': 722, u'\xc8': 611, u'K': 722, u'\xcc': 333, u'O': 722, u'\xd0': 722, u'S': 556, u'\u2022': 350, u'\xd4': 722, u'W': 944, u'\uff78': 500, u'\xd8': 722, u'[': 333, u'\xdc': 722, u'_': 500, u'\u0161': 389, u'\xe0': 444, u'c': 444, u'\uff65': 500, u'\xe4': 444, u'g': 500, u'\uff69': 500, u'\xe8': 444, u'k': 500, u'\uff6d': 500, u'\xec': 278, u'o': 500, u'\uff71': 500, u'\xf0': 500, u's': 389, u'\uff75': 500, u'\xf4': 500, u'w': 722, u'\uff79': 500, u'\xf8': 500, u'{': 480, u'\uff7e': 500, u'\u017d': 611, u'\xfc': 500, u'\u0300': 333, u'\uff83': 500, u'\u2002': 500, u'\u0304': 333, u'\uff87': 500, u'\u0308': 333, u'\uff8b': 500, u'\u030c': 333, u'\uff8f': 500, u'\uff93': 500, u'\u2012': 500, u'\uff97': 500, u'\uff9b': 500, u'\u201a': 333, u'\uff9f': 500, u'\u201e': 444, u'\xa1': 333, u'"': 408, u'\xa5': 500, u'&': 778, u'\xa9': 760, u'\u0328': 333, u'*': 500, u'\xad': 564, u'.': 250, u'\uffe8': 500, u'2': 500, u'\xb5': 500, u'6': 500, u'\xb9': 300, u':': 278, u'\xbd': 750, u'>': 564, u'\xc1': 722, u'\uff61': 500, u'B': 667, u'\xc5': 722, u'F': 556, u'\xc9': 611, u'J': 389, u'\xcd': 333, u'N': 722, u'\xd1': 722, u'\u203e': 500, u'R': 667, u'\xd5': 722, u'V': 722, u'\xd9': 722, u'Z': 611, u'\xdd': 722, u'^': 469, u'\xe1': 444, u'\u0160': 556, u'b': 500, u'\xe5': 444, u'\u2039': 333, u'f': 333, u'\xe9': 444, u'\uff68': 500, u'j': 278, u'\xed': 278, u'\uff6c': 500, u'n': 500, u'\xf1': 500, u'\uff70': 500, u'r': 333, u'\xf5': 500, u'\uff74': 500, u'v': 500, u'\xf9': 500, u'\u0178': 722, u'z': 444, u'\xfd': 500, u'\uff7c': 500, u'~': 333, u'\uff80': 500, u'\u0303': 333, u'\uff84': 500, u'\u0307': 333, u'\uff88': 500, u'\u030b': 333, u'\uff8c': 500, u'\u2011': 333, u'\uff90': 500, u'\uff94': 500, u'\uff98': 500, u'\uff9c': 500, u'\u2044': 167, u'!': 333, u'\xa2': 500, u'%': 833, u'\u0327': 333, u'\xa6': 200, u')': 333, u'\xaa': 276, u'-': 333, u'\xae': 760, u'1': 500, u'\xb2': 300, u'5': 500, u'9': 500, u'\xba': 310, u'=': 564, u'\xbe': 750, u'A': 722, u'\u01c0': 200, u'\xc2': 722, u'E': 611, u'\xc6': 889, u'I': 333, u'\xca': 611, u'M': 889, u'\xce': 333, u'Q': 722, u'\u0153': 722, u'\xd2': 722, u'U': 722, u'\xd6': 722, u'Y': 722, u'\ufb01': 556, u'\xda': 722, u']': 333, u'\xde': 556, u'a': 444, u'\uff63': 500, u'\xe2': 444, u'e': 444, u'\uff67': 500, u'\xe6': 667, u'i': 278, u'\uff7d': 500, u'\uff6b': 500, u'\xea': 444, u'm': 778, u'\uff6f': 500, u'\xee': 278, u'q': 500, u'\uff73': 500, u'\xf2': 500, u'u': 500, u'\uff77': 500, u'\xf6': 500, u'y': 500, u'\uff7b': 500, u'\xfa': 500, u'}': 480, u'\uff7f': 500, u'\xfe': 500}
-widthsByUnichar["HYGothic-Medium"] = {u' ': 500, u'$': 500, u'(': 500, u',': 500, u'0': 500, u'4': 500, u'8': 500, u'<': 500, u'@': 500, u'D': 500, u'H': 500, u'L': 500, u'P': 500, u'T': 500, u'X': 500, u'\\': 500, u'`': 500, u'd': 500, u'h': 500, u'l': 500, u'p': 500, u't': 500, u'x': 500, u'|': 500, u'#': 500, u"'": 500, u'+': 500, u'/': 500, u'3': 500, u'7': 500, u';': 500, u'?': 500, u'C': 500, u'G': 500, u'K': 500, u'O': 500, u'S': 500, u'W': 500, u'[': 500, u'_': 500, u'c': 500, u'g': 500, u'k': 500, u'o': 500, u's': 500, u'w': 500, u'{': 500, u'"': 500, u'&': 500, u'*': 500, u'.': 500, u'2': 500, u'6': 500, u':': 500, u'>': 500, u'B': 500, u'F': 500, u'J': 500, u'N': 500, u'R': 500, u'V': 500, u'Z': 500, u'^': 500, u'b': 500, u'f': 500, u'j': 500, u'n': 500, u'r': 500, u'v': 500, u'z': 500, u'!': 500, u'%': 500, u')': 500, u'-': 500, u'1': 500, u'5': 500, u'9': 500, u'=': 500, u'A': 500, u'E': 500, u'I': 500, u'M': 500, u'Q': 500, u'U': 500, u'Y': 500, u']': 500, u'a': 500, u'e': 500, u'i': 500, u'm': 500, u'q': 500, u'u': 500, u'y': 500, u'}': 500}
+widthsByUnichar["MSung-Light"] = {' ': 250, '$': 490, '(': 240, ',': 250, '0': 500, '4': 500, '8': 500, '<': 667, '@': 921, 'D': 760, 'H': 802, 'L': 604, 'P': 563, 'T': 698, 'X': 771, '\\': 520, '`': 250, 'd': 521, 'h': 531, 'l': 240, 'p': 521, 't': 292, 'x': 479, '|': 496, '#': 668, "'": 250, '+': 667, '/': 520, '3': 500, '7': 500, ';': 250, '?': 396, 'C': 719, 'G': 771, 'K': 781, 'O': 823, 'S': 542, 'W': 948, '[': 344, '_': 500, 'c': 427, 'g': 469, 'k': 458, 'o': 500, 's': 333, 'w': 677, '{': 480, '"': 408, '&': 698, '*': 417, '.': 250, '2': 500, '6': 500, ':': 250, '>': 667, 'B': 615, 'F': 552, 'J': 354, 'N': 750, 'R': 729, 'V': 729, 'Z': 635, '^': 469, 'b': 521, 'f': 271, 'j': 250, 'n': 531, 'r': 365, 'v': 458, 'z': 427, '~': 667, '!': 250, '%': 875, ')': 240, '-': 313, '1': 500, '5': 500, '9': 500, '=': 667, 'A': 677, 'E': 625, 'I': 354, 'M': 927, 'Q': 823, 'U': 771, 'Y': 677, ']': 344, 'a': 469, 'e': 438, 'i': 250, 'm': 802, 'q': 521, 'u': 521, 'y': 458, '}': 480}
+widthsByUnichar["HeiseiKakuGo-W5"] = {'\uff81': 500, '\uff85': 500, '\uff89': 500, '\uff8d': 500, '\uff91': 500, '\uff95': 500, '\uff99': 500, '\uff9d': 500, ' ': 277, '$': 668, '(': 445, ',': 305, '0': 668, '\u0332': 668, '4': 668, '8': 668, '<': 668, '@': 871, 'D': 699, 'H': 687, 'L': 582, 'P': 582, 'T': 641, 'X': 609, '`': 590, '\uff62': 500, 'd': 602, '\uff66': 500, 'h': 582, '\uff6a': 500, 'l': 234, '\uff6e': 500, 'p': 602, '\uff72': 500, 't': 441, '\uff76': 500, 'x': 531, '\uff7a': 500, '|': 246, '\uff7e': 500, '\uff82': 500, '\uff86': 500, '\uff8a': 500, '\uff8e': 500, '\uff92': 500, '\uff96': 500, '\uff9a': 500, '\uff9e': 500, '#': 668, "'": 305, '+': 668, '/': 539, '3': 668, '7': 668, ';': 305, '?': 566, 'C': 652, 'G': 676, 'K': 664, 'O': 734, 'S': 605, 'W': 945, '[': 445, '_': 668, '\uff61': 500, 'c': 547, '\uff65': 500, 'g': 609, '\uff69': 500, 'k': 539, '\uff6d': 500, 'o': 605, '\uff71': 500, 's': 508, '\uff75': 500, 'w': 781, '\uff79': 500, '{': 449, '\uff7d': 500, '\u0300': 590, '\uff83': 500, '\u2002': 500, '\uff87': 500, '\uff8b': 500, '\uff8f': 500, '\uff93': 500, '\uff97': 500, '\uff9b': 500, '\uff9f': 500, '"': 500, '\xa5': 668, '&': 727, '*': 508, '.': 305, '2': 668, '6': 668, ':': 305, '>': 668, 'B': 637, 'F': 555, 'J': 492, 'N': 707, '\u203e': 500, 'R': 605, 'V': 727, 'Z': 574, '^': 668, 'b': 609, '\uff64': 500, 'f': 391, '\uff68': 500, 'j': 277, '\uff6c': 500, 'n': 582, '\uff70': 500, 'r': 387, '\uff74': 500, 'v': 562, '\uff78': 500, 'z': 555, '\uff7c': 500, '~': 668, '\uff80': 500, '\u0303': 668, '\uff84': 500, '\uff88': 500, '\uff8c': 500, '\u2011': 379, '\uff90': 500, '\uff94': 500, '\uff98': 500, '\uff9c': 500, '!': 305, '%': 906, ')': 445, '-': 379, '1': 668, '5': 668, '9': 668, '=': 668, 'A': 727, 'E': 574, 'I': 242, 'M': 789, 'Q': 734, 'U': 668, 'Y': 609, ']': 445, 'a': 555, '\uff63': 500, 'e': 574, '\uff67': 500, 'i': 234, '\uffe8': 500, '\uff6b': 500, 'm': 895, '\uff6f': 500, 'q': 602, '\uff73': 500, 'u': 582, '\uff77': 500, 'y': 570, '\uff7b': 500, '}': 449, '\uff7f': 500}
+widthsByUnichar["HYSMyeongJo-Medium"] = {' ': 333, '$': 625, '(': 500, ',': 291, '0': 625, '4': 625, '8': 625, '<': 833, 'D': 750, 'H': 791, 'L': 666, 'P': 666, 'T': 791, 'X': 708, '\\': 375, '`': 333, 'd': 583, 'h': 583, 'l': 291, 'p': 583, 't': 375, 'x': 625, '|': 583, '#': 833, "'": 250, '+': 833, '/': 375, '3': 625, '7': 625, ';': 333, '?': 500, 'C': 708, 'G': 750, 'K': 791, 'O': 750, 'S': 666, '[': 500, '_': 500, 'c': 541, 'g': 583, 'k': 583, 'o': 583, 's': 541, 'w': 833, '{': 583, '"': 416, '&': 833, '*': 500, '.': 291, '2': 625, '6': 625, ':': 333, '>': 916, 'B': 708, 'F': 666, 'J': 500, 'N': 791, 'R': 708, 'V': 750, 'Z': 666, '^': 500, 'b': 583, 'f': 375, 'j': 333, 'n': 583, 'r': 458, 'v': 583, 'z': 500, '~': 750, '!': 416, '%': 916, ')': 500, '-': 833, '1': 625, '5': 625, '9': 625, '=': 833, 'A': 791, 'E': 708, 'I': 375, 'M': 916, 'Q': 750, 'U': 791, 'Y': 708, ']': 500, 'a': 541, 'e': 583, 'i': 291, 'm': 875, 'q': 583, 'u': 583, 'y': 625, '}': 583}
+widthsByUnichar["STSong-Light"] = {' ': 207, '$': 462, '(': 374, ',': 238, '0': 462, '4': 462, '8': 462, '<': 605, '@': 748, 'D': 739, 'H': 793, 'L': 526, 'P': 544, 'T': 607, 'X': 647, '\\': 333, '`': 239, 'd': 529, 'h': 518, 'l': 228, 'p': 524, 't': 277, 'x': 466, '|': 258, '#': 467, "'": 239, '+': 605, '/': 334, '3': 462, '7': 462, ';': 238, '?': 344, 'C': 695, 'G': 729, 'K': 666, 'O': 772, 'S': 465, 'W': 972, '[': 374, '_': 500, 'c': 427, 'g': 444, 'k': 495, 'o': 524, 's': 336, 'w': 652, '{': 370, '"': 342, '&': 710, '*': 423, '.': 238, '2': 462, '6': 462, ':': 238, '>': 605, 'B': 560, 'F': 511, 'J': 312, 'N': 758, 'R': 628, 'V': 711, 'Z': 607, '^': 606, 'b': 503, 'f': 264, 'j': 230, 'n': 527, 'r': 338, 'v': 450, 'z': 407, '~': 605, '!': 270, '%': 797, ')': 374, '-': 375, '1': 462, '5': 462, '9': 462, '=': 605, 'A': 684, 'E': 563, 'I': 318, 'M': 896, 'Q': 772, 'U': 753, 'Y': 620, ']': 374, 'a': 417, 'e': 415, 'i': 241, 'm': 793, 'q': 504, 'u': 517, 'y': 452, '}': 370}
+widthsByUnichar["HeiseiMin-W3"] = {'\uff81': 500, '\u0302': 333, '\uff85': 500, '\u0306': 333, '\uff89': 500, '\u030a': 333, '\uff8d': 500, '\uff91': 500, '\ufb02': 556, '\uff95': 500, '\uff99': 500, '\uff9d': 500, ' ': 250, '\xa3': 500, '\u2122': 980, '$': 500, '(': 333, '\xab': 500, ',': 250, '\xaf': 333, '0': 500, '\xb3': 300, '\u0332': 500, '4': 500, '\xb7': 250, '8': 500, '\xbb': 500, '<': 564, '\xbf': 444, '@': 921, '\xc3': 722, '\u0142': 278, 'D': 722, '\xc7': 667, 'H': 722, '\xcb': 611, 'L': 611, '\xcf': 333, 'P': 556, '\xd3': 722, '\u0152': 889, 'T': 611, 'X': 722, '\xdb': 722, '\\': 278, '\xdf': 500, '\uff64': 500, '`': 333, '\xe3': 444, '\uff62': 500, 'd': 500, '\xe7': 444, '\uff66': 500, 'h': 500, '\xeb': 444, '\uff6a': 500, 'l': 278, '\xef': 278, '\uff6e': 500, 'p': 500, '\xf3': 500, '\uff72': 500, 't': 278, '\uff76': 500, 'x': 500, '\xfb': 500, '\uff7a': 500, '|': 200, '\xff': 500, '\u017e': 444, '\u0301': 333, '\uff82': 500, '\u0305': 500, '\uff86': 500, '\uff8a': 500, '\uff8e': 500, '\u2013': 500, '\uff92': 500, '\uff96': 500, '\uff9a': 500, '\uff9e': 500, '#': 500, '\xa4': 500, "'": 180, '\u203a': 333, '+': 564, '\xac': 564, '/': 278, '\u0131': 278, '3': 500, '7': 500, '\xb8': 333, ';': 278, '\xbc': 750, '?': 444, '\u0141': 611, '\xc0': 722, 'C': 667, '\xc4': 722, 'G': 722, '\xc8': 611, 'K': 722, '\xcc': 333, 'O': 722, '\xd0': 722, 'S': 556, '\u2022': 350, '\xd4': 722, 'W': 944, '\uff78': 500, '\xd8': 722, '[': 333, '\xdc': 722, '_': 500, '\u0161': 389, '\xe0': 444, 'c': 444, '\uff65': 500, '\xe4': 444, 'g': 500, '\uff69': 500, '\xe8': 444, 'k': 500, '\uff6d': 500, '\xec': 278, 'o': 500, '\uff71': 500, '\xf0': 500, 's': 389, '\uff75': 500, '\xf4': 500, 'w': 722, '\uff79': 500, '\xf8': 500, '{': 480, '\uff7e': 500, '\u017d': 611, '\xfc': 500, '\u0300': 333, '\uff83': 500, '\u2002': 500, '\u0304': 333, '\uff87': 500, '\u0308': 333, '\uff8b': 500, '\u030c': 333, '\uff8f': 500, '\uff93': 500, '\u2012': 500, '\uff97': 500, '\uff9b': 500, '\u201a': 333, '\uff9f': 500, '\u201e': 444, '\xa1': 333, '"': 408, '\xa5': 500, '&': 778, '\xa9': 760, '\u0328': 333, '*': 500, '\xad': 564, '.': 250, '\uffe8': 500, '2': 500, '\xb5': 500, '6': 500, '\xb9': 300, ':': 278, '\xbd': 750, '>': 564, '\xc1': 722, '\uff61': 500, 'B': 667, '\xc5': 722, 'F': 556, '\xc9': 611, 'J': 389, '\xcd': 333, 'N': 722, '\xd1': 722, '\u203e': 500, 'R': 667, '\xd5': 722, 'V': 722, '\xd9': 722, 'Z': 611, '\xdd': 722, '^': 469, '\xe1': 444, '\u0160': 556, 'b': 500, '\xe5': 444, '\u2039': 333, 'f': 333, '\xe9': 444, '\uff68': 500, 'j': 278, '\xed': 278, '\uff6c': 500, 'n': 500, '\xf1': 500, '\uff70': 500, 'r': 333, '\xf5': 500, '\uff74': 500, 'v': 500, '\xf9': 500, '\u0178': 722, 'z': 444, '\xfd': 500, '\uff7c': 500, '~': 333, '\uff80': 500, '\u0303': 333, '\uff84': 500, '\u0307': 333, '\uff88': 500, '\u030b': 333, '\uff8c': 500, '\u2011': 333, '\uff90': 500, '\uff94': 500, '\uff98': 500, '\uff9c': 500, '\u2044': 167, '!': 333, '\xa2': 500, '%': 833, '\u0327': 333, '\xa6': 200, ')': 333, '\xaa': 276, '-': 333, '\xae': 760, '1': 500, '\xb2': 300, '5': 500, '9': 500, '\xba': 310, '=': 564, '\xbe': 750, 'A': 722, '\u01c0': 200, '\xc2': 722, 'E': 611, '\xc6': 889, 'I': 333, '\xca': 611, 'M': 889, '\xce': 333, 'Q': 722, '\u0153': 722, '\xd2': 722, 'U': 722, '\xd6': 722, 'Y': 722, '\ufb01': 556, '\xda': 722, ']': 333, '\xde': 556, 'a': 444, '\uff63': 500, '\xe2': 444, 'e': 444, '\uff67': 500, '\xe6': 667, 'i': 278, '\uff7d': 500, '\uff6b': 500, '\xea': 444, 'm': 778, '\uff6f': 500, '\xee': 278, 'q': 500, '\uff73': 500, '\xf2': 500, 'u': 500, '\uff77': 500, '\xf6': 500, 'y': 500, '\uff7b': 500, '\xfa': 500, '}': 480, '\uff7f': 500, '\xfe': 500}
+widthsByUnichar["HYGothic-Medium"] = {' ': 500, '$': 500, '(': 500, ',': 500, '0': 500, '4': 500, '8': 500, '<': 500, '@': 500, 'D': 500, 'H': 500, 'L': 500, 'P': 500, 'T': 500, 'X': 500, '\\': 500, '`': 500, 'd': 500, 'h': 500, 'l': 500, 'p': 500, 't': 500, 'x': 500, '|': 500, '#': 500, "'": 500, '+': 500, '/': 500, '3': 500, '7': 500, ';': 500, '?': 500, 'C': 500, 'G': 500, 'K': 500, 'O': 500, 'S': 500, 'W': 500, '[': 500, '_': 500, 'c': 500, 'g': 500, 'k': 500, 'o': 500, 's': 500, 'w': 500, '{': 500, '"': 500, '&': 500, '*': 500, '.': 500, '2': 500, '6': 500, ':': 500, '>': 500, 'B': 500, 'F': 500, 'J': 500, 'N': 500, 'R': 500, 'V': 500, 'Z': 500, '^': 500, 'b': 500, 'f': 500, 'j': 500, 'n': 500, 'r': 500, 'v': 500, 'z': 500, '!': 500, '%': 500, ')': 500, '-': 500, '1': 500, '5': 500, '9': 500, '=': 500, 'A': 500, 'E': 500, 'I': 500, 'M': 500, 'Q': 500, 'U': 500, 'Y': 500, ']': 500, 'a': 500, 'e': 500, 'i': 500, 'm': 500, 'q': 500, 'u': 500, 'y': 500, '}': 500}
 
 
 #shift-jis saying 'This is Heisei-Minchou'
--- a/src/reportlab/pdfbase/_fontdata.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/_fontdata.py	Tue Apr 30 14:20:22 2013 +0100
@@ -88,8 +88,8 @@
                 'courier-oblique': 'Courier-Oblique',
                 }
     _font2fnrMap = _font2fnrMapLinux2
-    for k, v in _font2fnrMap.items():
-        if k in _font2fnrMapWin32.keys():
+    for k, v in list(_font2fnrMap.items()):
+        if k in list(_font2fnrMapWin32.keys()):
             _font2fnrMapWin32[v.lower()] = _font2fnrMapWin32[k]
     del k, v
 else:
@@ -137,7 +137,7 @@
         y = x.lower()
         if y[-8:]=='encoding': y = y[:-8]
         y = self._XMap[y]
-        if y in self.keys(): raise IndexError, 'Encoding %s is already set' % y
+        if y in list(self.keys()): raise IndexError('Encoding %s is already set' % y)
         self.data[y] = v
 
     def __getitem__(self,x):
@@ -196,7 +196,7 @@
             widthsByFontGlyph=widthsByFontGlyph.copy(),
             )
         ):
-    for k,v in initial_dicts.iteritems():
+    for k,v in initial_dicts.items():
         d=globals()[k]
         d.clear()
         d.update(v)
--- a/src/reportlab/pdfbase/cidfonts.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/cidfonts.py	Tue Apr 30 14:20:22 2013 +0100
@@ -40,13 +40,13 @@
         if os.path.isfile(cmapfile):
             #print "found", cmapfile
             return cmapfile
-    raise IOError, 'CMAP file for encodings "%s" not found!' % name
+    raise IOError('CMAP file for encodings "%s" not found!' % name)
 
 def structToPDF(structure):
     "Converts deeply nested structure to PDFdoc dictionary/array objects"
     if type(structure) is DictType:
         newDict = {}
-        for k, v in structure.items():
+        for k, v in list(structure.items()):
             newDict[k] = structToPDF(v)
         return pdfdoc.PDFDictionary(newDict)
     elif type(structure) in (ListType, TupleType):
@@ -241,9 +241,8 @@
         try:
             fontDict = CIDFontInfo[name]
         except KeyError:
-            raise KeyError, ("Unable to find information on CID typeface '%s'" % name +
-                            "Only the following font names work:" + repr(allowedTypeFaces)
-                             )
+            raise KeyError("Unable to find information on CID typeface '%s'" % name +
+                            "Only the following font names work:" + repr(allowedTypeFaces))
         descFont = fontDict['DescendantFonts'][0]
         self.ascent = descFont['FontDescriptor']['Ascent']
         self.descent = descFont['FontDescriptor']['Descent']
@@ -422,7 +421,7 @@
         #these ones should be encoded asUTF16 minus the BOM
         from codecs import utf_16_be_encode
         #print 'formatting %s: %s' % (type(text), repr(text))
-        if type(text) is not unicode:
+        if type(text) is not str:
             text = text.decode('utf8')
         utfText = utf_16_be_encode(text)[0]
         encoded = _escape(utfText)
@@ -454,10 +453,10 @@
         try:
             enc = CIDEncoding(file)
         except:
-            print 'cannot parse %s, skipping' % enc
+            print('cannot parse %s, skipping' % enc)
             continue
         enc.fastSave(cmapdir)
-        print 'saved %s.fastmap' % file
+        print('saved %s.fastmap' % file)
 
 def test():
     # only works if you have cirrect encodings on your box!
@@ -477,7 +476,7 @@
     message1 = '\202\261\202\352\202\315\225\275\220\254\226\276\222\251\202\305\202\267\201B'
     c.drawString(100, 675, message1)
     c.save()
-    print 'saved test_japanese.pdf'
+    print('saved test_japanese.pdf')
 
 
 ##    print 'CMAP_DIR = ', CMAP_DIR
@@ -489,10 +488,10 @@
 
     encName = '90ms-RKSJ-H'
     enc = CIDEncoding(encName)
-    print message1, '->', enc.translate(message1)
+    print(message1, '->', enc.translate(message1))
 
     f = CIDFont('HeiseiMin-W3','90ms-RKSJ-H')
-    print 'width = %0.2f' % f.stringWidth(message1, 10)
+    print('width = %0.2f' % f.stringWidth(message1, 10))
 
 
     #testing all encodings
@@ -511,7 +510,7 @@
 
 if __name__=='__main__':
     import doctest
-    import cidfonts
+    from . import cidfonts
     doctest.testmod(cidfonts)
     #test()
 
--- a/src/reportlab/pdfbase/pdfdoc.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/pdfdoc.py	Tue Apr 30 14:20:22 2013 +0100
@@ -39,10 +39,10 @@
     def list(sequence):
         def f(x):
             return x
-        return map(f, sequence)
+        return list(map(f, sequence))
 
 def utf8str(x):
-    if isinstance(x,unicode):
+    if isinstance(x,str):
         return x.encode('utf8')
     else:
         return str(x)
@@ -240,7 +240,7 @@
             if os.name=='mac':
                 from reportlab.lib.utils import markfilename
                 markfilename(filename) # do platform specific file junk
-        if getattr(canvas,'_verbosity',None): print 'saved', filename
+        if getattr(canvas,'_verbosity',None): print('saved', filename)
 
     def GetPDFData(self, canvas):
         # realize delayed fonts
@@ -261,7 +261,7 @@
         """specify the current object as a page (enables reference binding and other page features)"""
         if self.inObject is not None:
             if self.inObject=="page": return
-            raise ValueError, "can't go in page already in object %s" % self.inObject
+            raise ValueError("can't go in page already in object %s" % self.inObject)
         self.inObject = "page"
 
     def inForm(self):
@@ -392,9 +392,9 @@
         self.info._dateFormatter = dateFormatter
 
     def getAvailableFonts(self):
-        fontnames = self.fontMapping.keys()
+        fontnames = list(self.fontMapping.keys())
         # the standard 14 are also always available! (even if not initialized yet)
-        import _fontdata
+        from . import _fontdata
         for name in _fontdata.standardFonts:
             if name not in fontnames:
                 fontnames.append(name)
@@ -450,7 +450,7 @@
         # sanity checks (must happen AFTER formatting)
         lno = len(numbertoid)
         if counter-1!=lno:
-            raise ValueError, "counter %s doesn't match number to id dictionary %s" %(counter, lno)
+            raise ValueError("counter %s doesn't match number to id dictionary %s" %(counter, lno))
         # now add the xref
         xref = PDFCrossReferenceTable()
         xref.addsection(0, ids)
@@ -491,7 +491,7 @@
                 # externally defined form
                 return list(theform.dictionary.dict[boxType].sequence)
             else:
-                raise ValueError, "I don't understand the form instance %s" % repr(name)
+                raise ValueError("I don't understand the form instance %s" % repr(name))
 
     def getXObjectName(self, name):
         """Lets canvas find out what form is called internally.
@@ -521,10 +521,10 @@
             # already registered
             intname = object.__InternalName__
             if name is not None and name!=intname:
-                raise ValueError, "attempt to reregister object %s with new name %s" % (
-                    repr(intname), repr(name))
+                raise ValueError("attempt to reregister object %s with new name %s" % (
+                    repr(intname), repr(name)))
             if intname not in idToObject:
-                raise ValueError, "object named but not registered"
+                raise ValueError("object named but not registered")
             return PDFObjectReference(intname)
         # otherwise register the new object
         objectcounter = self.objectcounter = self.objectcounter+1
@@ -533,7 +533,7 @@
         if name in idToObject:
             other = idToObject[name]
             if other!=object:
-                raise ValueError, "redefining named object: "+repr(name)
+                raise ValueError("redefining named object: "+repr(name))
             return PDFObjectReference(name)
         if iob:
             object.__InternalName__ = name
@@ -581,7 +581,7 @@
     try:
         utext.encode('pdfdoc')
         return 1
-    except UnicodeEncodeError, e:
+    except UnicodeEncodeError as e:
         return 0
 
 class PDFString:
@@ -617,9 +617,9 @@
                         s.decode('pdfdoc')
                     except:
                         import sys
-                        print >>sys.stderr, 'Error in',repr(s)
+                        print('Error in',repr(s), file=sys.stderr)
                         raise
-        elif type(s) is unicode:
+        elif type(s) is str:
             if enc is 'auto':
                 if _checkPdfdoc(s):
                     s = s.encode('pdfdoc')
@@ -679,9 +679,9 @@
     def format(self, document,IND=LINEEND+' '):
         dict = self.dict
         try:
-            keys = dict.keys()
+            keys = list(dict.keys())
         except:
-            print repr(dict)
+            print(repr(dict))
             raise
         keys.sort()
         L = [(format(PDFName(k),document)+" "+format(dict[k],document)) for k in keys]
@@ -690,7 +690,7 @@
         else:
             # break up every 6 elements anyway
             t=L.insert
-            for i in xrange(6, len(L), 6):
+            for i in range(6, len(L), 6):
                 t(i,LINEEND)
             L = " ".join(L)
         return "<< %s >>" % L
@@ -701,13 +701,13 @@
     def normalize(self):
         #normalize the names to use RL standard ie Name not /Name
         D = self.dict
-        K = [k for k in D.iterkeys() if k.startswith('/')]
+        K = [k for k in D.keys() if k.startswith('/')]
         for k in K:
             D[k[1:]] = D.pop(k)
 
 class checkPDFNames:
     def __init__(self,*names):
-        self.names = map(PDFName,names)
+        self.names = list(map(PDFName,names))
     def __call__(self,value):
         if not value.startswith('/'):
             value=PDFName(value)
@@ -755,12 +755,12 @@
     def encode(self, text):
         from reportlab.lib.utils import import_zlib
         zlib = import_zlib()
-        if not zlib: raise ImportError, "cannot z-compress zlib unavailable"
+        if not zlib: raise ImportError("cannot z-compress zlib unavailable")
         return zlib.compress(text)
     def decode(self, encoded):
         from reportlab.lib.utils import import_zlib
         zlib = import_zlib()
-        if not zlib: raise ImportError, "cannot z-decompress zlib unavailable"
+        if not zlib: raise ImportError("cannot z-decompress zlib unavailable")
         return zlib.decompress(encoded)
 
 # need only one of these, unless we implement parameters later
@@ -769,13 +769,13 @@
 class PDFStreamFilterBase85Encode:
     pdfname = "ASCII85Decode"
     def encode(self, text):
-        from pdfutils import _AsciiBase85Encode, _wrap
+        from .pdfutils import _AsciiBase85Encode, _wrap
         text = _AsciiBase85Encode(text)
         if rl_config.wrapA85:
             text = _wrap(text)
         return text
     def decode(self, text):
-        from pdfutils import _AsciiBase85Decode
+        from .pdfutils import _AsciiBase85Decode
         return _AsciiBase85Decode(text)
 
 # need only one of these too
@@ -805,7 +805,7 @@
         content = self.content
         filters = self.filters
         if self.content is None:
-            raise ValueError, "stream content not set"
+            raise ValueError("stream content not set")
         if filters is None:
             filters = document.defaultStreamFilters
         # only apply filters if they haven't been applied elsewhere
@@ -862,7 +862,7 @@
         self.sequence = list(sequence)
     def References(self, document):
         """make all objects in sequence references"""
-        self.sequence = map(document.Reference, self.sequence)
+        self.sequence = list(map(document.Reference, self.sequence))
     def format(self, document, IND=LINEEND+' '):
         L = [format(e, document) for e in self.sequence]
         if self.multiline:
@@ -909,7 +909,7 @@
         try:
             return "%s %s R" % document.idToObjectNumberAndVersion[self.name]
         except:
-            raise KeyError, "forward reference to %s not resolved upon final formatting" % repr(self.name)
+            raise KeyError("forward reference to %s not resolved upon final formatting" % repr(self.name))
 
 ### chapter 5
 # Following Ken Lunde's advice and the PDF spec, this includes
@@ -940,7 +940,7 @@
         self.write(s)
         return result
     def format(self, document):
-        strings = map(str, self.strings) # final conversion, in case of lazy objects
+        strings = list(map(str, self.strings)) # final conversion, in case of lazy objects
         return string.join(strings, "")
 
 XREFFMT = '%0.10d %0.5d n'
@@ -968,9 +968,9 @@
         for id in idsequence:
             (num, version) = idToNV[id]
             if num in taken:
-                raise ValueError, "object number collision %s %s %s" % (num, repr(id), repr(taken[id]))
+                raise ValueError("object number collision %s %s %s" % (num, repr(id), repr(taken[id])))
             if num>lastentrynumber or num<firstentrynumber:
-                raise ValueError, "object number %s not in range %s..%s" % (num, firstentrynumber, lastentrynumber)
+                raise ValueError("object number %s not in range %s..%s" % (num, firstentrynumber, lastentrynumber))
             # compute position in list
             rnum = num-firstentrynumber
             taken[num] = id
@@ -986,7 +986,7 @@
         elif LINEEND=="\r\n":
             reflineend = LINEEND
         else:
-            raise ValueError, "bad end of line! %s" % repr(LINEEND)
+            raise ValueError("bad end of line! %s" % repr(LINEEND))
         return string.join(entries, LINEEND)
 
 class PDFCrossReferenceTable:
@@ -1000,7 +1000,7 @@
     def format(self, document):
         sections = self.sections
         if not sections:
-            raise ValueError, "no crossref sections"
+            raise ValueError("no crossref sections")
         L = ["xref"+LINEEND]
         for s in self.sections:
             fs = format(s, document)
@@ -1019,7 +1019,7 @@
     def __init__(self, startxref, Size=None, Prev=None, Root=None, Info=None, ID=None, Encrypt=None):
         self.startxref = startxref
         if Size is None or Root is None:
-            raise ValueError, "Size and Root keys required"
+            raise ValueError("Size and Root keys required")
         dict = self.dict = PDFDictionary()
         for (n,v) in [("Size", Size), ("Prev", Prev), ("Root", Root),
                       ("Info", Info), ("ID", ID), ("Encrypt", Encrypt)]:
@@ -1056,7 +1056,7 @@
         defaults = self.__Defaults__
         Refs = self.__Refs__
         D = {}
-        for k in defaults.keys():
+        for k in list(defaults.keys()):
             default = defaults[k]
             v = None
             if hasattr(self, k) and getattr(self,k) is not None:
@@ -1157,7 +1157,7 @@
         self.compression = onoff
     def setStream(self, code):
         if self.Override_default_compilation:
-            raise ValueError, "overridden! must set stream explicitly"
+            raise ValueError("overridden! must set stream explicitly")
         from types import ListType
         if type(code) is ListType:
             code = string.join(code, LINEEND)+LINEEND
@@ -1398,9 +1398,9 @@
         """destinationname of None means "close the tree" """
         from types import IntType, TupleType
         if destinationname is None and level!=0:
-            raise ValueError, "close tree must have level of 0"
-        if type(level) is not IntType: raise ValueError, "level must be integer, got %s" % type(level)
-        if level<0: raise ValueError, "negative levels not allowed"
+            raise ValueError("close tree must have level of 0")
+        if type(level) is not IntType: raise ValueError("level must be integer, got %s" % type(level))
+        if level<0: raise ValueError("negative levels not allowed")
         if title is None: title = destinationname
         currentlevel = self.currentlevel
         stack = self.levelstack
@@ -1408,7 +1408,7 @@
         # adjust currentlevel and stack to match level
         if level>currentlevel:
             if level>currentlevel+1:
-                raise ValueError, "can't jump from outline level %s to level %s, need intermediates (destinationname=%r, title=%r)" %(currentlevel, level, destinationname, title)
+                raise ValueError("can't jump from outline level %s to level %s, need intermediates (destinationname=%r, title=%r)" %(currentlevel, level, destinationname, title))
             level = currentlevel = currentlevel+1
             stack.append([])
         while level<currentlevel:
@@ -1419,7 +1419,7 @@
             lastinprevious = previous[-1]
             if type(lastinprevious) is TupleType:
                 (name, sectionlist) = lastinprevious
-                raise ValueError, "cannot reset existing sections: " + repr(lastinprevious)
+                raise ValueError("cannot reset existing sections: " + repr(lastinprevious))
             else:
                 name = lastinprevious
                 sectionlist = current
@@ -1513,9 +1513,9 @@
             self.count = self.count+1
             levelname = "Outline.%s" % self.count
             if Parent is None:
-                raise ValueError, "non-top level outline elt parent must be specified"
+                raise ValueError("non-top level outline elt parent must be specified")
         if tdestinationtree is not ListType and tdestinationtree is not TupleType:
-            raise ValueError, "destinationtree must be list or tuple, got %s"
+            raise ValueError("destinationtree must be list or tuple, got %s")
         nelts = len(destinationtree)
         lastindex = nelts-1
         lastelt = firstref = lastref = None
@@ -1545,15 +1545,15 @@
                 try:
                     (leafdict, subsections) = elt
                 except:
-                    raise ValueError, "destination tree elt tuple should have two elts, got %s" % len(elt)
+                    raise ValueError("destination tree elt tuple should have two elts, got %s" % len(elt))
                 eltobj.Count = count(subsections, closedict)
                 (eltobj.First, eltobj.Last) = self.maketree(document, subsections, eltref)
             else:
-                raise ValueError, "destination tree elt should be dict or tuple, got %s" % te
+                raise ValueError("destination tree elt should be dict or tuple, got %s" % te)
             try:
-                [(Title, Dest)] = leafdict.items()
+                [(Title, Dest)] = list(leafdict.items())
             except:
-                raise ValueError, "bad outline leaf dictionary, should have one entry "+utf8str(elt)
+                raise ValueError("bad outline leaf dictionary, should have one entry "+utf8str(elt))
             eltobj.Title = destinationnamestotitles[Title]
             eltobj.Dest = Dest
             if te is TupleType and Dest in closedict:
@@ -1569,7 +1569,7 @@
     if tt is TupleType:
         # leaf with subsections XXXX should clean up this structural usage
         (leafdict, subsections) = tree
-        [(Title, Dest)] = leafdict.items()
+        [(Title, Dest)] = list(leafdict.items())
         if closedict and Dest in closedict:
             return 1 # closed tree element
     if tt is TupleType or tt is ListType:
@@ -1617,7 +1617,7 @@
     def copy(self):
         "shallow copy - useful in pagecatchering"
         thing = self.__klass__()
-        for (k, v) in self.__dict__.items():
+        for (k, v) in list(self.__dict__.items()):
             setattr(thing, k, v)
         return thing
 # skipping thumbnails, etc
@@ -1632,7 +1632,7 @@
     def cvtdict(self, d, escape=1):
         """transform dict args from python form to pdf string rep as needed"""
         Rect = d["Rect"]
-        if type(Rect) is not types.StringType:
+        if type(Rect) is not bytes:
             d["Rect"] = PDFArray(Rect)
         d["Contents"] = PDFString(d["Contents"],escape)
         return d
@@ -1648,15 +1648,15 @@
         d.update(kw)
         for name in self.required:
             if name not in d:
-                raise ValueError, "keyword argument %s missing" % name
+                raise ValueError("keyword argument %s missing" % name)
         d = self.cvtdict(d,escape=escape)
         permitted = self.permitted
-        for name in d.keys():
+        for name in list(d.keys()):
             if name not in permitted:
-                raise ValueError, "bad annotation dictionary name %s" % name
+                raise ValueError("bad annotation dictionary name %s" % name)
         return PDFDictionary(d)
     def Dict(self):
-        raise ValueError, "DictString undefined for virtual superclass Annotation, must overload"
+        raise ValueError("DictString undefined for virtual superclass Annotation, must overload")
         # but usually
         #return self.AnnotationDict(self, Rect=(a,b,c,d)) or whatever
     def format(self, document):
@@ -1747,7 +1747,7 @@
     # gmt offset now suppported properly
     def __init__(self, invariant=rl_config.invariant, dateFormatter=None):
         if invariant:
-            now = (2000,01,01,00,00,00,0)
+            now = (2000,0o1,0o1,00,00,00,0)
             self.dhh = 0
             self.dmm = 0
         else:
@@ -1790,9 +1790,9 @@
         self.fmt = self.page = None
     def format(self, document):
         f = self.fmt
-        if f is None: raise ValueError, "format not resolved %s" % self.name
+        if f is None: raise ValueError("format not resolved %s" % self.name)
         p = self.page
-        if p is None: raise ValueError, "Page reference unbound %s" % self.name
+        if p is None: raise ValueError("Page reference unbound %s" % self.name)
         f.page = p
         return f.format(document)
     def xyz(self, left, top, zoom):  # see pdfspec mar 11 99 pp184+
@@ -1895,7 +1895,7 @@
         self.Shading = {}
         # ?by default define the basicprocs
         self.basicProcs()
-    stdprocs = map(PDFName, string.split("PDF Text ImageB ImageC ImageI"))
+    stdprocs = list(map(PDFName, string.split("PDF Text ImageB ImageC ImageI")))
     dict_attributes = ("ColorSpace", "XObject", "ExtGState", "Font", "Pattern", "Properties", "Shading")
 
     def allProcs(self):
@@ -1909,11 +1909,11 @@
         self.Font = PDFObjectReference(BasicFonts)
 
     def setColorSpace(self,colorsUsed):
-        for c,s in colorsUsed.iteritems():
+        for c,s in colorsUsed.items():
             self.ColorSpace[s] = PDFObjectReference(c)
 
     def setShading(self,shadingUsed):
-        for c,s in shadingUsed.iteritems():
+        for c,s in shadingUsed.items():
             self.Shading[s] = PDFObjectReference(c)
 
     def format(self, document):
@@ -2023,7 +2023,7 @@
         self.lowerx = lowerx; self.lowery=lowery; self.upperx=upperx; self.uppery=uppery
 
     def setStreamList(self, data):
-        if type(data) is types.ListType:
+        if type(data) is list:
             data = string.join(data, LINEEND)
         self.stream = data
 
@@ -2130,9 +2130,9 @@
 
     def loadImageFromA85(self,source):
         IMG=[]
-        imagedata = map(string.strip,pdfutils.makeA85Image(source,IMG=IMG))
+        imagedata = list(map(string.strip,pdfutils.makeA85Image(source,IMG=IMG)))
         words = string.split(imagedata[1])
-        self.width, self.height = map(string.atoi,(words[1],words[3]))
+        self.width, self.height = list(map(string.atoi,(words[1],words[3])))
         self.colorSpace = {'/RGB':'DeviceRGB', '/G':'DeviceGray', '/CMYK':'DeviceCMYK'}[words[7]]
         self.bitsPerComponent = 8
         self._filters = 'ASCII85Decode','FlateDecode' #'A85','Fl'
@@ -2170,7 +2170,7 @@
         IMG=[]
         imagedata = pdfutils.makeRawImage(source,IMG=IMG)
         words = string.split(imagedata[1])
-        self.width, self.height = map(string.atoi,(words[1],words[3]))
+        self.width, self.height = list(map(string.atoi,(words[1],words[3])))
         self.colorSpace = {'/RGB':'DeviceRGB', '/G':'DeviceGray', '/CMYK':'DeviceCMYK'}[words[7]]
         self.bitsPerComponent = 8
         self._filters = 'FlateDecode', #'Fl'
@@ -2228,7 +2228,7 @@
             dict["Decode"] = PDFArray([1,0,1,0,1,0,1,0])
         elif getattr(self,'_decode',None):
             dict["Decode"] = PDFArray(self._decode)
-        dict["Filter"] = PDFArray(map(PDFName,self._filters))
+        dict["Filter"] = PDFArray(list(map(PDFName,self._filters)))
         dict["Length"] = len(self.streamContent)
         if self.mask: dict["Mask"] = PDFArray(self.mask)
         if getattr(self,'smask',None): dict["SMask"] = self.smask
@@ -2295,15 +2295,15 @@
         d.update(kw)
         for name in self.required:
             if name not in d:
-                raise ValueError, "keyword argument %s missing" % name
+                raise ValueError("keyword argument %s missing" % name)
         permitted = self.permitted
-        for name in d.keys():
+        for name in list(d.keys()):
             if name not in permitted:
-                raise ValueError, "bad annotation dictionary name %s" % name
+                raise ValueError("bad annotation dictionary name %s" % name)
         return PDFDictionary(d)
 
     def Dict(self, document):
-        raise ValueError, "Dict undefined for virtual superclass PDFShading, must overload"
+        raise ValueError("Dict undefined for virtual superclass PDFShading, must overload")
         # but usually
         #return self.FunctionDict(self, ...)
 
@@ -2356,15 +2356,15 @@
         d.update(kw)
         for name in self.required:
             if name not in d:
-                raise ValueError, "keyword argument %s missing" % name
+                raise ValueError("keyword argument %s missing" % name)
         permitted = self.permitted
-        for name in d.keys():
+        for name in list(d.keys()):
             if name not in permitted:
-                raise ValueError, "bad annotation dictionary name %s" % name
+                raise ValueError("bad annotation dictionary name %s" % name)
         return PDFDictionary(d)
 
     def Dict(self, document):
-        raise ValueError, "Dict undefined for virtual superclass PDFShading, must overload"
+        raise ValueError("Dict undefined for virtual superclass PDFShading, must overload")
         # but usually
         #return self.ShadingDict(self, ...)
 
@@ -2424,4 +2424,4 @@
         return self.ShadingDict(**d)
 
 if __name__=="__main__":
-    print "There is no script interpretation for pdfdoc."
+    print("There is no script interpretation for pdfdoc.")
--- a/src/reportlab/pdfbase/pdfform.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/pdfform.py	Tue Apr 30 14:20:22 2013 +0100
@@ -116,11 +116,11 @@
     buttonFieldRelative(c, "field3_1", "Off", 100, 800)
     c.rect(100, 800, 20, 20)
     c.save()
-    print "wrote", fn
+    print("wrote", fn)
 
 #==========================end of public interfaces
 
-from pdfpattern import PDFPattern
+from .pdfpattern import PDFPattern
 
 def getForm(canvas):
     "get form from canvas, create the form if needed"
@@ -191,7 +191,7 @@
     from reportlab.pdfbase.pdfdoc import PDFDictionary
     fontsdictionary = PDFDictionary()
     fontsdictionary.__RefOnly__ = 1
-    for (fullname, shortname) in FORMFONTNAMES.items():
+    for (fullname, shortname) in list(FORMFONTNAMES.items()):
         fontsdictionary[shortname] = FormFont(fullname, shortname)
     fontsdictionary["ZaDb"] = ZADB
     return fontsdictionary
@@ -466,9 +466,9 @@
     #print "ARGS", (title, value, options, xmin, ymin, xmax, ymax, page, font, fontsize, R, G, B)
     from reportlab.pdfbase.pdfdoc import PDFString, PDFName, PDFArray
     if value not in options:
-        raise ValueError, "value %s must be one of options %s" % (repr(value), repr(options))
+        raise ValueError("value %s must be one of options %s" % (repr(value), repr(options)))
     fontname = FORMFONTNAMES[font]
-    optionstrings = map(PDFString, options)
+    optionstrings = list(map(PDFString, options))
     optionarray = PDFArray(optionstrings)
     return PDFPattern(SelectFieldPattern,
                       Options=optionarray,
@@ -522,7 +522,7 @@
 
 def ButtonField(title, value, xmin, ymin, page):
     if value not in ("Yes", "Off"):
-        raise ValueError, "button value must be 'Yes' or 'Off': "+repr(value)
+        raise ValueError("button value must be 'Yes' or 'Off': "+repr(value))
     (dx, dy) = (16.77036, 14.90698)
     return PDFPattern(ButtonFieldPattern,
                       Name=PDFString(title),
--- a/src/reportlab/pdfbase/pdfmetrics.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/pdfmetrics.py	Tue Apr 30 14:20:22 2013 +0100
@@ -24,7 +24,7 @@
 from reportlab.lib.logger import warnOnce
 from reportlab.lib.utils import rl_isfile, rl_glob, rl_isdir, open_and_read, open_and_readlines, findInPaths
 from reportlab.rl_config import defaultEncoding, T1SearchPath
-import rl_codecs
+from . import rl_codecs
 _notdefChar = chr(110)
 
 rl_codecs.RL_Codecs.register()
@@ -48,7 +48,7 @@
         try:
             R.append((font,utext.encode(enc)))
             break
-        except UnicodeEncodeError, e:
+        except UnicodeEncodeError as e:
             i0, il = e.args[2:4]
             if i0:
                 R.append((font,utext[:i0].encode(enc)))
@@ -82,7 +82,7 @@
         #likely to be a MAC file
         if lines: lines = string.split(lines[0],'\r')
         if len(lines)<=1:
-            raise ValueError, 'AFM file %s hasn\'t enough data' % afmFileName
+            raise ValueError('AFM file %s hasn\'t enough data' % afmFileName)
     topLevel = {}
     glyphLevel = []
 
@@ -96,7 +96,7 @@
             inMetrics = 0
         elif inMetrics:
             chunks = string.split(line, ';')
-            chunks = map(string.strip, chunks)
+            chunks = list(map(string.strip, chunks))
             cidChunk, widthChunk, nameChunk = chunks[0:3]
 
             # character ID
@@ -128,7 +128,7 @@
             try:
                 left, right = string.split(line,' ',1)
             except:
-                raise ValueError, "Header information error in afm %s: line='%s'" % (afmFileName, line)
+                raise ValueError("Header information error in afm %s: line='%s'" % (afmFileName, line))
             try:
                 right = string.atoi(right)
             except:
@@ -170,7 +170,7 @@
         We presume they never change so this can be a shared reference."""
         name = str(name)    #needed for pycanvas&jython/2.1 compatibility
         self.glyphWidths = _fontdata.widthsByFontGlyph[name]
-        self.glyphNames = self.glyphWidths.keys()
+        self.glyphNames = list(self.glyphWidths.keys())
         self.ascent,self.descent = _fontdata.ascent_descent[name]
 
     def getFontFiles(self):
@@ -306,7 +306,7 @@
 
         ranges = []
         curRange = None
-        for i in xrange(len(self.vector)):
+        for i in range(len(self.vector)):
             glyph = self.vector[i]
             if glyph==otherEnc.vector[i]:
                 if curRange:
@@ -398,7 +398,7 @@
                 except KeyError:
                     import reportlab.rl_config
                     if reportlab.rl_config.warnOnMissingFontGlyphs:
-                        print 'typeface "%s" does not have a glyph "%s", bad font!' % (self.face.name, glyphName)
+                        print('typeface "%s" does not have a glyph "%s", bad font!' % (self.face.name, glyphName))
                     else:
                         pass
         self.widths = w
@@ -407,8 +407,8 @@
         """This is the "purist" approach to width.  The practical approach
         is to use the stringWidth function, which may be swapped in for one
         written in C."""
-        if not isinstance(text,unicode): text = text.decode(encoding)
-        return sum([sum(map(f.widths.__getitem__,map(ord,t))) for f, t in unicode2T1(text,[self]+self.substitutionFonts)])*0.001*size
+        if not isinstance(text,str): text = text.decode(encoding)
+        return sum([sum(map(f.widths.__getitem__,list(map(ord,t)))) for f, t in unicode2T1(text,[self]+self.substitutionFonts)])*0.001*size
     stringWidth = _py_stringWidth
 
     def _formatWidths(self):
@@ -463,13 +463,13 @@
 
 def _pfbCheck(p,d,m,fn):
     if d[p]!=PFB_MARKER or d[p+1]!=m:
-        raise ValueError, 'Bad pfb file\'%s\' expected chr(%d)chr(%d) at char %d, got chr(%d)chr(%d)' % (fn,ord(PFB_MARKER),ord(m),p,ord(d[p]),ord(d[p+1]))
+        raise ValueError('Bad pfb file\'%s\' expected chr(%d)chr(%d) at char %d, got chr(%d)chr(%d)' % (fn,ord(PFB_MARKER),ord(m),p,ord(d[p]),ord(d[p+1])))
     if m==PFB_EOF: return
     p = p + 2
     l = _pfbSegLen(p,d)
     p = p + 4
     if p+l>len(d):
-        raise ValueError, 'Bad pfb file\'%s\' needed %d+%d bytes have only %d!' % (fn,p,l,len(d))
+        raise ValueError('Bad pfb file\'%s\' needed %d+%d bytes have only %d!' % (fn,p,l,len(d)))
     return p, p+l
 
 class EmbeddedType1Face(TypeFace):
@@ -535,7 +535,7 @@
         for (cid, width, name) in glyphData:
             glyphWidths[name] = width
         self.glyphWidths = glyphWidths
-        self.glyphNames = glyphWidths.keys()
+        self.glyphNames = list(glyphWidths.keys())
         self.glyphNames.sort()
 
         # for font-specific encodings like Symbol, Dingbats, Carta we
@@ -713,7 +713,7 @@
 
 def getRegisteredFontNames():
     "Returns what's in there"
-    reg = _fonts.keys()
+    reg = list(_fonts.keys())
     reg.sort()
     return reg
 
@@ -730,27 +730,27 @@
     pass
 
 def dumpFontData():
-    print 'Registered Encodings:'
-    keys = _encodings.keys()
+    print('Registered Encodings:')
+    keys = list(_encodings.keys())
     keys.sort()
     for encName in keys:
-        print '   ',encName
+        print('   ',encName)
 
-    print
-    print 'Registered Typefaces:'
-    faces = _typefaces.keys()
+    print()
+    print('Registered Typefaces:')
+    faces = list(_typefaces.keys())
     faces.sort()
     for faceName in faces:
-        print '   ',faceName
+        print('   ',faceName)
 
 
-    print
-    print 'Registered Fonts:'
-    k = _fonts.keys()
+    print()
+    print('Registered Fonts:')
+    k = list(_fonts.keys())
     k.sort()
     for key in k:
         font = _fonts[key]
-        print '    %s (%s/%s)' % (font.fontName, font.face.name, font.encoding.name)
+        print('    %s (%s/%s)' % (font.fontName, font.face.name, font.encoding.name))
 
 def test3widths(texts):
     # checks all 3 algorithms give same answer, note speed
@@ -769,33 +769,33 @@
             for ch in text:
                 l2 = l2 + w[ord(ch)]
         t1 = time.time()
-        print 'slow stringWidth took %0.4f' % (t1 - t0)
+        print('slow stringWidth took %0.4f' % (t1 - t0))
 
         t0 = time.time()
         for text in texts:
             l3 = getFont(fontName).stringWidth(text, 10)
         t1 = time.time()
-        print 'class lookup and stringWidth took %0.4f' % (t1 - t0)
-        print
+        print('class lookup and stringWidth took %0.4f' % (t1 - t0))
+        print()
 
 def testStringWidthAlgorithms():
     rawdata = open('../../rlextra/rml2pdf/doc/rml_user_guide.prep').read()
-    print 'rawdata length %d' % len(rawdata)
-    print 'test one huge string...'
+    print('rawdata length %d' % len(rawdata))
+    print('test one huge string...')
     test3widths([rawdata])
-    print
+    print()
     words = string.split(rawdata)
-    print 'test %d shorter strings (average length %0.2f chars)...' % (len(words), 1.0*len(rawdata)/len(words))
+    print('test %d shorter strings (average length %0.2f chars)...' % (len(words), 1.0*len(rawdata)/len(words)))
     test3widths(words)
 
 
 def test():
     helv = TypeFace('Helvetica')
     registerTypeFace(helv)
-    print helv.glyphNames[0:30]
+    print(helv.glyphNames[0:30])
 
     wombat = TypeFace('Wombat')
-    print wombat.glyphNames
+    print(wombat.glyphNames)
     registerTypeFace(wombat)
 
     dumpFontData()
@@ -808,7 +808,7 @@
             _fonts = _fonts.copy(),
             )
         ):
-    for k,v in initial_dicts.iteritems():
+    for k,v in initial_dicts.items():
         d=globals()[k]
         d.clear()
         d.update(v)
--- a/src/reportlab/pdfbase/pdfpattern.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/pdfpattern.py	Tue Apr 30 14:20:22 2013 +0100
@@ -27,9 +27,9 @@
         for x in pattern_sequence:
             if type(x) not in toptypes:
                 if len(x)!=1:
-                    raise ValueError, "sequence elts must be strings or singletons containing strings: "+repr(x)
+                    raise ValueError("sequence elts must be strings or singletons containing strings: "+repr(x))
                 if type(x[0]) is not StringType:
-                    raise ValueError, "Singletons must contain strings or instances only: "+repr(x[0])
+                    raise ValueError("Singletons must contain strings or instances only: "+repr(x[0]))
     def __setitem__(self, item, value):
         self.arguments[item] = value
     def __getitem__(self, item):
@@ -48,7 +48,7 @@
                 name = x[0]
                 value = arguments.get(name, None)
                 if value is None:
-                    raise ValueError, "%s value not defined" % repr(name)
+                    raise ValueError("%s value not defined" % repr(name))
                 if type(value) is InstanceType:
                     #L.append( value.format(document) )
                     L.append(format(value, document))
--- a/src/reportlab/pdfbase/pdfutils.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/pdfutils.py	Tue Apr 30 14:20:22 2013 +0100
@@ -13,7 +13,7 @@
 LINEEND = '\015\012'
 
 def _chunker(src,dst=[],chunkSize=60):
-    for i in xrange(0,len(src),chunkSize):
+    for i in range(0,len(src),chunkSize):
         dst.append(src[i:i+chunkSize])
     return dst
 
@@ -80,9 +80,9 @@
     if filename==cachedname:
         if cachedImageExists(filename):
             from reportlab.lib.utils import open_for_read
-            if returnInMemory: return filter(None,open_for_read(cachedname).read().split(LINEEND))
+            if returnInMemory: return [_f for _f in open_for_read(cachedname).read().split(LINEEND) if _f]
         else:
-            raise IOError, 'No such cached image %s' % filename
+            raise IOError('No such cached image %s' % filename)
     else:
         if rl_config.useA85:
             code = makeA85Image(filename,IMG)
@@ -95,7 +95,7 @@
         f.write(LINEEND.join(code)+LINEEND)
         f.close()
         if rl_config.verbose:
-            print 'cached image as %s' % cachedname
+            print('cached image as %s' % cachedname)
 
 
 def preProcessImages(spec):
@@ -108,7 +108,7 @@
 
     import types, glob
 
-    if type(spec) is types.StringType:
+    if type(spec) is bytes:
         filelist = glob.glob(spec)
     else:  #list or tuple OK
         filelist = spec
@@ -116,7 +116,7 @@
     for filename in filelist:
         if cachedImageExists(filename):
             if rl_config.verbose:
-                print 'cached version of %s already exists' % filename
+                print('cached version of %s already exists' % filename)
         else:
             cacheImageFile(filename)
 
@@ -156,7 +156,7 @@
         _instanceEscapePDF=None
         if rl_config.sys_version>='2.1':
             _ESCAPEDICT={}
-            for c in xrange(0,256):
+            for c in range(0,256):
                 if c<32 or c>=127:
                     _ESCAPEDICT[chr(c)]= '\\%03o' % c
                 elif c in (ord('\\'),ord('('),ord(')')):
@@ -211,7 +211,7 @@
     stripped = stripped[:-1]  #chop off terminator
     assert len(stripped) % 2 == 0, 'Ascii Hex stream has odd number of bytes'
 
-    return ''.join([chr(int(stripped[i:i+2],16)) for i in xrange(0,len(stripped),2)])
+    return ''.join([chr(int(stripped[i:i+2],16)) for i in range(0,len(stripped),2)])
         
 if 1: # for testing always define this
     def _AsciiBase85EncodePYTHON(input):
@@ -226,7 +226,7 @@
         body, lastbit = input[0:cut], input[cut:]
 
         out = [].append
-        for i in xrange(whole_word_count):
+        for i in range(whole_word_count):
             offset = i*4
             b1 = ord(body[offset])
             b2 = ord(body[offset+1])
@@ -236,7 +236,7 @@
             if b1<128:
                 num = (((((b1<<8)|b2)<<8)|b3)<<8)|b4
             else:
-                num = 16777216L * b1 + 65536 * b2 + 256 * b3 + b4
+                num = 16777216 * b1 + 65536 * b2 + 256 * b3 + b4
 
             if num == 0:
                 #special case
@@ -267,7 +267,7 @@
             b3 = ord(lastbit[2])
             b4 = ord(lastbit[3])
 
-            num = 16777216L * b1 + 65536 * b2 + 256 * b3 + b4
+            num = 16777216 * b1 + 65536 * b2 + 256 * b3 + b4
 
             #solve for c1..c5
             temp, c5 = divmod(num, 85)
@@ -306,7 +306,7 @@
         body, lastbit = stripped[0:cut], stripped[cut:]
 
         out = [].append
-        for i in xrange(whole_word_count):
+        for i in range(whole_word_count):
             offset = i*5
             c1 = ord(body[offset]) - 33
             c2 = ord(body[offset+1]) - 33
@@ -314,7 +314,7 @@
             c4 = ord(body[offset+3]) - 33
             c5 = ord(body[offset+4]) - 33
 
-            num = ((85L**4) * c1) + ((85**3) * c2) + ((85**2) * c3) + (85*c4) + c5
+            num = ((85**4) * c1) + ((85**3) * c2) + ((85**2) * c3) + (85*c4) + c5
 
             temp, b4 = divmod(num,256)
             temp, b3 = divmod(temp,256)
@@ -335,7 +335,7 @@
             c3 = ord(lastbit[2]) - 33
             c4 = ord(lastbit[3]) - 33
             c5 = ord(lastbit[4]) - 33
-            num = (((85*c1+c2)*85+c3)*85+c4)*85L + (c5
+            num = (((85*c1+c2)*85+c3)*85+c4)*85 + (c5
                      +(0,0,0xFFFFFF,0xFFFF,0xFF)[remainder_size])
             temp, b4 = divmod(num,256)
             temp, b3 = divmod(temp,256)
@@ -406,7 +406,7 @@
     "Read width, height and number of components from open JPEG file."
 
     import struct
-    from pdfdoc import PDFError
+    from .pdfdoc import PDFError
 
     #Acceptable JPEG Markers:
     #  SROF0=baseline, SOF1=extended sequential or SOF2=progressive
@@ -456,10 +456,10 @@
         self._n = int(n) or 7
 
     def encrypt(self,s):
-        return self.__rotate(_AsciiBase85Encode(''.join(map(chr,self.__fusc(map(ord,s))))),self._n)
+        return self.__rotate(_AsciiBase85Encode(''.join(map(chr,self.__fusc(list(map(ord,s)))))),self._n)
 
     def decrypt(self,s):
-        return ''.join(map(chr,self.__fusc(map(ord,_AsciiBase85Decode(self.__rotate(s,-self._n))))))
+        return ''.join(map(chr,self.__fusc(list(map(ord,_AsciiBase85Decode(self.__rotate(s,-self._n)))))))
 
     def __rotate(self,s,n):
         l = len(s)
@@ -470,4 +470,4 @@
 
     def __fusc(self,s):
         slen = len(s)
-        return map(lambda x,y: x ^ y,s,map(ord,((int(slen/self._klen)+1)*self._k)[:slen]))
+        return list(map(lambda x,y: x ^ y,s,list(map(ord,((int(slen/self._klen)+1)*self._k)[:slen]))))
--- a/src/reportlab/pdfbase/rl_codecs.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/rl_codecs.py	Tue Apr 30 14:20:22 2013 +0100
@@ -986,7 +986,7 @@
     def _256_exception_codec(xt):
         exceptions,rexceptions = xt
         import codecs
-        decoding_map = codecs.make_identity_dict(xrange(32,256))
+        decoding_map = codecs.make_identity_dict(range(32,256))
         decoding_map.update(exceptions)
         encoding_map = codecs.make_encoding_map(decoding_map)
         if rexceptions: encoding_map.update(rexceptions)
@@ -1020,7 +1020,7 @@
 
     def _rl_codecs(name):
         name = name.lower()
-        from pdfmetrics import standardEncodings
+        from .pdfmetrics import standardEncodings
         for e in standardEncodings:
             e = e[:-8].lower()
             if name.startswith(e): return RL_Codecs.__rl_codecs(e)
--- a/src/reportlab/pdfbase/ttfonts.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfbase/ttfonts.py	Tue Apr 30 14:20:22 2013 +0100
@@ -69,8 +69,8 @@
 #
 
 from codecs import utf_8_encode, utf_8_decode, latin_1_decode
-parse_utf8=lambda x, decode=utf_8_decode: map(ord,decode(x)[0])
-parse_latin1 = lambda x, decode=latin_1_decode: map(ord,decode(x)[0])
+parse_utf8=lambda x, decode=utf_8_decode: list(map(ord,decode(x)[0]))
+parse_latin1 = lambda x, decode=latin_1_decode: list(map(ord,decode(x)[0]))
 def latin1_to_utf8(text):
     "helper to convert when needed from latin input"
     return utf_8_encode(latin_1_decode(text)[0])[0]
@@ -124,19 +124,19 @@
     hex32 = _rl_accel.hex32
 except:
     def hex32(i):
-        return '0X%8.8X' % (long(i)&0xFFFFFFFFL)
+        return '0X%8.8X' % (int(i)&0xFFFFFFFF)
 try:
     add32 = _rl_accel.add32L
     calcChecksum = _rl_accel.calcChecksumL
 except:
     def add32(x, y):
         "Calculate (x + y) modulo 2**32"
-        return (x+y) & 0xFFFFFFFFL
+        return (x+y) & 0xFFFFFFFF
 
     def calcChecksum(data):
         """Calculates TTF-style checksums"""
         if len(data)&3: data = data + (4-(len(data)&3))*"\0"
-        return sum(unpack(">%dl" % (len(data)>>2), data)) & 0xFFFFFFFFL
+        return sum(unpack(">%dl" % (len(data)>>2), data)) & 0xFFFFFFFF
 del _rl_accel
 #
 # TrueType font handling
@@ -205,7 +205,7 @@
         self.numSubfonts = self.read_ulong()
         self.subfontOffsets = []
         a = self.subfontOffsets.append
-        for i in xrange(self.numSubfonts):
+        for i in range(self.numSubfonts):
             a(self.read_ulong())
 
     def getSubfont(self,subfontIndex):
@@ -230,7 +230,7 @@
             # Read table directory
             self.table = {}
             self.tables = []
-            for n in xrange(self.numTables):
+            for n in range(self.numTables):
                 record = {}
                 record['tag'] = self.read_tag()
                 record['checksum'] = self.read_ulong()
@@ -280,7 +280,7 @@
     def checksumFile(self):
         # Check the checksums for the whole file
         checksum = calcChecksum(self._ttf_data)
-        if 0xB1B0AFBAL!=checksum:
+        if 0xB1B0AFBA!=checksum:
             raise TTFError('TTF file "%s": invalid checksum %s (expected 0xB1B0AFBA) len: %d &3: %d' % (self.filename,hex32(checksum),len(self._ttf_data),(len(self._ttf_data)&3)))
 
     def get_table_pos(self, tag):
@@ -323,8 +323,8 @@
         self._pos += 2
         try:
             return unpack('>h',self._ttf_data[self._pos-2:self._pos])[0]
-        except structError, error:
-            raise TTFError, error
+        except structError as error:
+            raise TTFError(error)
 
     def get_ushort(self, pos):
         "Return an unsigned short at given position"
@@ -375,7 +375,7 @@
                                  entrySelector, rangeShift))
 
         # Table directory
-        tables = self.tables.items()
+        tables = list(self.tables.items())
         tables.sort()     # XXX is this the correct order?
         offset = 12 + numTables * 16
         for tag, data in tables:
@@ -393,7 +393,7 @@
             write(data[:len(data)&~3])
 
         checksum = calcChecksum(stm.getvalue())
-        checksum = add32(0xB1B0AFBAL, -checksum)
+        checksum = add32(0xB1B0AFBA, -checksum)
         stm.seek(head_start + 8)
         write(pack('>L', checksum))
 
@@ -444,13 +444,13 @@
         name_offset = self.seek_table("name")
         format = self.read_ushort()
         if format != 0:
-            raise TTFError, "Unknown name table format (%d)" % format
+            raise TTFError("Unknown name table format (%d)" % format)
         numRecords = self.read_ushort()
         string_data_offset = name_offset + self.read_ushort()
         names = {1:None,2:None,3:None,4:None,6:None}
-        K = names.keys()
+        K = list(names.keys())
         nameCount = len(names)
-        for i in xrange(numRecords):
+        for i in range(numRecords):
             platformId = self.read_ushort()
             encodingId = self.read_ushort()
             languageId = self.read_ushort()
@@ -464,7 +464,7 @@
                 try:
                     self.seek(string_data_offset + offset)
                     if length % 2 != 0:
-                        raise TTFError, "PostScript name is UTF-16BE string of odd length"
+                        raise TTFError("PostScript name is UTF-16BE string of odd length")
                     length /= 2
                     N = []
                     A = N.append
@@ -496,11 +496,11 @@
 
         # Don't just assume, check for None since some shoddy fonts cause crashes here...
         if not psName:
-            raise TTFError, "Could not find PostScript font name"
+            raise TTFError("Could not find PostScript font name")
         for c in psName:
             oc = ord(c)
             if oc>126 or c in ' [](){}<>/%':
-                raise TTFError, "psName=%r contains invalid character '%s' ie U+%04X" % (psName,c,ord(c))
+                raise TTFError("psName=%r contains invalid character '%s' ie U+%04X" % (psName,c,ord(c)))
         self.name = psName
         self.familyName = names[1] or psName
         self.styleName = names[2] or 'Regular'
@@ -511,13 +511,13 @@
         self.seek_table("head")
         ver_maj, ver_min = self.read_ushort(), self.read_ushort()
         if ver_maj != 1:
-            raise TTFError, 'Unknown head table version %d.%04x' % (ver_maj, ver_min)
+            raise TTFError('Unknown head table version %d.%04x' % (ver_maj, ver_min))
         self.fontRevision = self.read_ushort(), self.read_ushort()
 
         self.skip(4)
         magic = self.read_ulong()
         if magic != 0x5F0F3CF5:
-            raise TTFError, 'Invalid head table magic %04x' % magic
+            raise TTFError('Invalid head table magic %04x' % magic)
         self.skip(2)
         self.unitsPerEm = unitsPerEm = self.read_ushort()
         scale = lambda x, unitsPerEm=unitsPerEm: x * 1000. / unitsPerEm
@@ -526,7 +526,7 @@
         yMin = self.read_short()
         xMax = self.read_short()
         yMax = self.read_short()
-        self.bbox = map(scale, [xMin, yMin, xMax, yMax])
+        self.bbox = list(map(scale, [xMin, yMin, xMax, yMax]))
         self.skip(3*2)
         indexToLocFormat = self.read_ushort()
         glyphDataFormat = self.read_ushort()
@@ -541,7 +541,7 @@
             self.skip(2)
             fsType = self.read_ushort()
             if fsType == 0x0002 or (fsType & 0x0300) != 0:
-                raise TTFError, 'Font does not allow subsetting/embedding (%04X)' % fsType
+                raise TTFError('Font does not allow subsetting/embedding (%04X)' % fsType)
             self.skip(58)   #11*2 + 10 + 4*4 + 4 + 3*2
             sTypoAscender = self.read_short()
             sTypoDescender = self.read_short()
@@ -575,7 +575,7 @@
             # From Apple docs it seems that we do not need to care
             # about the exact version, so if you get this error, you can
             # try to remove this check altogether.
-            raise TTFError, 'Unknown post table version %d.%04x' % (ver_maj, ver_min)
+            raise TTFError('Unknown post table version %d.%04x' % (ver_maj, ver_min))
         self.italicAngle = self.read_short() + self.read_ushort() / 65536.0
         self.underlinePosition = self.read_short()
         self.underlineThickness = self.read_short()
@@ -596,20 +596,20 @@
         self.seek_table("hhea")
         ver_maj, ver_min = self.read_ushort(), self.read_ushort()
         if ver_maj != 1:
-            raise TTFError, 'Unknown hhea table version %d.%04x' % (ver_maj, ver_min)
+            raise TTFError('Unknown hhea table version %d.%04x' % (ver_maj, ver_min))
         self.skip(28)
         metricDataFormat = self.read_ushort()
         if metricDataFormat != 0:
-            raise TTFError, 'Unknown horizontal metric data format (%d)' % metricDataFormat
+            raise TTFError('Unknown horizontal metric data format (%d)' % metricDataFormat)
         numberOfHMetrics = self.read_ushort()
         if numberOfHMetrics == 0:
-            raise TTFError, 'Number of horizontal metrics is 0'
+            raise TTFError('Number of horizontal metrics is 0')
 
         # maxp - Maximum profile table
         self.seek_table("maxp")
         ver_maj, ver_min = self.read_ushort(), self.read_ushort()
         if ver_maj != 1:
-            raise TTFError, 'Unknown maxp table version %d.%04x' % (ver_maj, ver_min)
+            raise TTFError('Unknown maxp table version %d.%04x' % (ver_maj, ver_min))
         numGlyphs = self.read_ushort()
 
         if not charInfo:
@@ -619,14 +619,14 @@
             return
 
         if glyphDataFormat != 0:
-            raise TTFError, 'Unknown glyph data format (%d)' % glyphDataFormat
+            raise TTFError('Unknown glyph data format (%d)' % glyphDataFormat)
 
         # cmap - Character to glyph index mapping table
         cmap_offset = self.seek_table("cmap")
         self.skip(2)
         cmapTableCount = self.read_ushort()
         unicode_cmap_offset = None
-        for n in xrange(cmapTableCount):
+        for n in range(cmapTableCount):
             platformID = self.read_ushort()
             encodingID = self.read_ushort()
             offset = self.read_ulong()
@@ -641,25 +641,25 @@
                     unicode_cmap_offset = cmap_offset + offset
                     break
         if unicode_cmap_offset is None:
-            raise TTFError, 'Font does not have cmap for Unicode (platform 3, encoding 1, format 4 or platform 0 any encoding format 4)'
+            raise TTFError('Font does not have cmap for Unicode (platform 3, encoding 1, format 4 or platform 0 any encoding format 4)')
         self.seek(unicode_cmap_offset + 2)
         length = self.read_ushort()
         limit = unicode_cmap_offset + length
         self.skip(2)
         segCount = int(self.read_ushort() / 2.0)
         self.skip(6)
-        endCount = map(lambda x, self=self: self.read_ushort(), xrange(segCount))
+        endCount = list(map(lambda x, self=self: self.read_ushort(), range(segCount)))
         self.skip(2)
-        startCount = map(lambda x, self=self: self.read_ushort(), xrange(segCount))
-        idDelta = map(lambda x, self=self: self.read_short(), xrange(segCount))
+        startCount = list(map(lambda x, self=self: self.read_ushort(), range(segCount)))
+        idDelta = list(map(lambda x, self=self: self.read_short(), range(segCount)))
         idRangeOffset_start = self._pos
-        idRangeOffset = map(lambda x, self=self: self.read_ushort(), xrange(segCount))
+        idRangeOffset = list(map(lambda x, self=self: self.read_ushort(), range(segCount)))
 
         # Now it gets tricky.
         glyphToChar = {}
         charToGlyph = {}
-        for n in xrange(segCount):
-            for unichar in xrange(startCount[n], endCount[n] + 1):
+        for n in range(segCount):
+            for unichar in range(startCount[n], endCount[n] + 1):
                 if idRangeOffset[n] == 0:
                     glyph = (unichar + idDelta[n]) & 0xFFFF
                 else:
@@ -685,7 +685,7 @@
         aw = None
         self.charWidths = {}
         self.hmetrics = []
-        for glyph in xrange(numberOfHMetrics):
+        for glyph in range(numberOfHMetrics):
             # advance width and left side bearing.  lsb is actually signed
             # short, but we don't need it anyway (except for subsetting)
             aw, lsb = self.read_ushort(), self.read_ushort()
@@ -696,7 +696,7 @@
             if glyph in glyphToChar:
                 for char in glyphToChar[glyph]:
                     self.charWidths[char] = aw
-        for glyph in xrange(numberOfHMetrics, numGlyphs):
+        for glyph in range(numberOfHMetrics, numGlyphs):
             # the rest of the table only lists advance left side bearings.
             # so we reuse aw set by the last iteration of the previous loop
             lsb = self.read_ushort()
@@ -709,13 +709,13 @@
         self.seek_table('loca')
         self.glyphPos = []
         if indexToLocFormat == 0:
-            for n in xrange(numGlyphs + 1):
+            for n in range(numGlyphs + 1):
                 self.glyphPos.append(self.read_ushort() << 1)
         elif indexToLocFormat == 1:
-            for n in xrange(numGlyphs + 1):
+            for n in range(numGlyphs + 1):
                 self.glyphPos.append(self.read_ulong())
         else:
-            raise TTFError, 'Unknown location table format (%d)' % indexToLocFormat
+            raise TTFError('Unknown location table format (%d)' % indexToLocFormat)
 
     # Subsetting
 
@@ -811,13 +811,13 @@
                 6, length, 0,   # format, length, language
                 0,
                 entryCount] + \
-               map(codeToGlyph.get, subset)
+               list(map(codeToGlyph.get, subset))
         cmap = pack(*([">%dH" % len(cmap)] + cmap))
         output.add('cmap', cmap)
 
         # hmtx - Horizontal Metrics
         hmtx = []
-        for n in xrange(numGlyphs):
+        for n in range(numGlyphs):
             originalGlyphIdx = glyphMap[n]
             aw, lsb = self.hmetrics[originalGlyphIdx]
             if n < numberOfHMetrics:
@@ -831,7 +831,7 @@
         offsets = []
         glyf = []
         pos = 0
-        for n in xrange(numGlyphs):
+        for n in range(numGlyphs):
             offsets.append(pos)
             originalGlyphIdx = glyphMap[n]
             glyphPos = self.glyphPos[originalGlyphIdx]
@@ -987,7 +987,7 @@
                 # Let's add the first 128 unicodes to the 0th subset, so ' '
                 # always has code 32 (for word spacing to work) and the ASCII
                 # output is readable
-                subset0 = range(128)
+                subset0 = list(range(128))
                 self.subsets = [subset0]
                 for n in subset0:
                     self.assignments[n] = n
@@ -1016,8 +1016,8 @@
 
     def _py_stringWidth(self, text, size, encoding='utf-8'):
         "Calculate text width"
-        if not isinstance(text,unicode):
-            text = unicode(text, encoding or 'utf-8')   # encoding defaults to utf-8
+        if not isinstance(text,str):
+            text = str(text, encoding or 'utf-8')   # encoding defaults to utf-8
         g = self.face.charWidths.get
         dw = self.face.defaultWidth
         return 0.001*size*sum([g(ord(u),dw) for u in text])
@@ -1046,8 +1046,8 @@
         curSet = -1
         cur = []
         results = []
-        if not isinstance(text,unicode):
-            text = unicode(text, encoding or 'utf-8')   # encoding defaults to utf-8
+        if not isinstance(text,str):
+            text = str(text, encoding or 'utf-8')   # encoding defaults to utf-8
         assignments = state.assignments
         subsets = state.subsets
         for code in map(ord,text):
@@ -1055,7 +1055,7 @@
                 n = assignments[code]
             else:
                 if state.frozen:
-                    raise pdfdoc.PDFError, "Font %s is already frozen, cannot add new character U+%04X" % (self.fontName, code)
+                    raise pdfdoc.PDFError("Font %s is already frozen, cannot add new character U+%04X" % (self.fontName, code))
                 n = state.nextCode
                 if n&0xFF==32:
                     # make code 32 always be a space character
@@ -1086,7 +1086,7 @@
         try: state = self.state[doc]
         except KeyError: state = self.state[doc] = TTFont.State(self._asciiReadable)
         if subset < 0 or subset >= len(state.subsets):
-            raise IndexError, 'Subset %d does not exist in font %s' % (subset, self.fontName)
+            raise IndexError('Subset %d does not exist in font %s' % (subset, self.fontName))
         if state.internalName is None:
             state.internalName = state.namePrefix +repr(len(doc.fontMapping) + 1)
             doc.fontMapping[self.fontName] = '/' + state.internalName
@@ -1116,7 +1116,7 @@
             pdfFont.FirstChar = 0
             pdfFont.LastChar = len(subset) - 1
 
-            widths = map(self.face.getCharWidth, subset)
+            widths = list(map(self.face.getCharWidth, subset))
             pdfFont.Widths = pdfdoc.PDFArray(widths)
 
             cmapStream = pdfdoc.PDFStream()
--- a/src/reportlab/pdfgen/canvas.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfgen/canvas.py	Tue Apr 30 14:20:22 2013 +0100
@@ -87,7 +87,7 @@
             return "DeviceRGB", aColor
         elif l == 4:
             return "DeviceCMYK", aColor
-    elif isinstance(aColor, basestring):
+    elif isinstance(aColor, str):
         return _normalizeColor(toColor(aColor))
     raise ValueError("Unknown color %r" % aColor)
 
@@ -119,14 +119,14 @@
         positions = [(1.0*x)/(nc-1) for x in range(nc)]
     else:
         # sort positions and colors in increasing order
-        poscolors = zip(positions, colors)
+        poscolors = list(zip(positions, colors))
         poscolors.sort(key=lambda x: x[0])
         # add endpoint positions if not already present
         if poscolors[0][0] != 0:
             poscolors.insert(0, (0.0, poscolors[0][1]))
         if poscolors[-1][0] != 1:
             poscolors.append((1.0, poscolors[-1][1]))
-        positions, colors = zip(*poscolors) # unzip
+        positions, colors = list(zip(*poscolors)) # unzip
     # build stitching function
     functions = []
     bounds = [pos for pos in positions[1:-1]]
@@ -172,7 +172,7 @@
 
     def getState(self):
         S = {}
-        for t,name in self._c.iteritems():
+        for t,name in self._c.items():
             S[name] = pdfdoc.PDFDictionary(dict((t,)))
         return S and pdfdoc.PDFDictionary(S) or None
 
@@ -317,8 +317,8 @@
         '''
         if encrypt:
             from reportlab.lib import pdfencrypt
-            if isinstance(encrypt, basestring): #encrypt is the password itself
-                if isinstance(encrypt, unicode):
+            if isinstance(encrypt, str): #encrypt is the password itself
+                if isinstance(encrypt, str):
                     encrypt = encrypt.encode('utf-8')
                 encrypt = pdfencrypt.StandardEncryption(encrypt)    #now it's the encrypt object
                 encrypt.setAllPermissions(1)
@@ -381,7 +381,7 @@
      _fillMode _charSpace _wordSpace _horizScale _textRenderMode _rise _textLineMatrix
      _textMatrix _lineCap _lineJoin _lineDash _lineWidth _mitreLimit _fillColorObj
      _strokeColorObj _extgstate""")
-    STATE_RANGE = range(len(STATE_ATTRIBUTES))
+    STATE_RANGE = list(range(len(STATE_ATTRIBUTES)))
 
         #self._addStandardFonts()
 
@@ -833,7 +833,7 @@
         """
     
         self._currentPageHasImages = 1
-        from pdfimages import PDFImage
+        from .pdfimages import PDFImage
         img_obj = PDFImage(image, x,y, width, height)
         img_obj.drawInlineImage(self,
             preserveAspectRatio=preserveAspectRatio, 
@@ -1255,7 +1255,7 @@
                                    a0*e+c0*f+e0, b0*e+d0*f+f0)
         if self._code and self._code[-1][-3:]==' cm':
             L = split(self._code[-1])
-            a0, b0, c0, d0, e0, f0 = map(float,L[-7:-1])
+            a0, b0, c0, d0, e0, f0 = list(map(float,L[-7:-1]))
             s = len(L)>7 and join(L)+ ' %s cm' or '%s cm'
             self._code[-1] = s % fp_str(a0*a+c0*b,b0*a+d0*b,a0*c+c0*d,b0*c+d0*d,a0*e+c0*f+e0,b0*e+d0*f+f0)
         else:
@@ -1264,7 +1264,7 @@
     def absolutePosition(self, x, y):
         """return the absolute position of x,y in user space w.r.t. default user space"""
         if not ENABLE_TRACKING:
-            raise ValueError, "tracking not enabled! (canvas.ENABLE_TRACKING=0)"
+            raise ValueError("tracking not enabled! (canvas.ENABLE_TRACKING=0)")
         (a,b,c,d,e,f) = self._currentMatrix
         xp = a*x + c*y + e
         yp = b*x + d*y + f
@@ -1571,7 +1571,7 @@
 
     def listLoadedFonts0(self):
         "Convenience function to list all loaded fonts"
-        names = pdfmetrics.widths.keys()
+        names = list(pdfmetrics.widths.keys())
         names.sort()
         return names
 
@@ -1808,4 +1808,4 @@
     Canvas._escape = new.instancemethod(_instanceEscapePDF,None,Canvas)
 
 if __name__ == '__main__':
-    print 'For test scripts, look in tests'
+    print('For test scripts, look in tests')
--- a/src/reportlab/pdfgen/pdfimages.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfgen/pdfimages.py	Tue Apr 30 14:20:22 2013 +0100
@@ -85,7 +85,7 @@
         cachedname = os.path.splitext(image)[0] + (rl_config.useA85 and '.a85' or '.bin')
         imagedata = open(cachedname,'rb').readlines()
         #trim off newlines...
-        imagedata = map(string.strip, imagedata)
+        imagedata = list(map(string.strip, imagedata))
         return imagedata
 
     def PIL_imagedata(self):
@@ -204,5 +204,5 @@
     img = PDFImage(srcfile, 100, 100)
     import pprint
     doc = pdfdoc.PDFDocument()
-    print 'source=',img.source
-    print img.format(doc)
+    print('source=',img.source)
+    print(img.format(doc))
--- a/src/reportlab/pdfgen/pycanvas.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfgen/pycanvas.py	Tue Apr 30 14:20:22 2013 +0100
@@ -97,7 +97,7 @@
     - For fun because you can do it !
 """
 
-import cStringIO
+import io
 from reportlab.pdfgen import canvas
 from reportlab.pdfgen import pathobject
 from reportlab.pdfgen import textobject
@@ -149,7 +149,7 @@
     arguments = ""
     for arg in args :
         arguments = arguments + ("%s, " % repr(arg))
-    for (kw, val) in kwargs.items() :
+    for (kw, val) in list(kwargs.items()) :
         arguments = arguments+ ("%s=%s, " % (kw, repr(val)))
     if arguments[-2:] == ", " :
         arguments = arguments[:-2]
@@ -274,7 +274,7 @@
         self._footerpresent = 0
         self._object = canvas.Canvas(*args,**kwargs)
         self._enforceColorSpace = self._object._enforceColorSpace
-        self._pyfile = cStringIO.StringIO()
+        self._pyfile = io.StringIO()
         self._PyWrite(PyHeader)
         try :
             del kwargs["filename"]
@@ -282,7 +282,7 @@
             pass
         self._PyWrite("    # create the PDF document\n    %s = Canvas(file, %s)\n\n    # Begins page 1" % (self._name, buildargs(*args[1:], **kwargs)))
 
-    def __nonzero__(self) :
+    def __bool__(self) :
         """This is needed by platypus' tables."""
         return 1
 
@@ -307,4 +307,4 @@
         self._pyfile.write("%s\n" % pycode)
 
 if __name__ == '__main__':
-    print 'For test scripts, look in tests'
+    print('For test scripts, look in tests')
--- a/src/reportlab/pdfgen/textobject.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/pdfgen/textobject.py	Tue Apr 30 14:20:22 2013 +0100
@@ -78,7 +78,7 @@
                 self._code.append('%s k' % fp_str(aColor))
             else:
                 raise ValueError('Unknown color %r' % aColor)
-        elif isinstance(aColor,basestring):
+        elif isinstance(aColor,str):
             self.setFillColor(toColor(aColor))
         else:
             raise ValueError('Unknown color %r' % aColor)
@@ -114,7 +114,7 @@
                 self._code.append('%s K' % fp_str(aColor))
             else:
                 raise ValueError('Unknown color %r' % aColor)
-        elif isinstance(aColor,basestring):
+        elif isinstance(aColor,str):
             self.setStrokeColor(toColor(aColor))
         else:
             raise ValueError('Unknown color %r' % aColor)
@@ -383,10 +383,10 @@
         else:
             #convert to T1  coding
             fc = font
-            if not isinstance(text,unicode):
+            if not isinstance(text,str):
                 try:
                     text = text.decode('utf8')
-                except UnicodeDecodeError,e:
+                except UnicodeDecodeError as e:
                     i,j = e.args[2:4]
                     raise UnicodeDecodeError(*(e.args[:4]+('%s\n%s-->%s<--%s' % (e.args[4],text[max(i-10,0):i],text[i:j],text[j:j+10]),)))
 
@@ -431,10 +431,10 @@
         since this may be indented, by default it trims whitespace
         off each line and from the beginning; set trim=0 to preserve
         whitespace."""
-        if isinstance(stuff,basestring):
+        if isinstance(stuff,str):
             lines = string.split(string.strip(stuff), '\n')
             if trim==1:
-                lines = map(string.strip,lines)
+                lines = list(map(string.strip,lines))
         elif isinstance(stuff,(tuple,list)):
             lines = stuff
         else:
@@ -445,6 +445,6 @@
         for line in lines:
             self.textLine(line)
 
-    def __nonzero__(self):
+    def __bool__(self):
         'PDFTextObject is true if it has something done after the init'
         return self._code != ['BT']
--- a/src/reportlab/platypus/__init__.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/platypus/__init__.py	Tue Apr 30 14:20:22 2013 +0100
@@ -13,4 +13,4 @@
 from reportlab.platypus.frames import Frame
 from reportlab.platypus.doctemplate import BaseDocTemplate, NextPageTemplate, PageTemplate, ActionFlowable, \
                         SimpleDocTemplate, FrameBreak, PageBegin, Indenter, NotAtTopPageBreak
-from xpreformatted import XPreformatted
+from .xpreformatted import XPreformatted
--- a/src/reportlab/platypus/doctemplate.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/platypus/doctemplate.py	Tue Apr 30 14:20:22 2013 +0100
@@ -42,7 +42,7 @@
 
 from base64 import encodestring, decodestring
 try:
-    import cPickle as pickle
+    import pickle as pickle
 except ImportError:
     import pickle
 dumps = pickle.dumps
@@ -144,14 +144,14 @@
             pass
         try:
             getattr(doc,arn)(*args)
-        except AttributeError, aerr:
+        except AttributeError as aerr:
             if aerr.args[0]==arn:
-                raise NotImplementedError, "Can't handle ActionFlowable(%s)" % action
+                raise NotImplementedError("Can't handle ActionFlowable(%s)" % action)
             else:
                 raise
         except:
             t, v, tb = sys.exc_info()
-            raise t, "%s\n   handle_%s args=%s"%(v,action,args), tb
+            raise t("%s\n   handle_%s args=%s"%(v,action,args)).with_traceback(tb)
 
     def __call__(self):
         return self
@@ -203,7 +203,7 @@
 
 def _evalMeasurement(n):
     if type(n) is type(''):
-        from paraparser import _num
+        from .paraparser import _num
         n = _num(n)
         if type(n) is type(()): n = n[1]
     return n
@@ -256,7 +256,7 @@
                  pagesize=None, autoNextPageTemplate=None):
         frames = frames or []
         if type(frames) not in (ListType,TupleType): frames = [frames]
-        assert filter(lambda x: not isinstance(x,Frame), frames)==[], "frames argument error"
+        assert [x for x in frames if not isinstance(x,Frame)]==[], "frames argument error"
         self.id = id
         self.frames = frames
         self.onPage = onPage
@@ -282,9 +282,9 @@
         cp = None
         dp = None
         sp = None
-        if canv._pagesize: cp = map(int, canv._pagesize)
-        if self.pagesize: sp = map(int, self.pagesize)
-        if doc.pagesize: dp = map(int, doc.pagesize)
+        if canv._pagesize: cp = list(map(int, canv._pagesize))
+        if self.pagesize: sp = list(map(int, self.pagesize))
+        if doc.pagesize: dp = list(map(int, doc.pagesize))
         if cp!=sp:
             if sp:
                 canv.setPageSize(self.pagesize)
@@ -463,12 +463,12 @@
         self._nameSpace = dict(doc=self)
         self._lifetimes = {}
 
-        for k in self._initArgs.keys():
+        for k in list(self._initArgs.keys()):
             if k not in kw:
                 v = self._initArgs[k]
             else:
                 if k in self._invalidInitArgs:
-                    raise ValueError, "Invalid argument %s" % k
+                    raise ValueError("Invalid argument %s" % k)
                 v = kw[k]
             setattr(self,k,v)
 
@@ -585,7 +585,7 @@
 
             if hasattr(self,'_nextPageTemplateCycle'):
                 #they are cycling through pages'; we keep the index
-                self.pageTemplate = self._nextPageTemplateCycle.next()
+                self.pageTemplate = next(self._nextPageTemplateCycle)
             elif hasattr(self,'_nextPageTemplateIndex'):
                 self.pageTemplate = self.pageTemplates[self._nextPageTemplateIndex]
                 del self._nextPageTemplateIndex
@@ -644,7 +644,7 @@
                 if t.id == pt:
                     self._nextPageTemplateIndex = self.pageTemplates.index(t)
                     return
-            raise ValueError, "can't find template('%s')"%pt
+            raise ValueError("can't find template('%s')"%pt)
         elif type(pt) is IntType:
             if hasattr(self, '_nextPageTemplateCycle'): del self._nextPageTemplateCycle
             self._nextPageTemplateIndex = pt
@@ -684,7 +684,7 @@
         elif type(fx) is IntType:
             self._nextFrameIndex = fx
         else:
-            raise TypeError, "argument fx should be string or integer"
+            raise TypeError("argument fx should be string or integer")
 
     def handle_currentFrame(self,fx,resume=0):
         '''change to the frame with name or index fx'''
@@ -938,8 +938,8 @@
 
     def pageRef(self, label):
         """hook to register a page number"""
-        if verbose: print "pageRef called with label '%s' on page %d" % (
-            label, self.page)
+        if verbose: print("pageRef called with label '%s' on page %d" % (
+            label, self.page))
         self._pageRefs[label] = self.page
 
     def multiBuild(self, story,
@@ -965,7 +965,7 @@
             passes += 1
             if self._onProgress:
                 self._onProgress('PASS', passes)
-            if verbose: print 'building pass '+str(passes) + '...',
+            if verbose: print('building pass '+str(passes) + '...', end=' ')
 
             for fl in self._indexingFlowables:
                 fl.beforeBuild()
@@ -985,7 +985,7 @@
                 self.canv.save()
                 break
             if passes > maxPasses:
-                raise IndexError, "Index entries not resolved after %d passes" % maxPasses
+                raise IndexError("Index entries not resolved after %d passes" % maxPasses)
 
             #work through any edits
             while mbe:
@@ -993,7 +993,7 @@
                 e[0](*e[1:])
 
         del self._multiBuildEdits
-        if verbose: print 'saved'
+        if verbose: print('saved')
         return passes
         
     #these are pure virtuals override in derived classes
@@ -1035,7 +1035,7 @@
 
     _allowedLifetimes = 'page','frame','build','forever'
     def docAssign(self,var,expr,lifetime):
-        if not isinstance(expr,(str,unicode)): expr=str(expr)
+        if not isinstance(expr,str): expr=str(expr)
         expr=expr.strip()
         var=var.strip()
         self.docExec('%s=(%s)'%(var.strip(),expr.strip()),lifetime)
@@ -1043,28 +1043,28 @@
     def docExec(self,stmt,lifetime):
         stmt=stmt.strip()
         NS=self._nameSpace
-        K0=NS.keys()
+        K0=list(NS.keys())
         try:
             if lifetime not in self._allowedLifetimes:
                 raise ValueError('bad lifetime %r not in %r'%(lifetime,self._allowedLifetimes))
-            exec stmt in {},NS
+            exec(stmt, {},NS)
         except:
             exc = sys.exc_info()[1]
             args = list(exc.args)
             msg = '\ndocExec %s lifetime=%r failed!' % (stmt,lifetime)
             args.append(msg)
             exc.args = tuple(args)
-            for k in NS.iterkeys():
+            for k in NS.keys():
                 if k not in K0:
                     del NS[k]
             raise
-        self._addVars([k for k in NS.iterkeys() if k not in K0],lifetime)
+        self._addVars([k for k in NS.keys() if k not in K0],lifetime)
 
     def _addVars(self,vars,lifetime):
         '''add namespace variables to lifetimes lists'''
         LT=self._lifetimes
         for var in vars:
-            for v in LT.itervalues():
+            for v in LT.values():
                 if var in v:
                     v.remove(var)
             LT.setdefault(lifetime,set([])).add(var)
@@ -1165,7 +1165,7 @@
     really accurate would be to do two passes, and I don't
     want to take that performance hit.
     """
-    print 'PROGRESS MONITOR:  %-10s   %d' % (typ, value)
+    print('PROGRESS MONITOR:  %-10s   %d' % (typ, value))
 
 if __name__ == '__main__':
     from reportlab.lib.styles import _baseFontName, _baseFontNameB
@@ -1197,7 +1197,7 @@
         objects_to_draw = []
         from reportlab.lib.styles import ParagraphStyle
         #from paragraph import Paragraph
-        from doctemplate import SimpleDocTemplate
+        from .doctemplate import SimpleDocTemplate
 
         #need a style
         normal = ParagraphStyle('normal')
--- a/src/reportlab/platypus/flowables.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/platypus/flowables.py	Tue Apr 30 14:20:22 2013 +0100
@@ -33,6 +33,7 @@
 from reportlab.pdfbase import pdfutils
 from reportlab.pdfbase.pdfmetrics import stringWidth
 from reportlab.rl_config import _FUZZ, overlapAttachedSpace, ignoreContainerActions
+import collections
 
 __all__=('TraceInfo','Flowable','XBox','Preformatted','Image','Spacer','PageBreak','SlowPageBreak',
         'CondPageBreak','KeepTogether','Macro','CallerMacro','ParagraphAndImage',
@@ -98,7 +99,7 @@
             elif a in ('RIGHT',TA_RIGHT):
                 x += sW
             elif a not in ('LEFT',TA_LEFT):
-                raise ValueError, "Bad hAlign value "+str(a)
+                raise ValueError("Bad hAlign value "+str(a))
         return x
 
     def drawOn(self, canvas, x, y, _sW=0):
@@ -491,7 +492,7 @@
 
     def identity(self,maxLen=None):
         r = Flowable.identity(self,maxLen)
-        if r[-4:]=='>...' and isinstance(self.filename,basestring):
+        if r[-4:]=='>...' and isinstance(self.filename,str):
             r = "%s filename=%s>" % (r[:-4],self.filename)
         return r
 
@@ -545,7 +546,7 @@
         if availHeight<self.height:
             f = self._doctemplateAttr('frame')
             if not f: return availWidth, availHeight
-            from doctemplate import FrameBreak
+            from .doctemplate import FrameBreak
             f.add_generated_content(FrameBreak)
         return 0, 0
 
@@ -600,7 +601,7 @@
 def _flowableSublist(V):
     "if it isn't a list or tuple, wrap it in a list"
     if not isinstance(V,(list,tuple)): V = V is not None and [V] or []
-    from doctemplate import LCActionFlowable
+    from .doctemplate import LCActionFlowable
     assert not [x for x in V if isinstance(x,LCActionFlowable)],'LCActionFlowables not allowed in sublists'
     return V
 
@@ -628,7 +629,7 @@
 
     def __repr__(self):
         f = self._content
-        L = map(repr,f)
+        L = list(map(repr,f))
         L = "\n"+"\n".join(L)
         L = L.replace("\n", "\n  ")
         return "%s(%s,maxHeight=%s)" % (self.__class__.__name__,L,self._maxHeight)
@@ -650,10 +651,10 @@
         C1 = (self._H0>aH) or C0 and atTop
         if C0 or C1:
             if C0:
-                from doctemplate import FrameBreak
+                from .doctemplate import FrameBreak
                 A = FrameBreak
             else:
-                from doctemplate import NullActionFlowable
+                from .doctemplate import NullActionFlowable
                 A = NullActionFlowable
             S.insert(0,A())
         return S
@@ -676,7 +677,7 @@
     def wrap(self, availWidth, availHeight):
         return (0,0)
     def draw(self):
-        exec self.command in globals(), {'canvas':self.canv}
+        exec(self.command, globals(), {'canvas':self.canv})
 
 class CallerMacro(Flowable):
     '''
@@ -829,7 +830,7 @@
 class _Container(_ContainerSpace):  #Abstract some common container like behaviour
     def drawOn(self, canv, x, y, _sW=0, scale=1.0, content=None, aW=None):
         '''we simulate being added to a frame'''
-        from doctemplate import ActionFlowable, Indenter
+        from .doctemplate import ActionFlowable, Indenter
         pS = 0
         if aW is None: aW = self.width
         aW *= scale
@@ -890,10 +891,10 @@
         n = len(C)
         I2W = {}
         dLeft = dRight = 0
-        for x in xrange(n):
+        for x in range(n):
             c = C[x]
             I = c._ptoinfo
-            if I not in I2W.keys():
+            if I not in list(I2W.keys()):
                 T = I.trailer
                 Hdr = I.header
                 tW, tH = _listWrapOn(T, availWidth, self.canv)
@@ -1027,7 +1028,7 @@
                 getattr(self,'maxHeight','')and (' maxHeight=%s' % fp_str(getattr(self,'maxHeight')))or '')
 
     def wrap(self,availWidth,availHeight):
-        from doctemplate import LayoutError
+        from .doctemplate import LayoutError
         mode = self.mode
         maxWidth = float(min(self.maxWidth or availWidth,availWidth))
         maxHeight = float(min(self.maxHeight or availHeight,availHeight))
@@ -1238,7 +1239,7 @@
                 return W, availHeight, F[:i],F[i:]
             H += h
             if H>availHeight:
-                from paragraph import Paragraph
+                from .paragraph import Paragraph
                 aH = availHeight-(H-h)
                 if isinstance(f,(Paragraph,Preformatted)):
                     leading = f.style.leading
@@ -1326,12 +1327,12 @@
 
 from reportlab.lib.sequencer import _type2formatter
 _bulletNames = dict(
-                bulletchar=u'\u2022',   #usually a small circle
-                circle=u'\u25cf',   #circle as high as the font
-                square=u'\u25a0',
-                disc=u'\u25cf',
-                diamond=u'\u25c6',
-                rarrowhead=u'\u27a4',
+                bulletchar='\u2022',    #usually a small circle
+                circle='\u25cf',    #circle as high as the font
+                square='\u25a0',
+                disc='\u25cf',
+                diamond='\u25c6',
+                rarrowhead='\u27a4',
                 )
 
 def _bulletFormat(value,type='1',format=None):
@@ -1341,9 +1342,9 @@
         s = _type2formatter[type](int(value))
 
     if format:
-        if isinstance(format,basestring):
+        if isinstance(format,str):
             s = format % s
-        elif callable(format):
+        elif isinstance(format, collections.Callable):
             s = format(s)
         else:
             raise ValueError('unexpected BulletDrawer format %r' % format)
@@ -1563,7 +1564,7 @@
                 raise ValueError('%s style argument not a ListStyle' % self.__class__.__name__)
             self.style = style
 
-        for k,v in ListStyle.defaults.iteritems():
+        for k,v in ListStyle.defaults.items():
             setattr(self,'_'+k,kwds.get(k,getattr(style,k,v)))
         if start is None:
             start = getattr(self,'_start',None)
@@ -1824,7 +1825,7 @@
     def func(self):
         expr = self.expr
         if expr:
-            if not isinstance(expr,(str,unicode)): expr = str(expr)
+            if not isinstance(expr,str): expr = str(expr)
             return self._doctemplateAttr('docEval')(expr)
 
     def add_content(self,*args):
--- a/src/reportlab/platypus/frames.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/platypus/frames.py	Tue Apr 30 14:20:22 2013 +0100
@@ -19,7 +19,7 @@
         self.color = color
         self.width = width
 
-    def __nonzero__(self):
+    def __bool__(self):
         return self.color is not None and self.width>=0
 
 class Frame:
@@ -96,7 +96,7 @@
             for ga in _geomAttr:
                 ga = '_'+ga
                 self.__dict__['_savedGeom'][ga] = self.__dict__[ga]
-        for k,v in kwds.iteritems():
+        for k,v in kwds.items():
             setattr(self,k,v)
 
     def _restoreGeom(self):
--- a/src/reportlab/platypus/para.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/platypus/para.py	Tue Apr 30 14:20:22 2013 +0100
@@ -152,8 +152,8 @@
             linewidth = maxwidth - indent - rightIndent
             beforelinestate = self.__dict__.copy()
             if linewidth<TOOSMALLSPACE:
-                raise ValueError, "indents %s %s too wide for space %s" % (self.indent, self.rightIndent, \
-                                                                           maxwidth)
+                raise ValueError("indents %s %s too wide for space %s" % (self.indent, self.rightIndent, \
+                                                                           maxwidth))
             try:
                 (lineIsFull, line, cursor, currentLength, \
                  usedIndent, maxLength, justStrings) = self.fitLine(remainder, maxwidth)
@@ -228,9 +228,9 @@
                     else:
                         line = self.shrinkWrap(line)
                     if debug:
-                        print "no justify because line is not full or end of para"
+                        print("no justify because line is not full or end of para")
             else:
-                raise ValueError, "bad alignment "+repr(alignment)
+                raise ValueError("bad alignment "+repr(alignment))
             if not justStrings:
                 line = self.cleanProgram(line)
             lineprogram.extend(line)
@@ -411,7 +411,7 @@
                     indent = indent + self.baseindent
                     opcode = (i, bullet, indent, font, size)
                     if not first:
-                        raise ValueError, "bullet not at beginning of line"
+                        raise ValueError("bullet not at beginning of line")
                     bulletwidth = float(stringWidth(bullet, font, size))
                     spacewidth = float(stringWidth(" ", font, size))
                     bulletmin = indent+spacewidth+bulletwidth
@@ -449,9 +449,9 @@
                     line.append(opcode)
 
                 else:
-                    raise ValueError, "at format time don't understand indicator "+repr(indicator)
+                    raise ValueError("at format time don't understand indicator "+repr(indicator))
             else:
-                raise ValueError, "op must be string, float, instance, or tuple "+repr(opcode)
+                raise ValueError("op must be string, float, instance, or tuple "+repr(opcode))
             if not done:
                 cursor = cursor+1
                 #first = 0
@@ -629,7 +629,7 @@
 ##            count = count-1
         # move end operations left and start operations left up to visibles
         change = 1
-        rline = range(len(result)-1)
+        rline = list(range(len(result)-1))
         while change:
             #print line
             change = 0
@@ -789,7 +789,7 @@
                 elif indicator=="bullet":
                     (i, bullet, indent, font, size) = opcode
                     if abs(self.x-xstart)>TOOSMALLSPACE:
-                        raise ValueError, "bullet not at beginning of line"
+                        raise ValueError("bullet not at beginning of line")
                     bulletwidth = float(stringWidth(bullet, font, size))
                     spacewidth = float(stringWidth(" ", font, size))
                     bulletmin = indent+spacewidth+bulletwidth
@@ -831,9 +831,9 @@
                         pass
                         #print "WARNING: HANDLER", handler, "NOT IN", newh
                 else:
-                    raise ValueError, "don't understand indicator "+repr(indicator)
+                    raise ValueError("don't understand indicator "+repr(indicator))
             else:
-                raise ValueError, "op must be string float or tuple "+repr(opcode)
+                raise ValueError("op must be string float or tuple "+repr(opcode))
         laststate = self.__dict__.copy()
         #self.resetState(startstate)
         self.__dict__.update(startstate)
@@ -881,7 +881,7 @@
     elif text.upper() in ("N", "NO", "FALSE", "0"):
         return 0
     else:
-        raise RMLError, "true/false attribute has illegal value '%s'" % text
+        raise RMLError("true/false attribute has illegal value '%s'" % text)
 
 def readAlignment(text):
     up = text.upper()
@@ -907,7 +907,7 @@
         try:
             number = float(numberText)
         except ValueError:
-            raise ValueError, "invalid length attribute '%s'" % text
+            raise ValueError("invalid length attribute '%s'" % text)
         try:
             multiplier = {
                 'in':72,
@@ -916,7 +916,7 @@
                 'pt':1
                 }[units]
         except KeyError:
-            raise RMLError, "invalid length attribute '%s'" % text
+            raise RMLError("invalid length attribute '%s'" % text)
 
         return number * multiplier
 
@@ -988,13 +988,13 @@
     def __init__(self, name, parent=None, **kw):
         mydict = self.__dict__
         if parent:
-            for (a,b) in parent.__dict__.items():
+            for (a,b) in list(parent.__dict__.items()):
                 mydict[a]=b
-        for (a,b) in kw.items():
+        for (a,b) in list(kw.items()):
             mydict[a] =  b
 
     def addAttributes(self, dictionary):
-        for key in dictionary.keys():
+        for key in list(dictionary.keys()):
             value = dictionary[key]
             if value is not None:
                 if hasattr(StyleAttributeConverters, key):
@@ -1026,7 +1026,7 @@
         #if debug:
         #    print "FAST", id(self)
         if "&" in simpletext:
-            raise ValueError, "no ampersands please!"
+            raise ValueError("no ampersands please!")
         self.style = style
         self.simpletext = simpletext
         self.lines = None
@@ -1110,7 +1110,7 @@
             return [] # not enough space for split
         lines = self.lines
         if lines is None:
-            raise ValueError, "must wrap before split"
+            raise ValueError("must wrap before split")
         remainder = self.remainder
         if remainder:
             next = FastPara(style, remainder)
@@ -1186,7 +1186,7 @@
     result = {}
     from reportlab.lib.styles import getSampleStyleSheet
     styles = getSampleStyleSheet()
-    for (stylenamekey, stylenamevalue) in DEFAULT_ALIASES.items():
+    for (stylenamekey, stylenamevalue) in list(DEFAULT_ALIASES.items()):
         result[stylenamekey] = styles[stylenamevalue]
     return result
 
@@ -1195,17 +1195,17 @@
     from reportlab.lib.styles import getSampleStyleSheet
     if stylesheet is not None:
         # Copy styles with the same name as aliases
-        for (stylenamekey, stylenamevalue) in DEFAULT_ALIASES.items():
+        for (stylenamekey, stylenamevalue) in list(DEFAULT_ALIASES.items()):
             if stylenamekey in stylesheet:
                 result[stylenamekey] = stylesheet[stylenamekey]
         # Then make aliases
-        for (stylenamekey, stylenamevalue) in DEFAULT_ALIASES.items():
+        for (stylenamekey, stylenamevalue) in list(DEFAULT_ALIASES.items()):
             if stylenamevalue in stylesheet:
                 result[stylenamekey] = stylesheet[stylenamevalue]
 
     styles = getSampleStyleSheet()
     # Then, fill in defaults if they were not filled yet.
-    for (stylenamekey, stylenamevalue) in DEFAULT_ALIASES.items():
+    for (stylenamekey, stylenamevalue) in list(DEFAULT_ALIASES.items()):
         if stylenamekey not in result and stylenamevalue in styles:
             result[stylenamekey] = styles[stylenamevalue]
     return result
@@ -1249,9 +1249,9 @@
 
     def wrap(self, availableWidth, availableHeight):
         if debug:
-            print "WRAPPING", id(self), availableWidth, availableHeight
-            print "   ", self.formattedProgram
-            print "   ", self.program
+            print("WRAPPING", id(self), availableWidth, availableHeight)
+            print("   ", self.formattedProgram)
+            print("   ", self.program)
         self.availableHeight = availableHeight
         self.myengine = p = paragraphEngine()
         p.baseindent = self.baseindent # for shifting bullets as needed
@@ -1277,7 +1277,7 @@
             #    print "CANNOT COMPILE, NEED AT LEAST", needatleast, 'AVAILABLE', availableHeight
             return (availableHeight+1, availableWidth) # cannot split
         if parsedText is None and program is None:
-            raise ValueError, "need parsedText for formatting"
+            raise ValueError("need parsedText for formatting")
         if not program:
             self.program = program = self.compileProgram(parsedText)
         if not self.formattedProgram:
@@ -1315,8 +1315,8 @@
         if debug:
             (w, h) = result
             if abs(availableHeight-h)<0.2:
-                print "exact match???" + repr(availableHeight, h)
-            print "wrap is", (availableWidth, availableHeight), result
+                print("exact match???" + repr(availableHeight, h))
+            print("wrap is", (availableWidth, availableHeight), result)
         return result
 
     def split(self, availableWidth, availableHeight):
@@ -1330,7 +1330,7 @@
         formattedProgram = self.formattedProgram
         #print "formattedProgram is", formattedProgram
         if formattedProgram is None:
-            raise ValueError, "must call wrap before split"
+            raise ValueError("must call wrap before split")
         elif not formattedProgram:
             # no first line in self: fail to split
             return []
@@ -1347,7 +1347,7 @@
         p = self.myengine #paragraphEngine()
         formattedProgram = self.formattedProgram
         if formattedProgram is None:
-            raise ValueError, "must call wrap before draw"
+            raise ValueError("must call wrap before draw")
         state = self.state
         laststate = self.laststate
         if state:
@@ -1368,10 +1368,10 @@
         t = c.beginText()
         #t.setTextOrigin(0,0)
         if DUMPPROGRAM or debug:
-            print "="*44, "now running program"
+            print("="*44, "now running program")
             for x in formattedProgram:
-                print x
-            print "-"*44
+                print(x)
+            print("-"*44)
         laststate = p.runOpCodes(formattedProgram, c, t)
         #print laststate["x"], laststate["y"]
         c.drawText(t)
@@ -1490,7 +1490,7 @@
                     L = [ "<" + tagname ]
                     a = L.append
                     if not attdict: attdict = {}
-                    for (k, v) in attdict.items():
+                    for (k, v) in list(attdict.items()):
                         a(" %s=%s" % (k,v))
                     if content:
                         a(">")
@@ -1501,7 +1501,7 @@
                     t = ''.join(L)
                     handleSpecialCharacters(self, t, program)
                 else:
-                    raise ValueError, "don't know how to handle tag " + repr(tagname)
+                    raise ValueError("don't know how to handle tag " + repr(tagname))
 
     def shiftfont(self, program, face=None, bold=None, italic=None):
         oldface = self.face
@@ -1573,11 +1573,11 @@
             te = type(e)
             if te in (StringType, UnicodeType):
                 if e.strip():
-                    raise ValueError, "don't expect CDATA between list elements"
+                    raise ValueError("don't expect CDATA between list elements")
             elif te is TupleType:
                 (tagname, attdict1, content1, extra) = e
                 if tagname!="li":
-                    raise ValueError, "don't expect %s inside list" % repr(tagname)
+                    raise ValueError("don't expect %s inside list" % repr(tagname))
                 newatts = atts.copy()
                 if attdict1:
                     newatts.update(attdict1)
@@ -1604,7 +1604,7 @@
             te = type(e)
             if te in (StringType, UnicodeType):
                 if e.strip():
-                    raise ValueError, "don't expect CDATA between list elements"
+                    raise ValueError("don't expect CDATA between list elements")
                 elif not contentcopy:
                     break # done at ending whitespace
                 else:
@@ -1612,11 +1612,11 @@
             elif te is TupleType:
                 (tagname, attdict1, content1, extra) = e
                 if tagname!="dd" and tagname!="dt":
-                    raise ValueError, "don't expect %s here inside list, expect 'dd' or 'dt'" % \
-                          repr(tagname)
+                    raise ValueError("don't expect %s here inside list, expect 'dd' or 'dt'" % \
+                          repr(tagname))
                 if tagname=="dt":
                     if bullet:
-                        raise ValueError, "dt will not be displayed unless followed by a dd: "+repr(bullet)
+                        raise ValueError("dt will not be displayed unless followed by a dd: "+repr(bullet))
                     if content1:
                         self.compile_para(attdict1, content1, extra, program)
                         # raise ValueError, \
@@ -1629,7 +1629,7 @@
                     self.compile_para(newatts, content1, extra, program)
                     bullet = "" # don't use this bullet again
         if bullet:
-            raise ValueError, "dt will not be displayed unless followed by a dd"+repr(bullet)
+            raise ValueError("dt will not be displayed unless followed by a dd"+repr(bullet))
 
     def compile_super(self, attdict, content, extra, program):
         size = self.size
@@ -1722,7 +1722,7 @@
     def compile_bullet(self, attdict, content, extra, program):
         ### eventually should allow things like images and graphics in bullets too XXXX
         if len(content)!=1 or type(content[0]) not in (StringType, UnicodeType):
-            raise ValueError, "content for bullet must be a single string"
+            raise ValueError("content for bullet must be a single string")
         text = content[0]
         self.do_bullet(text, program)
 
@@ -1814,7 +1814,7 @@
                 elif typ=="circle": bl = chr(108)
                 elif typ=="square": bl = chr(110)
                 else:
-                    raise ValueError, "unordered list type %s not implemented" % repr(typ)
+                    raise ValueError("unordered list type %s not implemented" % repr(typ))
                 if "bulletFontName" not in atts:
                     atts["bulletFontName"] = "ZapfDingbats"
             elif tagname=="ol":
@@ -1830,9 +1830,9 @@
                     theord = ord("A")+self.count-1
                     bl = chr(theord)
                 else:
-                    raise ValueError, "ordered bullet type %s not implemented" % repr(typ)
+                    raise ValueError("ordered bullet type %s not implemented" % repr(typ))
             else:
-                raise ValueError, "bad tagname "+repr(tagname)
+                raise ValueError("bad tagname "+repr(tagname))
         if "bulletText" not in atts:
             atts["bulletText"] = bl
         if "style" not in atts:
@@ -1993,7 +1993,7 @@
     Controller["title"] = theParaMapper
 
 def handleSpecialCharacters(engine, text, program=None):
-    from paraparser import greeks
+    from .paraparser import greeks
     from string import whitespace, atoi, atoi_error
     standard={'lt':'<', 'gt':'>', 'amp':'&'}
     # add space prefix if space here
@@ -2031,17 +2031,17 @@
                     except atoi_error:
                         n = -1
                     if n>=0:
-                        fragment = unichr(n).encode('utf8')+fragment[semi+1:]
+                        fragment = chr(n).encode('utf8')+fragment[semi+1:]
                     else:
                         fragment = "&"+fragment
                 elif name in standard:
                     s = standard[name]
-                    if isinstance(fragment,unicode):
+                    if isinstance(fragment,str):
                         s = s.decode('utf8')
                     fragment = s+fragment[semi+1:]
                 elif name in greeks:
                     s = greeks[name]
-                    if isinstance(fragment,unicode):
+                    if isinstance(fragment,str):
                         s = s.decode('utf8')
                     fragment = s+fragment[semi+1:]
                 else:
@@ -2108,7 +2108,7 @@
         fontsize = para.fontSize
         rect = [self.xStart, self.yStart, x,y+fontsize]
         if debug:
-            print "LINKING RECTANGLE", rect
+            print("LINKING RECTANGLE", rect)
             #canvas.rect(self.xStart, self.yStart, x-self.xStart,y+fontsize-self.yStart, stroke=1)
         self.link(rect, canvas)
 
@@ -2281,7 +2281,7 @@
     S = ParagraphStyle("Normal", None)
     P = Para(S, parsedpara)
     (w, h) = P.wrap(5*inch, 10*inch)
-    print "wrapped as", (h,w)
+    print("wrapped as", (h,w))
     canv.saveState()
     canv.translate(1*inch, 1*inch)
     canv.rect(0,0,5*inch,10*inch, fill=0, stroke=1)
@@ -2362,7 +2362,7 @@
         remainder = test_program + test_program + test_program
         laststate = {}
         while remainder:
-            print "NEW PAGE"
+            print("NEW PAGE")
             c.translate(inch, 8*inch)
             t = c.beginText()
             t.setTextOrigin(0,0)
@@ -2378,9 +2378,9 @@
             laststate = p.runOpCodes(formattedprogram, c, t)
             c.drawText(t)
             c.showPage()
-            print "="*30, "x=", laststate["x"], "y=", laststate["y"]
+            print("="*30, "x=", laststate["x"], "y=", laststate["y"])
     c.save()
-    print fn
+    print(fn)
 
 if __name__=="__main__":
     test()
--- a/src/reportlab/platypus/paragraph.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/platypus/paragraph.py	Tue Apr 30 14:20:22 2013 +0100
@@ -25,43 +25,43 @@
 #thanks to Dirk Holtwick for helpful discussions/insight
 #on this one
 _wsc = ''.join((
-    u'\u0009',  # HORIZONTAL TABULATION
-    u'\u000A',  # LINE FEED
-    u'\u000B',  # VERTICAL TABULATION
-    u'\u000C',  # FORM FEED
-    u'\u000D',  # CARRIAGE RETURN
-    u'\u001C',  # FILE SEPARATOR
-    u'\u001D',  # GROUP SEPARATOR
-    u'\u001E',  # RECORD SEPARATOR
-    u'\u001F',  # UNIT SEPARATOR
-    u'\u0020',  # SPACE
-    u'\u0085',  # NEXT LINE
+    '\u0009',  # HORIZONTAL TABULATION
+    '\u000A',  # LINE FEED
+    '\u000B',  # VERTICAL TABULATION
+    '\u000C',  # FORM FEED
+    '\u000D',  # CARRIAGE RETURN
+    '\u001C',  # FILE SEPARATOR
+    '\u001D',  # GROUP SEPARATOR
+    '\u001E',  # RECORD SEPARATOR
+    '\u001F',  # UNIT SEPARATOR
+    '\u0020',  # SPACE
+    '\u0085',  # NEXT LINE
     #u'\u00A0', # NO-BREAK SPACE
-    u'\u1680',  # OGHAM SPACE MARK
-    u'\u2000',  # EN QUAD
-    u'\u2001',  # EM QUAD
-    u'\u2002',  # EN SPACE
-    u'\u2003',  # EM SPACE
-    u'\u2004',  # THREE-PER-EM SPACE
-    u'\u2005',  # FOUR-PER-EM SPACE
-    u'\u2006',  # SIX-PER-EM SPACE
-    u'\u2007',  # FIGURE SPACE
-    u'\u2008',  # PUNCTUATION SPACE
-    u'\u2009',  # THIN SPACE
-    u'\u200A',  # HAIR SPACE
-    u'\u200B',  # ZERO WIDTH SPACE
-    u'\u2028',  # LINE SEPARATOR
-    u'\u2029',  # PARAGRAPH SEPARATOR
-    u'\u202F',  # NARROW NO-BREAK SPACE
-    u'\u205F',  # MEDIUM MATHEMATICAL SPACE
-    u'\u3000',  # IDEOGRAPHIC SPACE
+    '\u1680',  # OGHAM SPACE MARK
+    '\u2000',  # EN QUAD
+    '\u2001',  # EM QUAD
+    '\u2002',  # EN SPACE
+    '\u2003',  # EM SPACE
+    '\u2004',  # THREE-PER-EM SPACE
+    '\u2005',  # FOUR-PER-EM SPACE
+    '\u2006',  # SIX-PER-EM SPACE
+    '\u2007',  # FIGURE SPACE
+    '\u2008',  # PUNCTUATION SPACE
+    '\u2009',  # THIN SPACE
+    '\u200A',  # HAIR SPACE
+    '\u200B',  # ZERO WIDTH SPACE
+    '\u2028',  # LINE SEPARATOR
+    '\u2029',  # PARAGRAPH SEPARATOR
+    '\u202F',  # NARROW NO-BREAK SPACE
+    '\u205F',  # MEDIUM MATHEMATICAL SPACE
+    '\u3000',  # IDEOGRAPHIC SPACE
     ))
 _wsc_re_split=re.compile('[%s]+'% re.escape(_wsc)).split
 
 def split(text, delim=None):
     if type(text) is str: text = text.decode('utf8')
     if type(delim) is str: delim = delim.decode('utf8')
-    if delim is None and u'\xa0' in text:
+    if delim is None and '\xa0' in text:
         return [uword.encode('utf8') for uword in _wsc_re_split(text)]
     return [uword.encode('utf8') for uword in text.split(delim)]
 
@@ -92,13 +92,13 @@
     """
 
 def _lineClean(L):
-    return join(filter(truth,split(strip(L))))
+    return join(list(filter(truth,split(strip(L)))))
 
 def cleanBlockQuotedText(text,joiner=' '):
     """This is an internal utility which takes triple-
     quoted text form within the document and returns
     (hopefully) the paragraph the user intended originally."""
-    L=filter(truth,map(_lineClean, split(text, '\n')))
+    L=list(filter(truth,list(map(_lineClean, split(text, '\n')))))
     return join(L, joiner)
 
 def setXPos(tx,dx):
@@ -129,7 +129,7 @@
     if isinstance(w,str):
         return w.count('\xc2\xa0')
     else:
-        return w.count(u'\xa0')
+        return w.count('\xa0')
 
 def _justifyDrawParaLine( tx, offset, extraspace, words, last=0):
     setXPos(tx,offset)
@@ -515,7 +515,7 @@
     tx2 = canvas.beginText(style.bulletIndent, cur_y+getattr(style,"bulletOffsetY",0))
     tx2.setFont(style.bulletFontName, style.bulletFontSize)
     tx2.setFillColor(hasattr(style,'bulletColor') and style.bulletColor or style.textColor)
-    if isinstance(bulletText,basestring):
+    if isinstance(bulletText,str):
         tx2.textOut(bulletText)
     else:
         for f in bulletText:
@@ -534,7 +534,7 @@
     '''work out bullet width and adjust maxWidths[0] if neccessary
     '''
     if bulletText:
-        if isinstance(bulletText,basestring):
+        if isinstance(bulletText,str):
             bulletWidth = stringWidth( bulletText, style.bulletFontName, style.bulletFontSize)
         else:
             #it's a list of fragments
@@ -612,7 +612,7 @@
 
 _scheme_re = re.compile('^[a-zA-Z][-+a-zA-Z0-9]+$')
 def _doLink(tx,link,rect):
-    if isinstance(link,unicode):
+    if isinstance(link,str):
         link = link.encode('utf8')
     parts = link.split(':',1)
     scheme = len(parts)==2 and parts[0].lower() or ''
@@ -691,11 +691,11 @@
     if tt:
         tt=tt.lower()
         if tt=='lowercase':
-            tt = unicode.lower
+            tt = str.lower
         elif tt=='uppercase':
-            tt = unicode.upper
+            tt = str.upper
         elif  tt=='capitalize':
-            tt = unicode.title
+            tt = str.title
         elif tt=='none':
             return
         else:
@@ -704,19 +704,19 @@
         if n==1:
             #single fragment the easy case
             frags[0].text = tt(frags[0].text.decode('utf8')).encode('utf8')
-        elif tt is unicode.title:
+        elif tt is str.title:
             pb = True
             for f in frags:
                 t = f.text
                 if not t: continue
                 u = t.decode('utf8')
-                if u.startswith(u' ') or pb:
+                if u.startswith(' ') or pb:
                     u = tt(u)
                 else:
-                    i = u.find(u' ')
+                    i = u.find(' ')
                     if i>=0:
                         u = u[:i]+tt(u[i:])
-                pb = u.endswith(u' ')
+                pb = u.endswith(' ')
                 f.text = u.encode('utf8')
         else:
             for f in frags:
@@ -724,10 +724,10 @@
                 if not t: continue
                 f.text = tt(t.decode('utf8')).encode('utf8')
 
-class cjkU(unicode):
+class cjkU(str):
     '''simple class to hold the frag corresponding to a str'''
     def __new__(cls,value,frag,encoding):
-        self = unicode.__new__(cls,value)
+        self = str.__new__(cls,value)
         self._frag = frag
         if hasattr(frag,'cbDefn'):
             w = getattr(frag.cbDefn,'width',0)
@@ -759,14 +759,14 @@
         minDescent = min(minDescent,descent)
         if not _sameFrag(f0,f):
             f0=f0.clone()
-            f0.text = u''.join(CW)
+            f0.text = ''.join(CW)
             words.append(f0)
             CW = []
             f0 = f
         CW.append(u)
     if CW:
         f0=f0.clone()
-        f0.text = u''.join(CW)
+        f0.text = ''.join(CW)
         words.append(f0)
     return FragLine(kind=1,extraSpace=extraSpace,wordCount=1,words=words[1:],fontSize=maxSize,ascent=maxAscent,descent=minDescent,maxWidth=maxWidth,currentWidth=widthUsed,lineBreak=lineBreak)
 
@@ -776,7 +776,7 @@
     U = []  #get a list of single glyphs with their widths etc etc
     for f in frags:
         text = f.text
-        if not isinstance(text,unicode):
+        if not isinstance(text,str):
             text = text.decode(encoding)
         if text:
             U.extend([cjkU(t,f,encoding) for t in text])
@@ -813,13 +813,13 @@
                     #  - reversion to Kanji (which would be a good split point)
                     #  - in the worst case, roughly half way back along the line
                     limitCheck = (lineStartPos+i)>>1        #(arbitrary taste issue)
-                    for j in xrange(i-1,limitCheck,-1):
+                    for j in range(i-1,limitCheck,-1):
                         uj = U[j]
                         if uj and category(uj)=='Zs' or ord(uj)>=0x3000:
                             k = j+1
                             if k<i:
                                 j = k+1
-                                extraSpace += sum(U[ii].width for ii in xrange(j,i))
+                                extraSpace += sum(U[ii].width for ii in range(j,i))
                                 w = U[k].width
                                 u = U[k]
                                 i = j
@@ -919,7 +919,7 @@
     def __repr__(self):
         n = self.__class__.__name__
         L = [n+"("]
-        keys = self.__dict__.keys()
+        keys = list(self.__dict__.keys())
         for k in keys:
             L.append('%s: %s' % (repr(k).replace("\n", " ").replace("  "," "),repr(getattr(self, k)).replace("\n", " ").replace("  "," ")))
         L.append(") #"+n)
@@ -1001,7 +1001,7 @@
         else:
             words = _getFragWords(frags)
             func  = lambda x: x[0]
-        return max(map(func,words))
+        return max(list(map(func,words)))
 
     def _get_split_blParaFunc(self):
         return self.blPara.kind==0 and _split_blParaSimple or _split_blParaHard
@@ -1514,7 +1514,7 @@
                     if noJustifyLast and nLines==1 and style.endDots and dpl!=_rightDrawParaLine: _do_dots(0, dx, ws, xs, tx, dpl)
 
                     #now the middle of the paragraph, aligned with the left margin which is our origin.
-                    for i in xrange(1, nLines):
+                    for i in range(1, nLines):
                         ws = lines[i][0]
                         t_off = dpl( tx, _offsets[i], ws, lines[i][1], noJustifyLast and i==lim)
                         dx = t_off+leftIndent
@@ -1524,7 +1524,7 @@
                         if link: _do_link_line(i, dx, ws, tx)
                         if noJustifyLast and i==lim and style.endDots and dpl!=_rightDrawParaLine: _do_dots(i, dx, ws, xs, tx, dpl)
                 else:
-                    for i in xrange(1, nLines):
+                    for i in range(1, nLines):
                         dpl( tx, _offsets[i], lines[i][0], lines[i][1], noJustifyLast and i==lim)
             else:
                 f = lines[0]
@@ -1577,7 +1577,7 @@
                 _do_post_text(tx)
 
                 #now the middle of the paragraph, aligned with the left margin which is our origin.
-                for i in xrange(1, nLines):
+                for i in range(1, nLines):
                     f = lines[i]
                     dpl( tx, _offsets[i], f, noJustifyLast and i==lim)
                     _do_post_text(tx)
@@ -1612,11 +1612,11 @@
             func = lambda frag, w=self.width: w - frag.extraSpace
         else:
             func = lambda frag, w=self.width: w - frag[0]
-        return map(func,self.blPara.lines)
+        return list(map(func,self.blPara.lines))
 
 if __name__=='__main__':    #NORUNTESTS
     def dumpParagraphLines(P):
-        print 'dumpParagraphLines(<Paragraph @ %d>)' % id(P)
+        print('dumpParagraphLines(<Paragraph @ %d>)' % id(P))
         lines = P.blPara.lines
         for l,line in enumerate(lines):
             line = lines[l]
@@ -1625,10 +1625,10 @@
             else:
                 words = line[1]
             nwords = len(words)
-            print 'line%d: %d(%s)\n  ' % (l,nwords,str(getattr(line,'wordCount','Unknown'))),
-            for w in xrange(nwords):
-                print "%d:'%s'"%(w,getattr(words[w],'text',words[w])),
-            print
+            print('line%d: %d(%s)\n  ' % (l,nwords,str(getattr(line,'wordCount','Unknown'))), end=' ')
+            for w in range(nwords):
+                print("%d:'%s'"%(w,getattr(words[w],'text',words[w])), end=' ')
+            print()
 
     def fragDump(w):
         R= ["'%s'" % w[1]]
@@ -1638,20 +1638,20 @@
         return ', '.join(R)
 
     def dumpParagraphFrags(P):
-        print 'dumpParagraphFrags(<Paragraph @ %d>) minWidth() = %.2f' % (id(P), P.minWidth())
+        print('dumpParagraphFrags(<Paragraph @ %d>) minWidth() = %.2f' % (id(P), P.minWidth()))
         frags = P.frags
         n =len(frags)
-        for l in xrange(n):
-            print "frag%d: '%s' %s" % (l, frags[l].text,' '.join(['%s=%s' % (k,getattr(frags[l],k)) for k in frags[l].__dict__ if k!=text]))
+        for l in range(n):
+            print("frag%d: '%s' %s" % (l, frags[l].text,' '.join(['%s=%s' % (k,getattr(frags[l],k)) for k in frags[l].__dict__ if k!=text])))
 
         l = 0
         cum = 0
         for W in _getFragWords(frags,360):
             cum += W[0]
-            print "fragword%d: cum=%3d size=%d" % (l, cum, W[0]),
+            print("fragword%d: cum=%3d size=%d" % (l, cum, W[0]), end=' ')
             for w in W[1:]:
-                print '(%s)' % fragDump(w),
-            print
+                print('(%s)' % fragDump(w), end=' ')
+            print()
             l += 1
 
 
@@ -1722,12 +1722,12 @@
         P=Paragraph(text, B)
         dumpParagraphFrags(P)
         w,h = P.wrap(aW,aH)
-        print 'After initial wrap',w,h
+        print('After initial wrap',w,h)
         dumpParagraphLines(P)
         S = P.split(aW,aH)
         dumpParagraphFrags(S[0])
         w0,h0 = S[0].wrap(aW,aH)
-        print 'After split wrap',w0,h0
+        print('After split wrap',w0,h0)
         dumpParagraphLines(S[0])
 
     if flagged(5):
@@ -1761,7 +1761,7 @@
         w,h = P.wrap(6*72, 9.7*72)
         dumpParagraphLines(P)
         S = P.split(6*72,h/2.0)
-        print len(S)
+        print(len(S))
         dumpParagraphLines(S[0])
         dumpParagraphLines(S[1])
 
--- a/src/reportlab/platypus/paraparser.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/platypus/paraparser.py	Tue Apr 30 14:20:22 2013 +0100
@@ -11,7 +11,7 @@
 import copy
 import base64
 try:
-    import cPickle as pickle
+    import pickle as pickle
 except:
     import pickle
 import unicodedata
@@ -203,7 +203,7 @@
                 }
 
 def _addAttributeNames(m):
-    K = m.keys()
+    K = list(m.keys())
     for k in K:
         n = m[k][0]
         if n not in m: m[n] = m[k]
@@ -218,7 +218,7 @@
 _addAttributeNames(_linkAttrMap)
 
 def _applyAttributes(obj, attr):
-    for k, v in attr.items():
+    for k, v in list(attr.items()):
         if type(v) is TupleType and v[0]=='relative':
             #AR 20/5/2000 - remove 1.5.2-ism
             #v = v[1]+getattr(obj,k,0)
@@ -501,16 +501,16 @@
     if not _greek2Utf8:
         from reportlab.pdfbase.rl_codecs import RL_Codecs
         import codecs
-        dm = decoding_map = codecs.make_identity_dict(xrange(32,256))
-        for k in xrange(0,32):
+        dm = decoding_map = codecs.make_identity_dict(range(32,256))
+        for k in range(0,32):
             dm[k] = None
         dm.update(RL_Codecs._RL_Codecs__rl_codecs_data['symbol'][0])
         _greek2Utf8 = {}
-        for k,v in dm.iteritems():
+        for k,v in dm.items():
             if not v:
                 u = '\0'
             else:
-                u = unichr(v).encode('utf8')
+                u = chr(v).encode('utf8')
             _greek2Utf8[chr(k)] = u
     return ''.join(map(_greek2Utf8.__getitem__,data))
 
@@ -577,7 +577,7 @@
         if attrName!=attrName.lower() and attrName!="caseSensitive" and not self.caseSensitive and \
             (attrName.startswith("start_") or attrName.startswith("end_")):
                 return getattr(self,attrName.lower())
-        raise AttributeError, attrName
+        raise AttributeError(attrName)
 
     #### bold
     def start_b( self, attributes ):
@@ -713,7 +713,7 @@
         except ValueError:
             self.unknown_charref(name)
             return
-        self.handle_data(unichr(n).encode('utf8'))
+        self.handle_data(chr(n).encode('utf8'))
 
     def handle_entityref(self,name):
         if name in greeks:
@@ -745,14 +745,14 @@
                 v = '\0'
         elif 'code' in attr:
             try:
-                v = unichr(int(eval(attr['code']))).encode('utf8')
+                v = chr(int(eval(attr['code']))).encode('utf8')
             except:
                 self._syntax_error('<unichar/> invalid code attribute %s' % attr['code'])
                 v = '\0'
         else:
             v = None
             if attr:
-                self._syntax_error('<unichar/> invalid attribute %s' % attr.keys()[0])
+                self._syntax_error('<unichar/> invalid attribute %s' % list(attr.keys())[0])
 
         if v is not None:
             self.handle_data(v)
@@ -972,16 +972,16 @@
     def _pop(self,**kw):
         frag = self._stack[-1]
         del self._stack[-1]
-        for k, v in kw.items():
+        for k, v in list(kw.items()):
             assert getattr(frag,k)==v
         return frag
 
     def getAttributes(self,attr,attrMap):
         A = {}
-        for k, v in attr.items():
+        for k, v in list(attr.items()):
             if not self.caseSensitive:
                 k = string.lower(k)
-            if k in attrMap.keys():
+            if k in list(attrMap.keys()):
                 j = attrMap[k]
                 func = j[1]
                 try:
@@ -1099,10 +1099,10 @@
             #reconvert to unicode
             if fragList:
                 for frag in fragList:
-                    frag.text = unicode(frag.text, self._enc)
+                    frag.text = str(frag.text, self._enc)
             if bFragList:
                 for frag in bFragList:
-                    frag.text = unicode(frag.text, self._enc)
+                    frag.text = str(frag.text, self._enc)
 
         return style, fragList, bFragList
 
@@ -1136,19 +1136,19 @@
     from reportlab.lib.styles import _baseFontName
     _parser=ParaParser()
     def check_text(text,p=_parser):
-        print '##########'
+        print('##########')
         text = cleanBlockQuotedText(text)
         l,rv,bv = p.parse(text,style)
         if rv is None:
             for l in _parser.errors:
-                print l
+                print(l)
         else:
-            print 'ParaStyle', l.fontName,l.fontSize,l.textColor
+            print('ParaStyle', l.fontName,l.fontSize,l.textColor)
             for l in rv:
-                print l.fontName,l.fontSize,l.textColor,l.bold, l.rise, '|%s|'%l.text[:25],
+                print(l.fontName,l.fontSize,l.textColor,l.bold, l.rise, '|%s|'%l.text[:25], end=' ')
                 if hasattr(l,'cbDefn'):
-                    print 'cbDefn',getattr(l.cbDefn,'name',''),getattr(l.cbDefn,'label',''),l.cbDefn.kind
-                else: print
+                    print('cbDefn',getattr(l.cbDefn,'name',''),getattr(l.cbDefn,'label',''),l.cbDefn.kind)
+                else: print()
 
     style=ParaFrag()
     style.fontName=_baseFontName
--- a/src/reportlab/platypus/tableofcontents.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/platypus/tableofcontents.py	Tue Apr 30 14:20:22 2013 +0100
@@ -56,7 +56,7 @@
 from reportlab.pdfgen import canvas
 from base64 import encodestring, decodestring
 try:
-    import cPickle as pickle
+    import pickle as pickle
 except ImportError:
     import pickle
 dumps = pickle.dumps
@@ -99,7 +99,7 @@
         pagestrw = stringWidth(pagestr, style.fontName, fontSize)
         
     
-    if isinstance(dot, basestring):
+    if isinstance(dot, str):
         if dot:
             dotw = stringWidth(dot, style.fontName, fontSize)
             dotsn = int((availWidth-x-pagestrw)/dotw)
@@ -311,7 +311,7 @@
 
     def getFormatFunc(self,format):
         try:
-            exec 'from reportlab.lib.sequencer import _format_%s as formatFunc' % format in locals()
+            exec('from reportlab.lib.sequencer import _format_%s as formatFunc' % format, locals())
         except ImportError:
             raise ValueError('Unknown format %r' % format)
         return formatFunc
@@ -421,9 +421,9 @@
         '''Return the last run's entries!  If there are none, returns dummy.'''
         if not self._lastEntries:
             if self._entries:
-                return self._entries.items()
+                return list(self._entries.items())
             return dummy
-        return self._lastEntries.items()
+        return list(self._lastEntries.items())
 
     def _build(self,availWidth,availHeight):
         _tempEntries = self._getlastEntries()
--- a/src/reportlab/platypus/tables.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/platypus/tables.py	Tue Apr 30 14:20:22 2013 +0100
@@ -99,7 +99,7 @@
     s = avail
     w = n = 0.
     for v in V:
-        if isinstance(v,basestring):
+        if isinstance(v,str):
             v = v.strip()
             if not v:
                 v = None
@@ -156,7 +156,7 @@
 def _multiLine(scp,ecp,y,canvLine,ws,count):
     offset = 0.5*(count-1)*ws
     y += offset
-    for idx in xrange(count):
+    for idx in range(count):
         canvLine(scp, y, ecp, y)
         y -= ws
 
@@ -182,18 +182,18 @@
     #assign required space to variable rows equally to existing calculated values
     M = {}
     if not lim: lim = len(V0)   #in longtables the row calcs may be truncated
-    for (x0,x1),v in spanCons.iteritems():
+    for (x0,x1),v in spanCons.items():
         if x0>=lim: continue
         x1 += 1
-        t = sum([V[x]+M.get(x,0) for x in xrange(x0,x1)])
+        t = sum([V[x]+M.get(x,0) for x in range(x0,x1)])
         if t>=v-FUZZ: continue      #already good enough
-        X = [x for x in xrange(x0,x1) if V0[x] is None] #variable candidates
+        X = [x for x in range(x0,x1) if V0[x] is None] #variable candidates
         if not X: continue          #something wrong here mate
         v -= t
         v /= float(len(X))
         for x in X:
             M[x] = M.get(x,0)+v
-    for x,v in M.iteritems():
+    for x,v in M.items():
         V[x] += v
 
 class _ExpandedCellTuple(tuple):
@@ -212,7 +212,7 @@
         self._cellvalues = []
         _seqCW = isinstance(colWidths,(tuple,list))
         _seqRH = isinstance(rowHeights,(tuple,list))
-        if nrows: self._ncols = ncols = max(map(_rowLen,data))
+        if nrows: self._ncols = ncols = max(list(map(_rowLen,data)))
         elif colWidths and _seqCW: ncols = len(colWidths)
         else: ncols = 0
         if not emptyTableAction: emptyTableAction = rl_config.emptyTableAction
@@ -223,7 +223,7 @@
             elif emptyTableAction=='indicate':
                 self.__class__ = Preformatted
                 global _emptyTableStyle
-                if '_emptyTableStyle' not in globals().keys():
+                if '_emptyTableStyle' not in list(globals().keys()):
                     _emptyTableStyle = ParagraphStyle('_emptyTableStyle')
                     _emptyTableStyle.textColor = colors.red
                     _emptyTableStyle.backColor = colors.yellow
@@ -264,9 +264,9 @@
         self._colWidths = self._argW = colWidths
         if cellStyles is None:
             cellrows = []
-            for i in xrange(nrows):
+            for i in range(nrows):
                 cellcols = []
-                for j in xrange(ncols):
+                for j in range(ncols):
                     cellcols.append(CellStyle(repr((i,j))))
                 cellrows.append(cellcols)
             self._cellStyles = cellrows
@@ -304,7 +304,7 @@
         def normCell(stuff):
             if stuff is None:
                 return ''
-            elif isinstance(stuff,unicode):
+            elif isinstance(stuff,str):
                 return stuff.encode('utf8')
             else:
                 return stuff
@@ -326,8 +326,8 @@
         rh = getattr(self, '_rowHeights', None)
         if cv and 'unknown' not in (nr,nc):
             b = 0
-            for i in xrange(nr):
-                for j in xrange(nc):
+            for i in range(nr):
+                for j in range(nc):
                     v = cv[i][j]
                     if isinstance(v,(list,tuple,Flowable)):
                         if not isinstance(v,(tuple,list)): v = (v,)
@@ -341,7 +341,7 @@
                     else:
                         v = v is None and '' or str(v)
                         ix, jx, vx = i, j, v
-                        b = (vx and isinstance(v,basestring)) and 1 or 0
+                        b = (vx and isinstance(v,str)) and 1 or 0
                         if maxLen: vx = vx[:maxLen]
                     if b: break
                 if b: break
@@ -536,7 +536,7 @@
                 S = self._cellStyles[i] # styles for row i
                 h = 0
                 j = 0
-                for j,(v, s, w) in enumerate(zip(V, S, W)): # value, style, width (lengths must match)
+                for j,(v, s, w) in enumerate(list(zip(V, S, W))): # value, style, width (lengths must match)
                     ji = j,i
                     span = spanRanges.get(ji,None)
                     if ji in rowSpanCells and not span:
@@ -578,7 +578,7 @@
                     if height > availHeight:
                         #we can terminate if all spans are complete in H[:i]
                         if spanCons:
-                            msr = max([x[1] for x in spanCons.keys()])  #RS=[endrowspan,.....]
+                            msr = max([x[1] for x in list(spanCons.keys())])  #RS=[endrowspan,.....]
                             if hmax>=msr:
                                 break
             if None not in H: hmax = lim
@@ -653,8 +653,8 @@
         Allow a couple which we know are fixed size such as
         images and graphics."""
         if upToRow is None: upToRow = self._nrows
-        for row in xrange(min(self._nrows, upToRow)):
-            for col in xrange(self._ncols):
+        for row in range(min(self._nrows, upToRow)):
+            for col in range(self._ncols):
                 value = self._cellvalues[row][col]
                 if not self._canGetWidth(value):
                     return 1
@@ -700,8 +700,8 @@
             else:
                 assert isinstance(w,(int,float))
                 totalDefined = totalDefined + w
-        if verbose: print 'prelim width calculation.  %d columns, %d undefined width, %0.2f units remain' % (
-            self._ncols, numberUndefined, availWidth - totalDefined)
+        if verbose: print('prelim width calculation.  %d columns, %d undefined width, %0.2f units remain' % (
+            self._ncols, numberUndefined, availWidth - totalDefined))
 
         #check columnwise in each None column to see if they are sizable.
         given = []
@@ -710,12 +710,12 @@
         minimums = {}
         totalMinimum = 0
         elementWidth = self._elementWidth
-        for colNo in xrange(self._ncols):
+        for colNo in range(self._ncols):
             w = W[colNo]
             if w is None or w=='*' or _endswith(w,'%'):
                 siz = 1
                 final = 0
-                for rowNo in xrange(self._nrows):
+                for rowNo in range(self._nrows):
                     value = self._cellvalues[rowNo][colNo]
                     style = self._cellStyles[rowNo][colNo]
                     pad = style.leftPadding+style.rightPadding
@@ -737,9 +737,9 @@
                 given.append(colNo)
         if len(given) == self._ncols:
             return
-        if verbose: print 'predefined width:   ',given
-        if verbose: print 'uncomputable width: ',unsizeable
-        if verbose: print 'computable width:   ',sizeable
+        if verbose: print('predefined width:   ',given)
+        if verbose: print('uncomputable width: ',unsizeable)
+        if verbose: print('computable width:   ',sizeable)
 
         # how much width is left:
         remaining = availWidth - (totalMinimum + totalDefined)
@@ -761,7 +761,7 @@
             desiredWidths = []
             totalDesired = 0
             effectiveRemaining = remaining
-            for colNo, minimum in minimums.items():
+            for colNo, minimum in list(minimums.items()):
                 w = W[colNo]
                 if _endswith(w,'%'):
                     desired = (float(w[:-1])/percentTotal)*availWidth
@@ -821,9 +821,9 @@
                     assert adjusted >= minimum
                     W[colNo] = adjusted
         else:
-            for colNo, minimum in minimums.items():
+            for colNo, minimum in list(minimums.items()):
                 W[colNo] = minimum
-        if verbose: print 'new widths are:', W
+        if verbose: print('new widths are:', W)
         self._argW = self._colWidths = W
         return W
 
@@ -831,10 +831,10 @@
         W = list(self._argW)
         width = 0
         elementWidth = self._elementWidth
-        rowNos = xrange(self._nrows)
+        rowNos = range(self._nrows)
         values = self._cellvalues
         styles = self._cellStyles
-        for colNo in xrange(len(W)):
+        for colNo in range(len(W)):
             w = W[colNo]
             if w is None or w=='*' or _endswith(w,'%'):
                 final = 0
@@ -861,8 +861,8 @@
         Any cell not in the key is not part of a spanned region
         """
         self._spanRanges = spanRanges = {}
-        for x in xrange(self._ncols):
-            for y in xrange(self._nrows):
+        for x in range(self._ncols):
+            for y in range(self._nrows):
                 spanRanges[x,y] = (x, y, x, y)
         self._colSpanCells = []
         self._rowSpanCells = []
@@ -882,16 +882,16 @@
 
             if x0!=x1 or y0!=y1:
                 if x0!=x1: #column span
-                    for y in xrange(y0, y1+1):
-                        for x in xrange(x0,x1+1):
+                    for y in range(y0, y1+1):
+                        for x in range(x0,x1+1):
                             csa((x,y))
                 if y0!=y1: #row span
-                    for y in xrange(y0, y1+1):
-                        for x in xrange(x0,x1+1):
+                    for y in range(y0, y1+1):
+                        for x in range(x0,x1+1):
                             rsa((x,y))
 
-                for y in xrange(y0, y1+1):
-                    for x in xrange(x0,x1+1):
+                for y in range(y0, y1+1):
+                    for x in range(x0,x1+1):
                         spanRanges[x,y] = None
                 # set the main entry
                 spanRanges[x0,y0] = (x0, y0, x1, y1)
@@ -907,8 +907,8 @@
         Any cell not in the key is not part of a spanned region
         """
         self._nosplitRanges = nosplitRanges = {}
-        for x in xrange(self._ncols):
-            for y in xrange(self._nrows):
+        for x in range(self._ncols):
+            for y in range(self._nrows):
                 nosplitRanges[x,y] = (x, y, x, y)
         self._colNoSplitCells = []
         self._rowNoSplitCells = []
@@ -929,17 +929,17 @@
             if x0!=x1 or y0!=y1:
                 #column span
                 if x0!=x1:
-                    for y in xrange(y0, y1+1):
-                        for x in xrange(x0,x1+1):
+                    for y in range(y0, y1+1):
+                        for x in range(x0,x1+1):
                             csa((x,y))
                 #row span
                 if y0!=y1:
-                    for y in xrange(y0, y1+1):
-                        for x in xrange(x0,x1+1):
+                    for y in range(y0, y1+1):
+                        for x in range(x0,x1+1):
                             rsa((x,y))
 
-                for y in xrange(y0, y1+1):
-                    for x in xrange(x0,x1+1):
+                for y in range(y0, y1+1):
+                    for x in range(x0,x1+1):
                         nosplitRanges[x,y] = None
                 # set the main entry
                 nosplitRanges[x0,y0] = (x0, y0, x1, y1)
@@ -966,7 +966,7 @@
         vBlocks = {}
         hBlocks = {}
         rlim = len(rowpositions)-1
-        for (coord, value) in self._spanRanges.iteritems():
+        for (coord, value) in self._spanRanges.items():
             if value is None:
                 spanRects[coord] = None
             else:
@@ -974,10 +974,10 @@
                 if row1>=rlim: continue
                 col,row = coord
                 if col1-col0>0:
-                    for _ in xrange(col0+1,col1+1):
+                    for _ in range(col0+1,col1+1):
                         vBlocks.setdefault(colpositions[_],[]).append((rowpositions[row1+1],rowpositions[row0]))
                 if row1-row0>0:
-                    for _ in xrange(row0+1,row1+1):
+                    for _ in range(row0+1,row1+1):
                         hBlocks.setdefault(rowpositions[_],[]).append((colpositions[col0],colpositions[col1+1]))
                 x = colpositions[col0]
                 y = rowpositions[row1+1]
@@ -986,7 +986,7 @@
                 spanRects[coord] = (x, y, width, height)
 
         for _ in hBlocks, vBlocks:
-            for value in _.values():
+            for value in list(_.values()):
                 value.sort()
         self._spanRects = spanRects
         self._vBlocks = vBlocks
@@ -998,7 +998,7 @@
             tblstyle = TableStyle(tblstyle)
         for cmd in tblstyle.getCommands():
             self._addCommand(cmd)
-        for k,v in tblstyle._opts.items():
+        for k,v in list(tblstyle._opts.items()):
             setattr(self,k,v)
         for a in ('spaceBefore','spaceAfter'):
             if not hasattr(self,a) and hasattr(tblstyle,a):
@@ -1058,15 +1058,15 @@
             if ec < 0: ec = ec + self._ncols
             if sr < 0: sr = sr + self._nrows
             if er < 0: er = er + self._nrows
-            for i in xrange(sr, er+1):
-                for j in xrange(sc, ec+1):
+            for i in range(sr, er+1):
+                for j in range(sc, ec+1):
                     _setCellStyle(self._cellStyles, i, j, op, values)
 
     def _drawLines(self):
         ccap, cdash, cjoin = None, None, None
         self.canv.saveState()
         for op, (sc,sr), (ec,er), weight, color, cap, dash, join, count, space in self._linecmds:
-            if isinstance(sr,basestring) and sr.startswith('split'): continue
+            if isinstance(sr,str) and sr.startswith('split'): continue
             if sc < 0: sc = sc + self._ncols
             if ec < 0: ec = ec + self._ncols
             if sr < 0: sr = sr + self._nrows
@@ -1237,7 +1237,7 @@
         A = []
         # hack up the line commands
         for op, (sc,sr), (ec,er), weight, color, cap, dash, join, count, space in self._linecmds:
-            if isinstance(sr,basestring) and sr.startswith('split'):
+            if isinstance(sr,str) and sr.startswith('split'):
                 A.append((op,(sc,sr), (ec,sr), weight, color, cap, dash, join, count, space))
                 if sr=='splitlast':
                     sr = er = n-1
@@ -1368,8 +1368,8 @@
         else:
             # we have some row or col spans, need a more complex algorithm
             # to find the rect for each
-            for rowNo in xrange(self._nrows):
-                for colNo in xrange(self._ncols):
+            for rowNo in range(self._nrows):
+                for colNo in range(self._ncols):
                     cellRect = self._spanRects[colNo, rowNo]
                     if cellRect is not None:
                         (x, y, width, height) = cellRect
@@ -1404,10 +1404,10 @@
                 #might be already colours, or convertible to colors, or
                 # None, or the str 'None'.
                 #It's very common to alternate a pale shade with None.
-                colorCycle = map(colors.toColorOrNone, arg)
+                colorCycle = list(map(colors.toColorOrNone, arg))
                 count = len(colorCycle)
                 rowCount = er - sr + 1
-                for i in xrange(rowCount):
+                for i in range(rowCount):
                     color = colorCycle[i%count]
                     h = rowHeights[sr + i]
                     if color:
@@ -1416,10 +1416,10 @@
                     y0 = y0 - h
             elif cmd == 'COLBACKGROUNDS':
                 #cycle through colours columnwise
-                colorCycle = map(colors.toColorOrNone, arg)
+                colorCycle = list(map(colors.toColorOrNone, arg))
                 count = len(colorCycle)
                 colCount = ec - sc + 1
-                for i in xrange(colCount):
+                for i in range(colCount):
                     color = colorCycle[i%count]
                     w = colWidths[sc + i]
                     if color:
@@ -1530,7 +1530,7 @@
     '''Henning von Bargen's changes will be active'''
     _longTableOptimize = 1
 
-LINECOMMANDS = _LineOpMap.keys()
+LINECOMMANDS = list(_LineOpMap.keys())
 
 def _isLineCommand(cmd):
     return cmd[0] in LINECOMMANDS
--- a/src/reportlab/platypus/xpreformatted.py	Fri Feb 15 15:54:16 2013 +0000
+++ b/src/reportlab/platypus/xpreformatted.py	Tue Apr 30 14:20:22 2013 +0100
@@ -6,9 +6,9 @@
 import string
 from types import StringType, ListType
 from reportlab.lib import PyFontify
-from paragraph import Paragraph, cleanBlockQuotedText, _handleBulletWidth, \
+from .paragraph import Paragraph, cleanBlockQuotedText, _handleBulletWidth, \
      ParaLines, _getFragWords, stringWidth, _sameFrag, getAscentDescent, imgVRange, imgNormV
-from flowables import _dedenter
+from .flowables import _dedenter
 
 def _getFragLines(frags):
     lines = []
@@ -249,34 +249,34 @@
 
 if __name__=='__main__':    #NORUNTESTS
     def dumpXPreformattedLines(P):
-        print '\n############dumpXPreforemattedLines(%s)' % str(P)
+        print('\n############dumpXPreforemattedLines(%s)' % str(P))
         lines = P.blPara.lines
         n =len(lines)
         for l in range(n):
             line = lines[l]
             words = line.words
             nwords = len(words)
-            print 'line%d: %d(%d)\n  ' % (l,nwords,line.wordCount),
+            print('line%d: %d(%d)\n  ' % (l,nwords,line.wordCount), end=' ')
             for w in range(nwords):
-                print "%d:'%s'"%(w,words[w].text),
-            print
+                print("%d:'%s'"%(w,words[w].text), end=' ')
+            print()
 
     def dumpXPreformattedFrags(P):
-        print '\n############dumpXPreforemattedFrags(%s)' % str(P)
+        print('\n############dumpXPreforemattedFrags(%s)' % str(P))
         frags = P.frags
         n =len(frags)
         for l in range(n):
-            print "frag%d: '%s'" % (l, frags[l].text)
+            print("frag%d: '%s'" % (l, frags[l].text))
 
         l = 0
         for L in _getFragLines(frags):
             n=0
             for W in _getFragWords(L,360):
-                print "frag%d.%d: size=%d" % (l, n, W[0]),
+                print("frag%d.%d: size=%d" % (l, n, W[0]), end=' ')
                 n = n + 1
                 for w in W[1:]:
-                    print "'%s'" % w[1],
-                print
+                    print(&qu