# HG changeset patch # User rptlab # Date 1367328494 -3600 # Node ID 99aa837b6703418ca2dab31b6d0926947956a143 # Parent 29c11b905751064d95c0f65e8faf0cf2688394e2 second stage of port to Python 3.3; working hello world diff -r 29c11b905751 -r 99aa837b6703 docs/userguide/ch5_paragraphs.py --- a/docs/userguide/ch5_paragraphs.py Sun Feb 17 12:13:56 2013 +0000 +++ b/docs/userguide/ch5_paragraphs.py Tue Apr 30 14:28:14 2013 +0100 @@ -188,7 +188,7 @@ def getAttrs(A): _addAttributeNames(A) S={} - for k, v in list(A.items()): + for k, v in A.items(): a = v[0] if a not in S: S[a] = k diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/barcode/code128.py --- a/src/reportlab/graphics/barcode/code128.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/barcode/code128.py Tue Apr 30 14:28:14 2013 +0100 @@ -223,7 +223,7 @@ if type(value) is type(1): value = str(value) - for (k, v) in list(args.items()): + for k, v in args.items(): setattr(self, k, v) if self.quiet: diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/barcode/code93.py --- a/src/reportlab/graphics/barcode/code93.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/barcode/code93.py Tue Apr 30 14:28:14 2013 +0100 @@ -55,7 +55,7 @@ } _charsbyval = {} -for k, v in list(_patterns.items()): +for k, v in _patterns.items(): _charsbyval[v[1]] = k _extended = { diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/barcode/common.py --- a/src/reportlab/graphics/barcode/common.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/barcode/common.py Tue Apr 30 14:28:14 2013 +0100 @@ -308,7 +308,7 @@ if type(value) == type(1): value = str(value) - for (k, v) in list(args.items()): + for k, v in args.items(): setattr(self, k, v) if self.quiet: @@ -433,7 +433,7 @@ if type(value) == type(1): value = str(value) - for (k, v) in list(args.items()): + for k, v in 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 list(args.items()): + for k, v in 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 list(args.items()): + for k, v in args.items(): setattr(self, k, v) if self.quiet: diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/barcode/usps.py --- a/src/reportlab/graphics/barcode/usps.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/barcode/usps.py Tue Apr 30 14:28:14 2013 +0100 @@ -97,7 +97,7 @@ lquiet = inch * (15.0/32.0) quiet = 0 def __init__(self, value='', **args): - for (k, v) in list(args.items()): + for k, v in args.items(): setattr(self, k, v) Barcode.__init__(self, value) @@ -109,7 +109,7 @@ if c in string.whitespace: continue elif c in "abcdABCD": - self.validated = self.validated + string.upper(c) + self.validated = self.validated + c.upper() else: self.valid = 0 @@ -162,7 +162,7 @@ spaceWidth = inch * 0.0275 def __init__(self, value='', **args): - for (k, v) in list(args.items()): + for k, v in args.items(): setattr(self, k, v) Barcode.__init__(self, value) @@ -193,7 +193,7 @@ for c in self.validated: if c in string.digits: self.encoded = self.encoded + c - check = check + string.atoi(c) + check = check + int(c) elif c == '-': pass else: diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/charts/textlabels.py --- a/src/reportlab/graphics/charts/textlabels.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/charts/textlabels.py Tue Apr 30 14:28:14 2013 +0100 @@ -344,7 +344,7 @@ def __init__(self): self.textAnchor = 'start' self.boxAnchor = 'w' - for a in list(self._attrMap.keys()): + for a in 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 list(self.__dict__.items()): + for a,v in self.__dict__.items(): if v is None: v = getattr(l,a,None) setattr(L,a,v) self.decorate(l,L) diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/renderPDF.py --- a/src/reportlab/graphics/renderPDF.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/renderPDF.py Tue Apr 30 14:28:14 2013 +0100 @@ -18,7 +18,7 @@ from reportlab.graphics.shapes import * from reportlab.pdfgen.canvas import Canvas from reportlab.pdfbase.pdfmetrics import stringWidth -from reportlab.lib.utils import getStringIO +from reportlab.lib.utils import getBytesIO from reportlab import rl_config from .renderbase import Renderer, StateTracker, getStateDelta, renderScaledDrawing @@ -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 list(delta.items()): + for key, value in delta.items(): if key == 'transform': self._canvas.transform(value[0], value[1], value[2], value[3], value[4], value[5]) @@ -303,7 +303,7 @@ def drawToString(d, msg="", showBoundary=rl_config._unset_,autoSize=1): "Returns a PDF as a string in memory, without touching the disk" - s = getStringIO() + s = getBytesIO() drawToFile(d, s, msg=msg, showBoundary=showBoundary,autoSize=autoSize) return s.getvalue() diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/renderPM.py --- a/src/reportlab/graphics/renderPM.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/renderPM.py Tue Apr 30 14:28:14 2013 +0100 @@ -16,7 +16,7 @@ from reportlab.graphics.renderbase import StateTracker, getStateDelta, renderScaledDrawing from reportlab.pdfbase.pdfmetrics import getFont, unicode2T1 from math import sin, cos, pi, ceil -from reportlab.lib.utils import getStringIO, open_and_read +from reportlab.lib.utils import getBytesIO, open_and_read from reportlab import rl_config class RenderPMError(Exception): @@ -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 list(A.keys()): + for k in A.keys(): A[k] = getattr(gs,k) del gs, self._gs gs = self.__dict__['_gs'] = _renderPM.gstate(w,h,bg=bg) - for k in list(A.keys()): + for k in A.keys(): setattr(self,k,A[k]) gs.setFont(fN,fS) @@ -355,7 +355,7 @@ markfilename(fn,ext=fmt) def saveToString(self,fmt='GIF'): - s = getStringIO() + s = getBytesIO() self.saveToFile(s,fmt=fmt) return s.getvalue() @@ -661,7 +661,7 @@ c.saveToFile(fn,fmt) def drawToString(d,fmt='GIF', dpi=72, bg=0xffffff, configPIL=None, showBoundary=rl_config._unset_): - s = getStringIO() + s = getBytesIO() drawToFile(d,s,fmt=fmt, dpi=dpi, bg=bg, configPIL=configPIL) return s.getvalue() diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/renderPS.py --- a/src/reportlab/graphics/renderPS.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/renderPS.py Tue Apr 30 14:28:14 2013 +0100 @@ -6,7 +6,7 @@ import string, types from reportlab.pdfbase.pdfmetrics import getFont, stringWidth, unicode2T1 # for font info -from reportlab.lib.utils import fp_str, getStringIO +from reportlab.lib.utils import fp_str, getBytesIO from reportlab.lib.colors import black from reportlab.graphics.renderbase import Renderer, StateTracker, getStateDelta, renderScaledDrawing from reportlab.graphics.shapes import STATE_DEFAULTS @@ -589,7 +589,7 @@ hex_encoded = self._AsciiHexEncode(rawimage) # write in blocks of 78 chars per line - outstream = getStringIO(hex_encoded) + outstream = getBytesIO(hex_encoded) dataline = outstream.read(78) while dataline != "": @@ -601,7 +601,7 @@ # end of drawImage def _AsciiHexEncode(self, input): # also based on piddlePDF "Helper function used by images" - output = getStringIO() + output = getBytesIO() for char in input: output.write('%02x' % ord(char)) return output.getvalue() @@ -659,7 +659,7 @@ hex_encoded = self._AsciiHexEncode(rawimage) # write in blocks of 78 chars per line - outstream = getStringIO(hex_encoded) + outstream = getBytesIO(hex_encoded) dataline = outstream.read(78) while dataline != "": @@ -726,7 +726,7 @@ self._canvas._color = color #restore things we might have lost (without actually doing anything). - for k, v in list(rDeltas.items()): + for k, v in rDeltas.items(): if k in self._restores: setattr(self._canvas,self._restores[k],v) @@ -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 list(delta.items()): + for key, value in delta.items(): if key == 'transform': self._canvas.transform(value[0], value[1], value[2], value[3], value[4], value[5]) @@ -879,7 +879,7 @@ def drawToString(d, showBoundary=rl_config.showBoundary): "Returns a PS as a string in memory, without touching the disk" - s = getStringIO() + s = getBytesIO() drawToFile(d, s, showBoundary=showBoundary) return s.getvalue() diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/renderSVG.py --- a/src/reportlab/graphics/renderSVG.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/renderSVG.py Tue Apr 30 14:28:14 2013 +0100 @@ -17,7 +17,7 @@ from reportlab.graphics.shapes import STATE_DEFAULTS, Path, UserNode from reportlab.graphics.shapes import * # (only for test0) from reportlab import rl_config -from reportlab.lib.utils import getStringIO, RLString +from reportlab.lib.utils import getBytesIO, RLString from xml.dom import getDOMImplementation @@ -34,7 +34,7 @@ ### top-level user function ### def drawToString(d, showBoundary=rl_config.showBoundary,**kwds): "Returns a SVG as a string in memory, without touching the disk" - s = getStringIO() + s = getBytesIO() drawToFile(d, s, showBoundary=showBoundary,**kwds) return s.getvalue() @@ -83,7 +83,7 @@ """ newNode = doc.createElement(newTag) - for newAttr, attr in list(attrDict.items()): + for newAttr, attr in attrDict.items(): sattr = str(attr) if not node: newNode.setAttribute(newAttr, sattr) @@ -709,7 +709,7 @@ self._canvas._color = color #restore things we might have lost (without actually doing anything). - for k, v in list(rDeltas.items()): + for k, v in rDeltas.items(): if k in self._restores: setattr(self._canvas,self._restores[k],v) self._canvas.style = style @@ -850,7 +850,7 @@ """This takes a set of states, and outputs the operators needed to set those properties""" - for key, value in list(delta.items()): + for key, value in delta.items(): if key == 'transform': pass #self._canvas.transform(value[0], value[1], value[2], value[3], value[4], value[5]) diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/renderbase.py --- a/src/reportlab/graphics/renderbase.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/renderbase.py Tue Apr 30 14:28:14 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 list(shape.getProperties().items()): + for prop, value in 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 list(delta.items()): + for key, value in 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 list(lastDelta.items()): + for key, curValue in lastDelta.items(): #print ' key=%s, value=%s' % (key, curValue) prevValue = newState[key] if prevValue != curValue: @@ -230,7 +230,7 @@ parent. """ - for (key, value) in list(node.__dict__.items()): + for key, value in node.__dict__.items(): if isinstance(value, DerivedValue): #just replace with default for key? #print ' fillDerivedValues(%s)' % key diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/shapes.py --- a/src/reportlab/graphics/shapes.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/shapes.py Tue Apr 30 14:28:14 2013 +0100 @@ -183,7 +183,7 @@ class _SetKeyWordArgs: def __init__(self, keywords={}): """In general properties may be supplied to the constructor.""" - for key, value in list(keywords.items()): + for key, value in keywords.items(): setattr(self, key, value) @@ -308,7 +308,7 @@ #for more complex objects like widgets you #may need to override this. props = {} - for key, value in list(self.__dict__.items()): + for key, value in self.__dict__.items(): if key[0:1] != '_': props[key] = value return props @@ -341,10 +341,10 @@ an informative exception.""" if self._attrMap is not None: - for key in list(self.__dict__.keys()): + for key in self.__dict__.keys(): if key[0] != '_': assert key in self._attrMap, "Unexpected attribute %s found in %s" % (key, self) - for (attr, metavalue) in list(self._attrMap.items()): + for attr, metavalue in 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__) @@ -474,7 +474,7 @@ from copy import copy self_contents = self.contents if not aKeys: aKeys = list(self._attrMap.keys()) - for (k, v) in list(self.__dict__.items()): + for k, v in self.__dict__.items(): if v in self_contents: pos = self_contents.index(v) setattr(obj, k, obj.contents[pos]) @@ -578,7 +578,7 @@ v = P[n] del P[n] s = s + '%s,' % _repr(v,I) - for n,v in list(P.items()): + for n,v in 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 list(kw.keys()): + for k in 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 list(I.items()): + for m, o in 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) diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/widgetbase.py --- a/src/reportlab/graphics/widgetbase.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/widgetbase.py Tue Apr 30 14:28:14 2013 +0100 @@ -27,11 +27,11 @@ """ if self._attrMap is not None: - for key in list(self.__dict__.keys()): + for key in 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 list(self._attrMap.items()): + for attr, metavalue in 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 list(self.__dict__.keys()): + for name in 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 list(childProps.items()): + for childKey, childValue in 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 list(propDict.items()): + for name, value in 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 list(childPropDicts.items()): + for childName, childPropDict in childPropDicts.items(): child = getattr(self, childName) child.setProperties(childPropDict) @@ -136,7 +136,7 @@ widgets and vice versa.""" def _setKeywords(self,**kw): - for k,v in list(kw.items()): + for k,v in kw.items(): if k not in self.__dict__: setattr(self,k,v) @@ -273,19 +273,19 @@ # differs from the parent props = {} - for (key, value) in list(self._value.getProperties(recur=recur).items()): + for key, value in self._value.getProperties(recur=recur).items(): props['%s' % key] = value - for idx in list(self._children.keys()): + for idx in self._children.keys(): childProps = self._children[idx].getProperties(recur=recur) - for (key, value) in list(childProps.items()): + for key, value in 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 list(kw.items()): + for name, value in kw.items(): for i in range(len(value)): setattr(self[i],name,value[i]) @@ -333,7 +333,7 @@ def __init__(self, **kwargs): "Initialize with attributes if any." - for k, v in list(kwargs.items()): + for k, v in kwargs.items(): setattr(self, k, v) diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/graphics/widgets/table.py --- a/src/reportlab/graphics/widgets/table.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/graphics/widgets/table.py Tue Apr 30 14:28:14 2013 +0100 @@ -62,7 +62,7 @@ self.textAnchor = 'start' - for k, v in list(kw.items()): + for k, v in kw.items(): if k in list(self.__class__._attrMap.keys()): setattr(self, k, v) print('setting %s = %s'%(k, v)) diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/lib/attrmap.py --- a/src/reportlab/lib/attrmap.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/lib/attrmap.py Tue Apr 30 14:28:14 2013 +0100 @@ -28,7 +28,6 @@ ''' -from UserDict import UserDict from reportlab.lib.validators import isAnything, _SequenceTypes, DerivedValue from reportlab import rl_config @@ -50,7 +49,7 @@ self.desc = desc self._initial = initial self._advancedUsage = advancedUsage - for k,v in list(kw.items()): + for k,v in kw.items(): setattr(self,k,v) def __getattr__(self,name): @@ -65,7 +64,7 @@ def __repr__(self): return 'AttrMapValue(%s)' % ', '.join(['%s=%r' % i for i in self.__dict__.items()]) -class AttrMap(UserDict): +class AttrMap(dict): def __init__(self,BASE=None,UNWANTED=[],**kw): data = {} if BASE: @@ -79,7 +78,7 @@ else: raise ValueError('BASE=%s has wrong kind of value' % str(B)) - UserDict.__init__(self,data) + dict.__init__(self,data) self.remove(UNWANTED) self.data.update(kw) diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/lib/colors.py --- a/src/reportlab/lib/colors.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/lib/colors.py Tue Apr 30 14:28:14 2013 +0100 @@ -706,7 +706,7 @@ if _namedColors is not None: return _namedColors from . import colors _namedColors = {} - for (name, value) in list(colors.__dict__.items()): + for name, value in colors.__dict__.items(): if isinstance(value, Color): _namedColors[name] = value @@ -720,7 +720,7 @@ ''' namedColors = getAllNamedColors() closest = (10, None, None) #big number, name, color - for (name, color) in list(namedColors.items()): + for name, color in namedColors.items(): distance = colorDistance(aColor, color) if distance < closest[0]: closest = (distance, name, color) @@ -874,7 +874,7 @@ assigned = {} while kw and progress: progress = 0 - for k, v in list(kw.items()): + for k, v in kw.items(): if isinstance(v,(tuple,list)): c = list(map(lambda x,UNDEF=UNDEF: toColor(x,UNDEF),v)) if isinstance(v,tuple): c = tuple(c) @@ -889,7 +889,7 @@ if kw: raise ValueError("Can't convert\n%s" % str(kw)) getAllNamedColors() - for k, c in list(assigned.items()): + for k, c in assigned.items(): globals()[k] = c if isinstance(c,Color): _namedColors[k] = c diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/lib/fontfinder.py --- a/src/reportlab/lib/fontfinder.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/lib/fontfinder.py Tue Apr 30 14:28:14 2013 +0100 @@ -105,7 +105,7 @@ def getTag(self): "Return an XML tag representation" attrs = [] - for (k, v) in list(self.__dict__.items()): + for k, v in self.__dict__.items(): if k not in ['timeModified']: if v: attrs.append('%s=%s' % (k, quoteattr(str(v)))) @@ -178,7 +178,7 @@ selected = [] for font in self._fonts: OK = True - for (k, v) in list(kwds.items()): + for k, v in kwds.items(): if getattr(font, k, None) != v: OK = False if OK: diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/lib/fonts.py --- a/src/reportlab/lib/fonts.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/lib/fonts.py Tue Apr 30 14:28:14 2013 +0100 @@ -63,7 +63,7 @@ } _ps2tt_map={} -for k,v in list(_tt2ps_map.items()): +for k,v in _tt2ps_map.items(): if k not in _ps2tt_map: _ps2tt_map[v.lower()] = k diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/lib/pdfencrypt.py --- a/src/reportlab/lib/pdfencrypt.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/lib/pdfencrypt.py Tue Apr 30 14:28:14 2013 +0100 @@ -4,13 +4,13 @@ """helpers for pdf encryption/decryption""" -import string, sys, os +import sys, os try: from hashlib import md5 except ImportError: from md5 import md5 -from reportlab.lib.utils import getStringIO +from reportlab.lib.utils import getBytesIO import tempfile from reportlab.pdfgen.canvas import Canvas @@ -176,7 +176,7 @@ return out def hexchar(x): - return chr(string.atoi(x, 16)) + return chr(int(x, 16)) def hexText(text): "a legitimate way to show strings in PDF" @@ -196,7 +196,7 @@ out = out + char return out -PadString = string.join(list(map(hexchar, string.split(string.strip(padding)))), "") +PadString = ''.join(map(hexchar, padding.strip().split())) def encryptionkey(password, OwnerKey, Permissions, FileId1, revision=2): # FileId1 is first string of the fileid array @@ -408,7 +408,7 @@ firstPageSize = bboxInfo['PageForms0'][2:] #now make a new PDF document - buf = getStringIO() + buf = getBytesIO() canv = Canvas(buf, pagesize=firstPageSize) # set a standard ID while debugging diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/lib/rparsexml.py --- a/src/reportlab/lib/rparsexml.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/lib/rparsexml.py Tue Apr 30 14:28:14 2013 +0100 @@ -382,7 +382,7 @@ if not attdict: attdict={} join = string.join attlist = [] - for k in list(attdict.keys()): + for k in attdict.keys(): v = attdict[k] attlist.append("%s=%s" % (k, repr(v))) attributes = join(attlist, " ") diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/lib/styles.py --- a/src/reportlab/lib/styles.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/lib/styles.py Tue Apr 30 14:28:14 2013 +0100 @@ -62,7 +62,7 @@ def _setKwds(self,**kw): #step three - copy keywords if any - for (key, value) in list(kw.items()): + for key, value in kw.items(): self.__dict__[key] = value def __repr__(self): @@ -73,7 +73,7 @@ use if you have been hacking the styles. This is used by __init__""" if self.parent: - for (key, value) in list(self.parent.__dict__.items()): + for key, value in self.parent.__dict__.items(): if (key not in ['name','parent']): self.__dict__[key] = value diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/lib/utils.py --- a/src/reportlab/lib/utils.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/lib/utils.py Tue Apr 30 14:28:14 2013 +0100 @@ -5,20 +5,13 @@ __doc__='''Gazillions of miscellaneous internal utility functions''' import os, sys, imp, time -try: - from hashlib import md5 -except: - from md5 import md5 +import base64 +import pickle +from io import BytesIO +import hashlib from reportlab.lib.logger import warnOnce from .rltempfile import get_rl_tempfile, get_rl_tempdir, _rl_getuid -def isSeqType(v,_st=(tuple,list)): - return isinstance(v,_st) - -if sys.hexversion<0x2030000: - True = 1 - False = 0 - if sys.hexversion >= 0x02000000: def _digester(s): return md5(s).hexdigest() @@ -27,6 +20,56 @@ def _digester(s): return join(["%02x" % ord(x) for x in md5(s).digest()], '') +isPython3 = sys.version_info[0]==3 + +def isFunctionType(v): + return type(v) == type(isFunctionType) + +class c: + def m(self): pass + +def isMethodType(v,mt=type(c.m)): + return type(v) == mt +del c + +def isModuleType(v): + return type(v) == type(sys) + +def isSeqType(v,_st=(tuple,list)): + return isinstance(v,_st) + +if isPython3: + def UniChr(v): + return chr(v) + + def isStrType(v): + return isinstance(v, str) + + def isBytesType(v): + return isinstance(v, bytes) + + def isUnicodeType(v): + return isinstance(v, str) + + def isClassType(v): + return isinstance(v, type) +else: + def UniChr(v): + return unichr(v) + + def isStrType(v): + return isinstance(v, basestring) + + def isBytesType(v): + return isinstance(v, str) + + def isUnicodeType(v): + return isinstance(v, unicode) + + def isClassType(v): + import types + return isinstance(v, types.ClassType) + def _findFiles(dirList,ext='.ttf'): from os.path import isfile, isdir, join as path_join from os import listdir @@ -40,39 +83,34 @@ if isfile(fn) and (not ext or fn.lower().endswith(ext)): A(fn) return R -try: - _UserDict = dict -except: - from UserDict import UserDict as _UserDict - -class CIDict(_UserDict): +class CIDict(dict): def __init__(self,*args,**kwds): for a in args: self.update(a) self.update(kwds) def update(self,D): - for k,v in list(D.items()): self[k] = v + for k,v in D.items(): self[k] = v def __setitem__(self,k,v): try: k = k.lower() except: pass - _UserDict.__setitem__(self,k,v) + dict.__setitem__(self,k,v) def __getitem__(self,k): try: k = k.lower() except: pass - return _UserDict.__getitem__(self,k) + return dict.__getitem__(self,k) def __delitem__(self,k): try: k = k.lower() except: pass - return _UserDict.__delitem__(self,k) + return dict.__delitem__(self,k) def get(self,k,dv=None): try: @@ -92,14 +130,14 @@ k = k.lower() except: pass - return _UserDict.pop(*((self,k)+a)) + return dict.pop(*((self,k)+a)) def setdefault(self,k,*a): try: k = k.lower() except: pass - return _UserDict.setdefault(*((self,k)+a)) + return dict.setdefault(*((self,k)+a)) if os.name == 'mac': #with the Mac, we need to tag the file in a special @@ -255,52 +293,6 @@ def fp_str(*a): return _FP_STR(*a).replace(',','.') -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 = list(map(normalize,sys.path)) - if baseDir: - if not isSeqType(baseDir): - tp = [baseDir] - else: - 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) - - if noCWD: - for p in ('','.',normalize('.')): - while p in path: - if debug: print('removed "%s" from path' % p) - path.remove(p) - elif '.' not in path: - path.insert(0,'.') - - if debug: - import pprint - pp = pprint.pprint - 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), locals()) - sys.path = opath - return m - except ImportError: - sys.path = opath - msg = "Could not import '%s'" % modulename - if baseDir: - msg = msg + " under %s" % baseDir - raise ImportError(msg) - - except Exception, e: - msg = "Exception raised while importing '%s': %s" % (modulename, e.message) - raise ImportError(msg) - - def recursiveGetAttr(obj, name): "Can call down into e.g. object1.object2[4].attr" return eval(name, obj.__dict__) @@ -347,14 +339,11 @@ Image = None haveImages = Image is not None -try: - from io import StringIO as __StringIO -except ImportError: - from io import StringIO as __StringIO -def getStringIO(buf=None): +def getBytesIO(buf=None): '''unified StringIO instance interface''' - return buf is not None and __StringIO(buf) or __StringIO() -_StringIOKlass=__StringIO().__class__ + if buf: + return BytesIO(buf) + return BytesIO() class ArgvDictValue: '''A type to allow clients of getArgvDict to specify a conversion function''' @@ -371,8 +360,7 @@ if func: v = func(av) else: - if isinstance(v,str): - if isinstance(v,str): v = v.encode('utf8') + if isStrType(v): v = av elif isinstance(v,float): v = float(av) @@ -388,7 +376,7 @@ A = sys.argv[1:] R = {} - for k, v in list(kw.items()): + for k, v in kw.items(): if isinstance(v,ArgvDictValue): v, func = v.value, v.func else: @@ -437,20 +425,26 @@ name = _startswith_rl(name) s = __loader__.get_data(name) if 'b' not in mode and os.linesep!='\n': s = s.replace(os.linesep,'\n') - return getStringIO(s) + return getBytesIO(s) -import urllib.request, urllib.error, urllib.parse -def open_for_read(name,mode='b', urlopen=urllib.request.urlopen): +try: + import urllib2 + urlopen=urllib2.urlopen +except ImportError: + import urllib.request + urlopen=urllib.request.urlopen + +def open_for_read(name,mode='b', urlopen=urlopen): '''attempt to open a file or URL for reading''' if hasattr(name,'read'): return name try: return open_for_read_by_name(name,mode) except: try: - return getStringIO(urlopen(name).read()) + return getBytesIO(urlopen(name).read()) except: raise IOError('Cannot open resource "%s"' % name) -del urllib2 +del urlopen def open_and_read(name,mode='b'): return open_for_read(name,mode).read() @@ -476,7 +470,7 @@ 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 list(__loader__._files.keys()) if x.startswith(pn)] + return [x[len(pn):] for x in __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) @@ -547,7 +541,7 @@ try: from reportlab.rl_config import imageReaderFlags self.fp = open_for_read(fileName,'b') - if isinstance(self.fp,_StringIOKlass): imageReaderFlags=0 #avoid messing with already internal files + if isinstance(self.fp,BytesIO): imageReaderFlags=0 #avoid messing with already internal files if imageReaderFlags>0: #interning data = self.fp.read() if imageReaderFlags&2: #autoclose @@ -560,7 +554,7 @@ from rl_config import register_reset register_reset(self._cache.clear) data=self._cache.setdefault(md5(data).digest(),data) - self.fp=getStringIO(data) + self.fp=getBytesIO(data) elif imageReaderFlags==-1 and isinstance(fileName,str): #try Ralf Schmitt's re-opening technique of avoiding too many open files self.fp.close() @@ -587,7 +581,7 @@ def identity(self): '''try to return information that will identify the instance''' fn = self.fileName - if not isinstance(fn,str): + if not isStrType(fn): 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 +664,10 @@ palette = palette.palette except: palette = palette.data - return list(map(ord, palette[transparency:transparency+3])) + if isPython3: + return palette[transparency:transparency+3] + else: + return [ord(c) for c in palette[transparency:transparency+3]] else: return None @@ -730,7 +727,7 @@ self.store = store = {} if capture_traceback and sys.exc_info() != (None,None,None): import traceback - s = getStringIO() + s = getBytesIO() traceback.print_exc(None,s) store['__traceback'] = s.getvalue() cwd=os.getcwd() @@ -763,7 +760,6 @@ 'lcwd': lcwd, 'lpcwd': lpcwd, 'byteorder': sys.byteorder, - 'maxint': sys.maxsize, 'maxint': getattr(sys,'maxunicode','????'), 'api_version': getattr(sys,'api_version','????'), 'version_info': getattr(sys,'version_info','????'), @@ -798,7 +794,7 @@ except: pass module_versions = {} - for n,m in list(sys.modules.items()): + for n,m in 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 [_f for _f in v if _f]: @@ -810,20 +806,19 @@ def _add(self,D): payload = self.store['__payload'] - for k, v in list(D.items()): + for k, v in D.items(): payload[k] = v def add(self,**kw): self._add(kw) def _dump(self,f): - import pickle try: pos=f.tell() pickle.dump(self.store,f) except: S=self.store.copy() - ff=getStringIO() + ff=getBytesIO() for k,v in S.items(): try: pickle.dump({k:v},ff) @@ -840,12 +835,11 @@ f.close() def dumps(self): - f = getStringIO() + f = getBytesIO() self._dump(f) return f.getvalue() def _load(self,f): - import pickle self.store = pickle.load(f) def load(self): @@ -856,7 +850,7 @@ f.close() def loads(self,s): - self._load(getStringIO(s)) + self._load(getBytesIO(s)) def _show_module_versions(self,k,v): self._writeln(k[2:]) @@ -866,7 +860,8 @@ vk = vk0 = v[k] if isinstance(vk,tuple): vk0 = vk[0] try: - m = recursiveImport(k,sys.path[:],1) + __import__(k) + m = sys.modules[k] d = getattr(m,'__version__',None)==vk0 and 'SAME' or 'DIFFERENT' except: m = None @@ -902,7 +897,8 @@ for mn in ('_rl_accel','_renderPM','sgmlop','pyRXP','pyRXPU','_imaging','Image'): try: A = [mn].append - m = recursiveImport(mn,sys.path[:],1) + __import__(mn) + m = sys.modules[mn] A(m.__file__) for vn in ('__version__','VERSION','_version','version'): if hasattr(m,vn): @@ -1122,14 +1118,15 @@ e = i break if e>=0: - if isinstance(a,str): - if not isinstance(msg,str): - msg=msg.decode(enc) - else: - if isinstance(msg,str): - msg=msg.encode(enc) + if not isPython3: + if isinstance(a,unicode): + if not isinstance(msg,unicode): + msg=msg.decode(enc) else: - msg = str(msg) + if isinstance(msg,unicode): + msg=msg.encode(enc) + else: + msg = str(msg) if isinstance(v,IOError) and getattr(v,'strerror',None): v.strerror = msg+'\n'+str(v.strerror) else: @@ -1166,6 +1163,18 @@ data = data.replace("&lt;", "<") return data +def encode_label(args): + s = base64.encodestring(pickle.dumps(args)).strip() + if not isStrType(s): + s = s.decode('utf-8') + return s + +def decode_label(label): + if isUnicodeType(label): + label = label.encode('utf-8') + v = pickle.loads(base64.decodestring(label)) + return v + class IdentStr(str): '''useful for identifying things that get split''' def __new__(cls,value): diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/lib/xmllib.py --- a/src/reportlab/lib/xmllib.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/lib/xmllib.py Tue Apr 30 14:28:14 2013 +0100 @@ -8,7 +8,6 @@ Probably ought to be removed''' import re -import string try: import sgmlop # this works for both builtin on the path or relative @@ -116,7 +115,7 @@ res = ref.search(data, i) if res is None: newdata.append(data[i:]) - return string.join(newdata, '') + return ''.join(newdata) if data[res.end(0) - 1] != ';': self.syntax_error(self.lineno, '; missing after entity/char reference') @@ -124,9 +123,9 @@ str = res.group(1) if str[0] == '#': if str[1] == 'x': - newdata.append(chr(string.atoi(str[2:], 16))) + newdata.append(chr(int(str[2:], 16))) else: - newdata.append(chr(string.atoi(str[1:]))) + newdata.append(chr(int(str[1:]))) else: try: newdata.append(self.entitydefs[str]) @@ -146,7 +145,7 @@ if self.nomoretags: data = rawdata[i:n] self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') + self.lineno = self.lineno + '\n'.count(data) i = n break res = interesting.search(rawdata, i) @@ -157,7 +156,7 @@ if i < j: data = rawdata[i:j] self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') + self.lineno = self.lineno + '\n'.count(data) i = j if i == n: break if rawdata[i] == '<': @@ -165,18 +164,18 @@ if self.literal: data = rawdata[i] self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') + self.lineno = self.lineno + '\n'.count(data) i = i+1 continue k = self.parse_starttag(i) if k < 0: break - self.lineno = self.lineno + string.count(rawdata[i:k], '\n') + self.lineno = self.lineno + '\n'.count(rawdata[i:k]) i = k continue if endtagopen.match(rawdata, i): k = self.parse_endtag(i) if k < 0: break - self.lineno = self.lineno + string.count(rawdata[i:k], '\n') + self.lineno = self.lineno + '\n'.count(rawdata[i:k]) i = k self.literal = 0 continue @@ -184,25 +183,25 @@ if self.literal: data = rawdata[i] self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') + self.lineno = self.lineno + '\n'.count(data) i = i+1 continue k = self.parse_comment(i) if k < 0: break - self.lineno = self.lineno + string.count(rawdata[i:k], '\n') + self.lineno = self.lineno + '\n'.count(rawdata[i:k]) i = k continue if cdataopen.match(rawdata, i): k = self.parse_cdata(i) if k < 0: break - self.lineno = self.lineno + string.count(rawdata[i:i], '\n') + self.lineno = self.lineno + '\n'.count(rawdata[i:i]) i = k continue res = procopen.match(rawdata, i) if res: k = self.parse_proc(i, res) if k < 0: break - self.lineno = self.lineno + string.count(rawdata[i:k], '\n') + self.lineno = self.lineno + '\n'.count(rawdata[i:k]) i = k continue res = special.match(rawdata, i) @@ -210,11 +209,11 @@ if self.literal: data = rawdata[i] self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') + self.lineno = self.lineno + '\n'.count(data) i = i+1 continue self.handle_special(res.group('special')) - self.lineno = self.lineno + string.count(res.group(0), '\n') + self.lineno = self.lineno + '\n'.count(res.group(0)) i = res.end(0) continue elif rawdata[i] == '&': @@ -225,7 +224,7 @@ self.syntax_error(self.lineno, '; missing in charref') i = i-1 self.handle_charref(res.group('char')[:-1]) - self.lineno = self.lineno + string.count(res.group(0), '\n') + self.lineno = self.lineno + '\n'.count(res.group(0)) continue res = entityref.match(rawdata, i) if res is not None: @@ -234,7 +233,7 @@ self.syntax_error(self.lineno, '; missing in entityref') i = i-1 self.handle_entityref(res.group('name')) - self.lineno = self.lineno + string.count(res.group(0), '\n') + self.lineno = self.lineno + '\n'.count(res.group(0)) continue else: raise RuntimeError('neither < nor & ??') @@ -244,7 +243,7 @@ if not res: data = rawdata[i] self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') + self.lineno = self.lineno + '\n'.count(data) i = i+1 continue j = res.end(0) @@ -253,13 +252,13 @@ self.syntax_error(self.lineno, 'bogus < or &') data = res.group(0) self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') + self.lineno = self.lineno + '\n'.count(data) i = j # end while if end and i < n: data = rawdata[i:n] self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') + self.lineno = self.lineno + '\n'.count(data) i = n self.rawdata = rawdata[i:] # XXX if end: check for empty stack @@ -424,10 +423,10 @@ def handle_charref(self, name): try: if name[0] == 'x': - n = string.atoi(name[1:], 16) + n = int(name[1:], 16) else: - n = string.atoi(name) - except string.atoi_error: + n = int(name) + except int_error: self.unknown_charref(name) return if not 0 <= n <= 255: @@ -530,7 +529,7 @@ res = ref.search(data, i) if res is None: newdata.append(data[i:]) - return string.join(newdata, '') + return ''.join(newdata) if data[res.end(0) - 1] != ';': self.syntax_error(self.lineno, '; missing after entity/char reference') @@ -538,9 +537,9 @@ str = res.group(1) if str[0] == '#': if str[1] == 'x': - newdata.append(chr(string.atoi(str[2:], 16))) + newdata.append(chr(int(str[2:], 16))) else: - newdata.append(chr(string.atoi(str[1:]))) + newdata.append(chr(int(str[1:]))) else: try: newdata.append(self.entitydefs[str]) @@ -603,10 +602,10 @@ def handle_charref(self, name): try: if name[0] == 'x': - n = string.atoi(name[1:], 16) + n = int(name[1:], 16) else: - n = string.atoi(name) - except string.atoi_error: + n = int(name) + except ValueError: self.unknown_charref(name) return if not 0 <= n <= 255: @@ -713,7 +712,7 @@ print('start tag: <' + tag + '>') else: print('start tag: <' + tag, end=' ') - for name, value in list(attrs.items()): + for name, value in attrs.items(): print(name + '=' + '"' + value + '"', end=' ') print('>') diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfbase/_can_cmap_data.py --- a/src/reportlab/pdfbase/_can_cmap_data.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfbase/_can_cmap_data.py Tue Apr 30 14:28:14 2013 +0100 @@ -29,7 +29,7 @@ buf = [] buf.append('widthsByUnichar = {}') - for (fontName, (language, encName)) in list(defaultUnicodeEncodings.items()): + for fontName, (language, encName) in defaultUnicodeEncodings.items(): print('handling %s : %s : %s' % (fontName, language, encName)) #this does just about all of it for us, as all the info @@ -39,7 +39,7 @@ widthsByCID = font.face._explicitWidths cmap = font.encoding._cmap nonStandardWidthsByUnichar = {} - for (codePoint, cid) in list(cmap.items()): + for codePoint, cid in cmap.items(): width = widthsByCID.get(cid, 1000) if width != 1000: nonStandardWidthsByUnichar[chr(codePoint)] = width diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfbase/_fontdata.py --- a/src/reportlab/pdfbase/_fontdata.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfbase/_fontdata.py Tue Apr 30 14:28:14 2013 +0100 @@ -17,7 +17,7 @@ as Jython cannot handle more than 64k of bytecode in the 'top level' code of a Python module. """ -import UserDict, os, sys +import os, sys # mapping of name to width vector, starts empty until fonts are added # e.g. widths['Courier'] = [...600,600,600,...] @@ -88,8 +88,8 @@ 'courier-oblique': 'Courier-Oblique', } _font2fnrMap = _font2fnrMapLinux2 - for k, v in list(_font2fnrMap.items()): - if k in list(_font2fnrMapWin32.keys()): + for k, v in _font2fnrMap.items(): + if k in _font2fnrMapWin32.keys(): _font2fnrMapWin32[v.lower()] = _font2fnrMapWin32[k] del k, v else: @@ -130,21 +130,21 @@ standardEncodings = ('WinAnsiEncoding','MacRomanEncoding','StandardEncoding','SymbolEncoding','ZapfDingbatsEncoding','PDFDocEncoding', 'MacExpertEncoding') #this is the global mapping of standard encodings to name vectors -class _Name2StandardEncodingMap(UserDict.UserDict): +class _Name2StandardEncodingMap(dict): '''Trivial fake dictionary with some [] magic''' _XMap = {'winansi':'WinAnsiEncoding','macroman': 'MacRomanEncoding','standard':'StandardEncoding','symbol':'SymbolEncoding', 'zapfdingbats':'ZapfDingbatsEncoding','pdfdoc':'PDFDocEncoding', 'macexpert':'MacExpertEncoding'} def __setitem__(self,x,v): y = x.lower() if y[-8:]=='encoding': y = y[:-8] y = self._XMap[y] - if y in list(self.keys()): raise IndexError('Encoding %s is already set' % y) - self.data[y] = v + if y in self: raise IndexError('Encoding %s is already set' % y) + dict.__setitem__(self,y,v) def __getitem__(self,x): y = x.lower() if y[-8:]=='encoding': y = y[:-8] y = self._XMap[y] - return self.data[y] + return dict.__getitem__(self,y) encodings = _Name2StandardEncodingMap() @@ -153,11 +153,22 @@ #well under 64k. We might well be able to ditch many of #these anyway now we run on Unicode. -for keyname in standardEncodings: - modname = '_fontdata_enc_%s' % keyname.lower()[:-8] #chop off 'Encoding' - module = __import__(modname, globals(), locals()) - encodings[keyname] = getattr(module, keyname) - +from reportlab.pdfbase._fontdata_enc_winansi import WinAnsiEncoding +from reportlab.pdfbase._fontdata_enc_macroman import MacRomanEncoding +from reportlab.pdfbase._fontdata_enc_standard import StandardEncoding +from reportlab.pdfbase._fontdata_enc_symbol import SymbolEncoding +from reportlab.pdfbase._fontdata_enc_zapfdingbats import ZapfDingbatsEncoding +from reportlab.pdfbase._fontdata_enc_pdfdoc import PDFDocEncoding +from reportlab.pdfbase._fontdata_enc_macexpert import MacExpertEncoding +encodings.update({ + 'WinAnsiEncoding': WinAnsiEncoding, + 'MacRomanEncoding': MacRomanEncoding, + 'StandardEncoding': StandardEncoding, + 'SymbolEncoding': SymbolEncoding, + 'ZapfDingbatsEncoding': ZapfDingbatsEncoding, + 'PDFDocEncoding': PDFDocEncoding, + 'MacExpertEncoding': MacExpertEncoding, +}) ascent_descent = { 'Courier': (629, -157), @@ -177,12 +188,50 @@ } # ditto about 64k limit - profusion of external files -widthsByFontGlyph = {} -for fontName in standardFonts: - modname = '_fontdata_widths_%s' % fontName.lower().replace('-','') - module = __import__(modname, globals(), locals()) - widthsByFontGlyph[fontName] = module.widths - +import reportlab.pdfbase._fontdata_widths_courier +import reportlab.pdfbase._fontdata_widths_courierbold +import reportlab.pdfbase._fontdata_widths_courieroblique +import reportlab.pdfbase._fontdata_widths_courierboldoblique +import reportlab.pdfbase._fontdata_widths_helvetica +import reportlab.pdfbase._fontdata_widths_helveticabold +import reportlab.pdfbase._fontdata_widths_helveticaoblique +import reportlab.pdfbase._fontdata_widths_helveticaboldoblique +import reportlab.pdfbase._fontdata_widths_timesroman +import reportlab.pdfbase._fontdata_widths_timesbold +import reportlab.pdfbase._fontdata_widths_timesitalic +import reportlab.pdfbase._fontdata_widths_timesbolditalic +import reportlab.pdfbase._fontdata_widths_symbol +import reportlab.pdfbase._fontdata_widths_zapfdingbats +widthsByFontGlyph = { + 'Courier': + reportlab.pdfbase._fontdata_widths_courier.widths, + 'Courier-Bold': + reportlab.pdfbase._fontdata_widths_courierbold.widths, + 'Courier-Oblique': + reportlab.pdfbase._fontdata_widths_courieroblique.widths, + 'Courier-BoldOblique': + reportlab.pdfbase._fontdata_widths_courierboldoblique.widths, + 'Helvetica': + reportlab.pdfbase._fontdata_widths_helvetica.widths, + 'Helvetica-Bold': + reportlab.pdfbase._fontdata_widths_helveticabold.widths, + 'Helvetica-Oblique': + reportlab.pdfbase._fontdata_widths_helveticaoblique.widths, + 'Helvetica-BoldOblique': + reportlab.pdfbase._fontdata_widths_helveticaboldoblique.widths, + 'Times-Roman': + reportlab.pdfbase._fontdata_widths_timesroman.widths, + 'Times-Bold': + reportlab.pdfbase._fontdata_widths_timesbold.widths, + 'Times-Italic': + reportlab.pdfbase._fontdata_widths_timesitalic.widths, + 'Times-BoldItalic': + reportlab.pdfbase._fontdata_widths_timesbolditalic.widths, + 'Symbol': + reportlab.pdfbase._fontdata_widths_symbol.widths, + 'ZapfDingbats': + reportlab.pdfbase._fontdata_widths_zapfdingbats.widths, +} #preserve the initial values here diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfbase/cidfonts.py --- a/src/reportlab/pdfbase/cidfonts.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfbase/cidfonts.py Tue Apr 30 14:28:14 2013 +0100 @@ -46,7 +46,7 @@ "Converts deeply nested structure to PDFdoc dictionary/array objects" if type(structure) is DictType: newDict = {} - for k, v in list(structure.items()): + for k, v in structure.items(): newDict[k] = structToPDF(v) return pdfdoc.PDFDictionary(newDict) elif type(structure) in (ListType, TupleType): diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfbase/pdfdoc.py --- a/src/reportlab/pdfbase/pdfdoc.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfbase/pdfdoc.py Tue Apr 30 14:28:14 2013 +0100 @@ -18,21 +18,12 @@ from reportlab.pdfbase import pdfutils from reportlab.pdfbase.pdfutils import LINEEND # this constant needed in both from reportlab import rl_config -from reportlab.lib.utils import import_zlib, open_for_read, fp_str, _digester, makeFileName +from reportlab.lib.utils import import_zlib, open_for_read, fp_str, makeFileName, isSeqType, isBytesType, isUnicodeType, _digester from reportlab.pdfbase import pdfmetrics -try: - from hashlib import md5 -except ImportError: - from md5 import md5 +from hashlib import md5 from sys import platform -try: - from sys import version_info -except: # pre-2.0 - # may be inaccurate but will at least - #work in anything which seeks to format - # version_info into a string - version_info = (1,5,2,'unknown',0) +from sys import version_info if platform[:4] == 'java' and version_info[:2] == (2, 1): # workaround for list()-bug in Jython 2.1 (should be fixed in 2.2) @@ -87,8 +78,7 @@ transparency = (1, 4), ) -from types import InstanceType -def format(element, document, toplevel=0, InstanceType=InstanceType): +def format(element, document, toplevel=0): """Indirection step for formatting. Ensures that document parameters alter behaviour of formatting for all elements. @@ -164,12 +154,16 @@ self._pdfVersion = pdfVersion # signature for creating PDF ID sig = self.signature = md5() - sig.update("a reportlab document") + sig.update(b"a reportlab document") if not self.invariant: cat = _getTimeStamp() else: cat = 946684800.0 - sig.update(repr(cat)) # initialize with timestamp digest + cat = repr(cat) + import sys + if sys.version_info[0] == 3: + cat = bytes(repr(cat), 'utf-8') + sig.update(cat) # initialize with timestamp digest # mapping of internal identifier ("Page001") to PDF objectnumber and generation number (34, 0) self.idToObjectNumberAndVersion = {} # mapping of internal identifier ("Page001") to PDF object (PDFPage instance) @@ -233,14 +227,17 @@ myfile = 1 filename = makeFileName(filename) f = open(filename, "wb") - f.write(self.GetPDFData(canvas)) + data = self.GetPDFData(canvas) + if isUnicodeType(data): + data = data.encode('utf8') + f.write(data) if myfile: f.close() import os 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 %s' % (filename,)) def GetPDFData(self, canvas): # realize delayed fonts @@ -268,7 +265,7 @@ """specify that we are in a form xobject (disable page features, etc)""" # don't need this check anymore since going in a form pushes old context at canvas level. #if self.inObject not in ["form", None]: - # raise ValueError, "can't go in form already in object %s" % self.inObject + # raise ValueError("can't go in form already in object %s" % self.inObject) self.inObject = "form" # don't need to do anything else, I think... @@ -509,7 +506,7 @@ #print "xobjDict D", D return PDFDictionary(D) - def Reference(self, object, name=None, InstanceType=InstanceType): + def Reference(self, object, name=None): ### note references may "grow" during the final formatting pass: don't use d.keys()! # don't make references to other references, or non instances, unless they are named! #print"object type is ", type(object) @@ -553,8 +550,11 @@ def __init__(self, t): self.t = t def format(self, document): - result = binascii.hexlify(document.encrypt.encode(self.t)) - return "<%s>" % result + t = self.t + if isUnicodeType(t): + t = t.encode('utf-8') + result = binascii.hexlify(document.encrypt.encode(t)) + return b"<" + result + b">" def __str__(self): dummydoc = DummyDoc() return self.format(dummydoc) @@ -604,7 +604,7 @@ def format(self, document): s = self.s enc = getattr(self,'enc','auto') - if type(s) is str: + if (isBytesType(s)): if enc is 'auto': try: u = s.decode(s.startswith(codecs.BOM_UTF16_BE) and 'utf16' or 'utf8') @@ -616,10 +616,9 @@ try: s.decode('pdfdoc') except: - import sys - print('Error in',repr(s), file=sys.stderr) + sys.stderr.write('Error in %s' % (repr(s),)) raise - elif type(s) is str: + elif isUnicodeType(s): if enc is 'auto': if _checkPdfdoc(s): s = s.encode('pdfdoc') @@ -645,7 +644,7 @@ es = es.replace('\\(','(').replace('\\)',')') return es else: - return '(%s)' % s + return b'(' + s + b')' def __str__(self): return "(%s)" % pdfutils._escape(self.s) @@ -756,6 +755,8 @@ from reportlab.lib.utils import import_zlib zlib = import_zlib() if not zlib: raise ImportError("cannot z-compress zlib unavailable") + if isUnicodeType(text): + text = text.encode('utf8') return zlib.compress(text) def decode(self, encoded): from reportlab.lib.utils import import_zlib @@ -841,7 +842,7 @@ #content = "" # test if content is None: content = teststreamcontent - content = string.strip(content) + content = content.strip() content = string.replace(content, "\n", LINEEND) + LINEEND S = PDFStream(content = content, filters=rl_config.useA85 and [PDFBase85Encode,PDFZCompress] or [PDFZCompress]) @@ -940,8 +941,8 @@ self.write(s) return result def format(self, document): - strings = list(map(str, self.strings)) # final conversion, in case of lazy objects - return string.join(strings, "") + strings = map(str, self.strings) # final conversion, in case of lazy objects + return "".join(strings) XREFFMT = '%0.10d %0.5d n' @@ -987,7 +988,7 @@ reflineend = LINEEND else: raise ValueError("bad end of line! %s" % repr(LINEEND)) - return string.join(entries, LINEEND) + return LINEEND.join(entries) class PDFCrossReferenceTable: __PDFObject__ = True @@ -1005,7 +1006,7 @@ for s in self.sections: fs = format(s, document) L.append(fs) - return string.join(L, "") + return "".join(L) TRAILERFMT = ("trailer%(LINEEND)s" "%(dict)s%(LINEEND)s" @@ -1045,10 +1046,9 @@ __Defaults__ = {"Type": PDFName("Catalog"), "PageMode": PDFName("UseNone"), } - __NoDefault__ = string.split(""" + __NoDefault__ = """ Dests Outlines Pages Threads AcroForm Names OpenAction PageMode URI - ViewerPreferences PageLabels PageLayout JavaScript StructTreeRoot SpiderInfo""" - ) + ViewerPreferences PageLabels PageLayout JavaScript StructTreeRoot SpiderInfo""".split() __Refs__ = __NoDefault__ # make these all into references, if present def format(self, document): @@ -1056,7 +1056,7 @@ defaults = self.__Defaults__ Refs = self.__Refs__ D = {} - for k in list(defaults.keys()): + for k in defaults.keys(): default = defaults[k] v = None if hasattr(self, k) and getattr(self,k) is not None: @@ -1103,7 +1103,7 @@ # note: could implement page attribute inheritance... __Defaults__ = {"Type": PDFName("Pages"), } - __NoDefault__ = string.split("Kids Count Parent") + __NoDefault__ = "Kids Count Parent".split() __Refs__ = ["Parent"] def __init__(self): self.pages = [] @@ -1129,14 +1129,11 @@ __Defaults__ = {"Type": PDFName("Page"), # "Parent": PDFObjectReference(Pages), # no! use document.Pages } - __NoDefault__ = string.split(""" Parent + __NoDefault__ = """Parent MediaBox Resources Contents CropBox Rotate Thumb Annots B Dur Hid Trans AA PieceInfo LastModified SeparationInfo ArtBox TrimBox BleedBox ID PZ - Trans - """) - __Refs__ = string.split(""" - Contents Parent ID - """) + Trans""".split() + __Refs__ = """Contents Parent ID""".split() pagewidth = 595 pageheight = 842 stream = None @@ -1158,9 +1155,8 @@ def setStream(self, code): if self.Override_default_compilation: raise ValueError("overridden! must set stream explicitly") - from types import ListType - if type(code) is ListType: - code = string.join(code, LINEEND)+LINEEND + if isSeqType(code): + code = LINEEND.join(code)+LINEEND self.stream = code def setPageTransition(self, tranDict): @@ -1175,7 +1171,7 @@ self.Annots = None else: #print self.Annots - #raise ValueError, "annotations not reimplemented yet" + #raise ValueError("annotations not reimplemented yet") if not hasattr(self.Annots,'__PDFObject__'): self.Annots = PDFArray(self.Annots) if not self.Contents: @@ -1341,7 +1337,7 @@ class PDFOutlines0: __PDFObject__ = True __Comment__ = "TEST OUTLINE!" - text = string.replace(DUMMYOUTLINE, "\n", LINEEND) + text = DUMMYOUTLINE.replace("\n", LINEEND) __RefOnly__ = 1 def format(self, document): return self.text @@ -1396,10 +1392,9 @@ def addOutlineEntry(self, destinationname, level=0, title=None, closed=None): """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 not isinstance(level,int): 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 @@ -1417,7 +1412,7 @@ del stack[-1] previous = stack[-1] lastinprevious = previous[-1] - if type(lastinprevious) is TupleType: + if isinstance(lastinprevious,tuple): (name, sectionlist) = lastinprevious raise ValueError("cannot reset existing sections: " + repr(lastinprevious)) else: @@ -1457,12 +1452,10 @@ def translateNames(self, canvas, object): "recursively translate tree of names into tree of destinations" - from types import StringType, ListType, TupleType - Ot = type(object) destinationnamestotitles = self.destinationnamestotitles destinationstotitles = self.destinationstotitles closedict = self.closedict - if Ot is StringType: + if isStrType(object): destination = canvas._bookmarkReference(object) title = object if object in destinationnamestotitles: @@ -1473,11 +1466,11 @@ if object in closedict: closedict[destination] = 1 # mark destination closed return {object: canvas._bookmarkReference(object)} # name-->ref - if Ot is ListType or Ot is TupleType: + if isSeqType(object): L = [] for o in object: L.append(self.translateNames(canvas, o)) - if Ot is TupleType: + if isinstance(object,tuple): return tuple(L) return L # bug contributed by Benjamin Dumke @@ -1504,8 +1497,6 @@ self.ready = 1 def maketree(self, document, destinationtree, Parent=None, toplevel=0): - from types import ListType, TupleType, DictType - tdestinationtree = type(destinationtree) if toplevel: levelname = "Outline" Parent = document.Reference(document.Outlines) @@ -1514,7 +1505,7 @@ levelname = "Outline.%s" % self.count if Parent is None: raise ValueError("non-top level outline elt parent must be specified") - if tdestinationtree is not ListType and tdestinationtree is not TupleType: + if not isSeqType(destinationtree): raise ValueError("destinationtree must be list or tuple, got %s") nelts = len(destinationtree) lastindex = nelts-1 @@ -1536,11 +1527,10 @@ lastelt = eltobj # advance eltobj lastref = eltref elt = destinationtree[index] - te = type(elt) - if te is DictType: + if isinstance(elt,dict): # simple leaf {name: dest} leafdict = elt - elif te is TupleType: + elif isinstance(elt,tuple): # leaf with subsections: ({name: ref}, subsections) XXXX should clean up (see count(...)) try: (leafdict, subsections) = elt @@ -1556,7 +1546,7 @@ 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: + if isinstance(elt,tuple) and Dest in closedict: # closed subsection, count should be negative eltobj.Count = -eltobj.Count return (firstref, lastref) @@ -1564,15 +1554,13 @@ def count(tree, closedict=None): """utility for outline: recursively count leaves in a tuple/list tree""" from operator import add - from types import TupleType, ListType - tt = type(tree) - if tt is TupleType: + if isinstance(tree,tuple): # leaf with subsections XXXX should clean up this structural usage (leafdict, subsections) = tree [(Title, Dest)] = list(leafdict.items()) if closedict and Dest in closedict: return 1 # closed tree element - if tt is TupleType or tt is ListType: + if isSeqType(tree): #return reduce(add, map(count, tree)) counts = [] for e in tree: @@ -1617,7 +1605,7 @@ def copy(self): "shallow copy - useful in pagecatchering" thing = self.__klass__() - for (k, v) in list(self.__dict__.items()): + for k, v in self.__dict__.items(): setattr(thing, k, v) return thing # skipping thumbnails, etc @@ -1632,7 +1620,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 bytes: + if not isStrType(Rect): d["Rect"] = PDFArray(Rect) d["Contents"] = PDFString(d["Contents"],escape) return d @@ -1651,7 +1639,7 @@ raise ValueError("keyword argument %s missing" % name) d = self.cvtdict(d,escape=escape) permitted = self.permitted - for name in list(d.keys()): + for name in d.keys(): if name not in permitted: raise ValueError("bad annotation dictionary name %s" % name) return PDFDictionary(d) @@ -1747,7 +1735,7 @@ # gmt offset now suppported properly def __init__(self, invariant=rl_config.invariant, dateFormatter=None): if invariant: - now = (2000,0o1,0o1,00,00,00,0) + now = (2000,1,1,0,0,0,0) self.dhh = 0 self.dmm = 0 else: @@ -1895,7 +1883,7 @@ self.Shading = {} # ?by default define the basicprocs self.basicProcs() - stdprocs = list(map(PDFName, string.split("PDF Text ImageB ImageC ImageI"))) + stdprocs = [PDFName(s) for s in "PDF Text ImageB ImageC ImageI".split()] dict_attributes = ("ColorSpace", "XObject", "ExtGState", "Font", "Pattern", "Properties", "Shading") def allProcs(self): @@ -1918,10 +1906,9 @@ def format(self, document): D = {} - from types import ListType, DictType for dname in self.dict_attributes: v = getattr(self, dname) - if type(v) is DictType: + if isinstance(v,dict): if v: dv = PDFDictionary(v) D[dname] = dv @@ -1929,7 +1916,7 @@ D[dname] = v v = self.ProcSet dname = "ProcSet" - if type(v) is ListType: + if isSeqType(v): if v: dv = PDFArray(v) D[dname] = dv @@ -1949,11 +1936,11 @@ __PDFObject__ = True __RefOnly__ = 1 # note! /Name appears to be an undocumented attribute.... - name_attributes = string.split("Type Subtype BaseFont Name") + name_attributes = "Type Subtype BaseFont Name".split() Type = "Font" Subtype = "Type1" # these attributes are assumed to already be of the right type - local_attributes = string.split("FirstChar LastChar Widths Encoding ToUnicode FontDescriptor") + local_attributes = "FirstChar LastChar Widths Encoding ToUnicode FontDescriptor".split() def format(self, document): D = {} for name in self.name_attributes: @@ -2023,8 +2010,8 @@ self.lowerx = lowerx; self.lowery=lowery; self.upperx=upperx; self.uppery=uppery def setStreamList(self, data): - if type(data) is list: - data = string.join(data, LINEEND) + if isSeqType(data): + data = LINEEND.join(data) self.stream = data def BBoxList(self): @@ -2120,7 +2107,7 @@ else: # it is a filename import os - ext = string.lower(os.path.splitext(source)[1]) + ext = os.path.splitext(source)[1].lower() src = open_for_read(source) if not(ext in ('.jpg', '.jpeg') and self.loadImageFromJPEG(src)): if rl_config.useA85: @@ -2130,15 +2117,15 @@ def loadImageFromA85(self,source): IMG=[] - imagedata = list(map(string.strip,pdfutils.makeA85Image(source,IMG=IMG))) - words = string.split(imagedata[1]) - self.width, self.height = list(map(string.atoi,(words[1],words[3]))) + imagedata = [s.strip() for s in pdfutils.makeA85Image(source,IMG=IMG)] + words = imagedata[1].split() + self.width, self.height = (int(words[1]),int(words[3])) self.colorSpace = {'/RGB':'DeviceRGB', '/G':'DeviceGray', '/CMYK':'DeviceCMYK'}[words[7]] self.bitsPerComponent = 8 self._filters = 'ASCII85Decode','FlateDecode' #'A85','Fl' if IMG: self._checkTransparency(IMG[0]) elif self.mask=='auto': self.mask = None - self.streamContent = string.join(imagedata[3:-1],'') + self.streamContent = ''.join(imagedata[3:-1]) def loadImageFromJPEG(self,imageFile): try: @@ -2170,13 +2157,14 @@ IMG=[] imagedata = pdfutils.makeRawImage(source,IMG=IMG) words = string.split(imagedata[1]) - self.width, self.height = list(map(string.atoi,(words[1],words[3]))) + self.width = int(words[1]) + self.height = int(words[3]) self.colorSpace = {'/RGB':'DeviceRGB', '/G':'DeviceGray', '/CMYK':'DeviceCMYK'}[words[7]] self.bitsPerComponent = 8 self._filters = 'FlateDecode', #'Fl' if IMG: self._checkTransparency(IMG[0]) elif self.mask=='auto': self.mask = None - self.streamContent = string.join(imagedata[3:-1],'') + self.streamContent = ''.join(imagedata[3:-1]) def _checkTransparency(self,im): if self.mask=='auto': @@ -2228,7 +2216,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(list(map(PDFName,self._filters))) + dict["Filter"] = PDFArray(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 @@ -2297,7 +2285,7 @@ if name not in d: raise ValueError("keyword argument %s missing" % name) permitted = self.permitted - for name in list(d.keys()): + for name in d.keys(): if name not in permitted: raise ValueError("bad annotation dictionary name %s" % name) return PDFDictionary(d) @@ -2358,7 +2346,7 @@ if name not in d: raise ValueError("keyword argument %s missing" % name) permitted = self.permitted - for name in list(d.keys()): + for name in d.keys(): if name not in permitted: raise ValueError("bad annotation dictionary name %s" % name) return PDFDictionary(d) diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfbase/pdfform.py --- a/src/reportlab/pdfbase/pdfform.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfbase/pdfform.py Tue Apr 30 14:28:14 2013 +0100 @@ -191,7 +191,7 @@ from reportlab.pdfbase.pdfdoc import PDFDictionary fontsdictionary = PDFDictionary() fontsdictionary.__RefOnly__ = 1 - for (fullname, shortname) in list(FORMFONTNAMES.items()): + for fullname, shortname in FORMFONTNAMES.items(): fontsdictionary[shortname] = FormFont(fullname, shortname) fontsdictionary["ZaDb"] = ZADB return fontsdictionary diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfbase/pdfmetrics.py --- a/src/reportlab/pdfbase/pdfmetrics.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfbase/pdfmetrics.py Tue Apr 30 14:28:14 2013 +0100 @@ -19,13 +19,12 @@ trap attempts to access them and do it on first access. """ import string, os, sys -from types import StringType, ListType, TupleType from reportlab.pdfbase import _fontdata 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.lib.utils import rl_isfile, rl_glob, rl_isdir, open_and_read, open_and_readlines, findInPaths, isSeqType, isStrType, isUnicodeType, isPython3 from reportlab.rl_config import defaultEncoding, T1SearchPath from . import rl_codecs -_notdefChar = chr(110) +_notdefChar = b'n' rl_codecs.RL_Codecs.register() standardFonts = _fontdata.standardFonts @@ -37,8 +36,6 @@ def _py_unicode2T1(utext,fonts): '''return a list of (font,string) pairs representing the unicode text''' - #print 'unicode2t1(%s, %s): %s' % (utext, fonts, type(utext)) - #if type(utext) R = [] font, fonts = fonts[0], fonts[1:] enc = font.encName @@ -46,7 +43,11 @@ enc = 'UTF16' while utext: try: - R.append((font,utext.encode(enc))) + if isUnicodeType(utext): + s = utext.encode(enc) + else: + s = utext + R.append((font,s)) break except UnicodeEncodeError as e: i0, il = e.args[2:4] @@ -80,13 +81,14 @@ lines = open_and_readlines(afmFileName, 'r') if len(lines)<=1: #likely to be a MAC file - if lines: lines = string.split(lines[0],'\r') + if lines: lines = lines[0].split('\r') if len(lines)<=1: raise ValueError('AFM file %s hasn\'t enough data' % afmFileName) topLevel = {} glyphLevel = [] - lines = [l for l in map(string.strip, lines) if not l.lower().startswith('comment')] + lines = [l.strip() for l in lines] + lines = [l for l in lines if not l.lower().startswith('comment')] #pass 1 - get the widths inMetrics = 0 # os 'TOP', or 'CHARMETRICS' for line in lines: @@ -95,22 +97,22 @@ elif line[0:14] == 'EndCharMetrics': inMetrics = 0 elif inMetrics: - chunks = string.split(line, ';') - chunks = list(map(string.strip, chunks)) + chunks = line.split(';') + chunks = [chunk.strip() for chunk in chunks] cidChunk, widthChunk, nameChunk = chunks[0:3] # character ID - l, r = string.split(cidChunk) + l, r = cidChunk.split() assert l == 'C', 'bad line in font file %s' % line - cid = string.atoi(r) + cid = int(r) # width - l, r = string.split(widthChunk) + l, r = widthChunk.split() assert l == 'WX', 'bad line in font file %s' % line - width = string.atoi(r) + width = int(r) # name - l, r = string.split(nameChunk) + l, r = nameChunk.split() assert l == 'N', 'bad line in font file %s' % line name = r @@ -126,11 +128,11 @@ elif inHeader: if line[0:7] == 'Comment': pass try: - left, right = string.split(line,' ',1) + left, right = line.split(' ',1) except: raise ValueError("Header information error in afm %s: line='%s'" % (afmFileName, line)) try: - right = string.atoi(right) + right = int(right) except: pass topLevel[left] = right @@ -178,7 +180,7 @@ return [] def findT1File(self, ext='.pfb'): - possible_exts = (string.lower(ext), string.upper(ext)) + possible_exts = (ext.lower(), ext.upper()) if hasattr(self,'pfbFileName'): r_basename = os.path.splitext(self.pfbFileName)[0] for e in possible_exts: @@ -189,14 +191,14 @@ except: afm = bruteForceSearchForAFM(self.name) if afm: - if string.lower(ext) == '.pfb': + if ext.lower() == '.pfb': for e in possible_exts: pfb = os.path.splitext(afm)[0] + e if rl_isfile(pfb): r = pfb else: r = None - elif string.lower(ext) == '.afm': + elif ext.lower() == '.afm': r = afm else: r = None @@ -251,11 +253,11 @@ # assume based on the usual one self.baseEncodingName = defaultEncoding self.vector = _fontdata.encodings[defaultEncoding] - elif type(base) is StringType: + elif isStrType(base): baseEnc = getEncoding(base) self.baseEncodingName = baseEnc.name self.vector = baseEnc.vector[:] - elif type(base) in (ListType, TupleType): + elif isSeqType(base): self.baseEncodingName = defaultEncoding self.vector = base[:] elif isinstance(base, Encoding): @@ -407,19 +409,19 @@ """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,str): text = text.decode(encoding) + if not isUnicodeType(text): 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): "returns a pretty block in PDF Array format to aid inspection" - text = '[' + text = b'[' for i in range(256): - text = text + ' ' + str(self.widths[i]) + text = text + b' ' + bytes(str(self.widths[i]),'utf8') if i == 255: - text = text + ' ]' + text = text + b' ]' if i % 16 == 15: - text = text + '\n' + text = text + b'\n' return text def addObjects(self, doc): @@ -457,20 +459,33 @@ PFB_ASCII=chr(1) PFB_BINARY=chr(2) PFB_EOF=chr(3) -def _pfbSegLen(p,d): - '''compute a pfb style length from the first 4 bytes of string d''' - return ((((ord(d[p+3])<<8)|ord(d[p+2])<<8)|ord(d[p+1]))<<8)|ord(d[p]) -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]))) - 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))) - return p, p+l +if isPython3: + def _pfbCheck(p,d,m,fn): + if chr(d[p])!=PFB_MARKER or chr(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,d[p],d[p+1])) + if m==PFB_EOF: return + p = p + 2 + l = (((((d[p+3])<<8)|(d[p+2])<<8)|(d[p+1]))<<8)|(d[p]) + 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))) + return p, p+l +else: + def _pfbSegLen(p,d): + '''compute a pfb style length from the first 4 bytes of string d''' + return ((((ord(d[p+3])<<8)|ord(d[p+2])<<8)|ord(d[p+1]))<<8)|ord(d[p]) + + 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]))) + 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))) + return p, p+l class EmbeddedType1Face(TypeFace): """A Type 1 font other than one of the basic 14. @@ -526,10 +541,10 @@ self.xHeight = topLevel.get('XHeight', 1000) strBbox = topLevel.get('FontBBox', [0,0,1000,1000]) - tokens = string.split(strBbox) + tokens = strBbox.split() self.bbox = [] for tok in tokens: - self.bbox.append(string.atoi(tok)) + self.bbox.append(int(tok)) glyphWidths = {} for (cid, width, name) in glyphData: @@ -666,6 +681,7 @@ def findFontAndRegister(fontName): '''search for and register a font given its name''' + assert type(fontName) is str #it might have a font-specific encoding e.g. Symbol # or Dingbats. If not, take the default. face = getTypeFace(fontName) @@ -784,7 +800,7 @@ print('test one huge string...') test3widths([rawdata]) print() - words = string.split(rawdata) + words = rawdata.split() print('test %d shorter strings (average length %0.2f chars)...' % (len(words), 1.0*len(rawdata)/len(words))) test3widths(words) diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfbase/pdfutils.py --- a/src/reportlab/pdfbase/pdfutils.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfbase/pdfutils.py Tue Apr 30 14:28:14 2013 +0100 @@ -6,9 +6,11 @@ # pdfutils.py - everything to do with images, streams, # compression, and some constants +import sys import os +import binascii from reportlab import rl_config -from reportlab.lib.utils import getStringIO, ImageReader +from reportlab.lib.utils import getBytesIO, ImageReader, isStrType, isUnicodeType, isPython3 LINEEND = '\015\012' @@ -80,7 +82,7 @@ if filename==cachedname: if cachedImageExists(filename): from reportlab.lib.utils import open_for_read - if returnInMemory: return [_f for _f in open_for_read(cachedname).read().split(LINEEND) if _f] + if returnInMemory: return filter(None,open_for_read(cachedname).read().split(LINEEND)) else: raise IOError('No such cached image %s' % filename) else: @@ -108,7 +110,7 @@ import types, glob - if type(spec) is bytes: + if type(spec) is types.StringType: filelist = glob.glob(spec) else: #list or tuple OK filelist = spec @@ -154,26 +156,23 @@ _escape = escapePDF except ImportError: _instanceEscapePDF=None - if rl_config.sys_version>='2.1': - _ESCAPEDICT={} - for c in range(0,256): - if c<32 or c>=127: - _ESCAPEDICT[chr(c)]= '\\%03o' % c - elif c in (ord('\\'),ord('('),ord(')')): - _ESCAPEDICT[chr(c)] = '\\'+chr(c) - else: - _ESCAPEDICT[chr(c)] = chr(c) - del c - #Michael Hudson donated this - def _escape(s): - return ''.join(map(lambda c, d=_ESCAPEDICT: d[c],s)) - else: - def _escape(s): - """Escapes some PDF symbols (in fact, parenthesis). - PDF escapes are almost like Python ones, but brackets - need slashes before them too. Uses Python's repr function - and chops off the quotes first.""" - return repr(s)[1:-1].replace('(','\(').replace(')','\)') + _ESCAPEDICT={} + for c in range(256): + if c<32 or c>=127: + _ESCAPEDICT[c]= '\\%03o' % c + elif c in (ord('\\'),ord('('),ord(')')): + _ESCAPEDICT[c] = '\\'+chr(c) + else: + _ESCAPEDICT[c] = chr(c) + del c + #Michael Hudson donated this + def _escape(s): + r = [] + for c in s: + if not type(c) is int: + c = ord(c) + r.append(_ESCAPEDICT[c]) + return ''.join(r) def _normalizeLineEnds(text,desired=LINEEND,unlikely='\x00\x01\x02\x03'): """Normalizes different line end character(s). @@ -193,10 +192,11 @@ This is a verbose encoding used for binary data within a PDF file. One byte binary becomes two bytes of ASCII. Helper function used by images.""" - output = getStringIO() - for char in input: - output.write('%02x' % ord(char)) - output.write('>') + if isUnicodeType(input): + input = input.encode('utf-8') + output = getBytesIO() + output.write(binascii.b2a_hex(input)) + output.write(b'>') return output.getvalue() @@ -206,6 +206,8 @@ Not used except to provide a test of the inverse function.""" #strip out all whitespace + if not isStrType(input): + input = input.decode('utf-8') stripped = ''.join(input.split()) assert stripped[-1] == '>', 'Invalid terminator for Ascii Hex Stream' stripped = stripped[:-1] #chop off terminator @@ -224,14 +226,20 @@ whole_word_count, remainder_size = divmod(len(input), 4) cut = 4 * whole_word_count body, lastbit = input[0:cut], input[cut:] + if isPython3 and isStrType(lastbit): + lastbit = lastbit.encode('utf-8') out = [].append for i in range(whole_word_count): offset = i*4 - b1 = ord(body[offset]) - b2 = ord(body[offset+1]) - b3 = ord(body[offset+2]) - b4 = ord(body[offset+3]) + b1 = body[offset] + b2 = body[offset+1] + b3 = body[offset+2] + b4 = body[offset+3] + if isStrType(b1): b1 = ord(b1) + if isStrType(b2): b2 = ord(b2) + if isStrType(b3): b3 = ord(b3) + if isStrType(b4): b4 = ord(b4) if b1<128: num = (((((b1<<8)|b2)<<8)|b3)<<8)|b4 @@ -261,11 +269,15 @@ #encode however many bytes we have as usual if remainder_size > 0: while len(lastbit) < 4: - lastbit = lastbit + '\000' - b1 = ord(lastbit[0]) - b2 = ord(lastbit[1]) - b3 = ord(lastbit[2]) - b4 = ord(lastbit[3]) + lastbit = lastbit + b'\000' + b1 = lastbit[0] + b2 = lastbit[1] + b3 = lastbit[2] + b4 = lastbit[3] + if isStrType(b1): b1 = ord(b1) + if isStrType(b2): b2 = ord(b2) + if isStrType(b3): b3 = ord(b3) + if isStrType(b4): b4 = ord(b4) num = 16777216 * b1 + 65536 * b2 + 256 * b3 + b4 diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfbase/ttfonts.py --- a/src/reportlab/pdfbase/ttfonts.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfbase/ttfonts.py Tue Apr 30 14:28:14 2013 +0100 @@ -53,7 +53,7 @@ import string from struct import pack, unpack, error as structError -from reportlab.lib.utils import getStringIO +from reportlab.lib.utils import getBytesIO from reportlab.pdfbase import pdfmetrics, pdfdoc from reportlab import rl_config @@ -358,7 +358,7 @@ def makeStream(self): "Finishes the generation and returns the TTF file as a string" - stm = getStringIO() + stm = getBytesIO() write = stm.write numTables = len(self.tables) diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfgen/canvas.py --- a/src/reportlab/pdfgen/canvas.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfgen/canvas.py Tue Apr 30 14:28:14 2013 +0100 @@ -12,21 +12,17 @@ import os import sys import re -from string import join, split, strip, atoi, replace, upper, digits +import hashlib +from string import digits import tempfile from math import sin, cos, tan, pi, ceil -try: - from hashlib import md5 -except ImportError: - from md5 import md5 - from reportlab import rl_config from reportlab.pdfbase import pdfutils from reportlab.pdfbase import pdfdoc from reportlab.pdfbase import pdfmetrics from reportlab.pdfgen import pdfgeom, pathobject, textobject from reportlab.lib.colors import black, _chooseEnforceColorSpace, Color, CMYKColor, toColor -from reportlab.lib.utils import import_zlib, ImageReader, fp_str, _digester +from reportlab.lib.utils import import_zlib, ImageReader, fp_str, isSeqType, isStrType, isUnicodeType, _digester from reportlab.lib.boxstuff import aspectRatioFix digitPat = re.compile('\d') #used in decimal alignment @@ -317,8 +313,8 @@ ''' if encrypt: from reportlab.lib import pdfencrypt - if isinstance(encrypt, str): #encrypt is the password itself - if isinstance(encrypt, str): + if isStrType(encrypt): #encrypt is the password itself + if isUnicodeType(encrypt): encrypt = encrypt.encode('utf-8') encrypt = pdfencrypt.StandardEncryption(encrypt) #now it's the encrypt object encrypt.setAllPermissions(1) @@ -376,11 +372,10 @@ d = self.__dict__ d.update(state) - STATE_ATTRIBUTES = split(""" - _x _y _fontname _fontsize _textMode _leading _currentMatrix _fillMode + STATE_ATTRIBUTES = """_x _y _fontname _fontsize _textMode _leading _currentMatrix _fillMode _fillMode _charSpace _wordSpace _horizScale _textRenderMode _rise _textLineMatrix _textMatrix _lineCap _lineJoin _lineDash _lineWidth _mitreLimit _fillColorObj - _strokeColorObj _extgstate""") + _strokeColorObj _extgstate""".split() STATE_RANGE = list(range(len(STATE_ATTRIBUTES))) #self._addStandardFonts() @@ -912,10 +907,15 @@ mdata = smask.getRGBData() else: mdata = str(mask) + if isUnicodeType(mdata): + mdata = mdata.encode('utf8') name = _digester(rawdata+mdata) else: #filename, use it - name = _digester('%s%s' % (image, mask)) + s = '%s%s' % (image, mask) + if isUnicodeType(s): + s = s.encode('utf-8') + name = _digester(s) # in the pdf document, this will be prefixed with something to # say it is an XObject. Does it exist yet? @@ -1044,7 +1044,10 @@ will error in Distiller but work on printers supporting it. """ #check if we've done this one already... - rawName = 'PS' + md5(command).hexdigest() + if isUnicodeType(command): + rawName = 'PS' + hashlib.md5(command.encode('utf-8')).hexdigest() + else: + rawName = 'PS' + hashlib.md5(command).hexdigest() regName = self._doc.getXObjectName(rawName) psObj = self._doc.idToObject.get(regName, None) if not psObj: @@ -1198,7 +1201,10 @@ If there is current data a ShowPage is executed automatically. After this operation the canvas must not be used further.""" if len(self._code): self.showPage() - return self._doc.GetPDFData(self) + s = self._doc.GetPDFData(self) + if isUnicodeType(s): + s = s.encode('utf-8') + return s def setPageSize(self, size): """accepts a 2-tuple in points for paper size for this @@ -1254,7 +1260,7 @@ a0*c+c0*d, b0*c+d0*d, a0*e+c0*f+e0, b0*e+d0*f+f0) if self._code and self._code[-1][-3:]==' cm': - L = split(self._code[-1]) + L = self._code[-1].split() 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) @@ -1475,6 +1481,8 @@ def drawString(self, x, y, text, mode=None): """Draws a string in the current text styles.""" + if sys.version_info[0] == 3 and not isinstance(text, str): + text = text.decode('utf-8') #we could inline this for speed if needed t = self.beginText(x, y) if mode is not None: t.setTextRenderMode(mode) @@ -1483,6 +1491,8 @@ def drawRightString(self, x, y, text, mode=None): """Draws a string right-aligned with the x coordinate""" + if sys.version_info[0] == 3 and not isinstance(text, str): + text = text.decode('utf-8') width = self.stringWidth(text, self._fontname, self._fontsize) t = self.beginText(x - width, y) if mode is not None: t.setTextRenderMode(mode) @@ -1493,6 +1503,8 @@ """Draws a string centred on the x coordinate. We're British, dammit, and proud of our spelling!""" + if sys.version_info[0] == 3 and not isinstance(text, str): + text = text.decode('utf-8') width = self.stringWidth(text, self._fontname, self._fontsize) t = self.beginText(x - 0.5*width, y) if mode is not None: t.setTextRenderMode(mode) @@ -1628,9 +1640,9 @@ """Two notations. pass two numbers, or an array and phase""" if isinstance(array,(int,float)): self._code.append('[%s %s] 0 d' % (array, phase)) - elif isinstance(array,(tuple,list)): + elif isSeqType(array): assert phase >= 0, "phase is a length in user space" - textarray = ' '.join(map(str, array)) + textarray = ' '.join([str(s) for s in array]) self._code.append('[%s] %s d' % (textarray, phase)) # path stuff - the separate path object builds it diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfgen/pdfimages.py --- a/src/reportlab/pdfgen/pdfimages.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfgen/pdfimages.py Tue Apr 30 14:28:14 2013 +0100 @@ -7,13 +7,11 @@ """ import os -import string -from types import StringType import reportlab from reportlab import rl_config from reportlab.pdfbase import pdfutils from reportlab.pdfbase import pdfdoc -from reportlab.lib.utils import fp_str, getStringIO +from reportlab.lib.utils import fp_str, getBytesIO, isStrType from reportlab.lib.utils import import_zlib, haveImages from reportlab.lib.boxstuff import aspectRatioFix @@ -85,7 +83,7 @@ cachedname = os.path.splitext(image)[0] + (rl_config.useA85 and '.a85' or '.bin') imagedata = open(cachedname,'rb').readlines() #trim off newlines... - imagedata = list(map(string.strip, imagedata)) + imagedata = list(map(str.strip, imagedata)) return imagedata def PIL_imagedata(self): @@ -129,16 +127,16 @@ imagedata = pdfutils.cacheImageFile(image,returnInMemory=1) else: imagedata = self.cache_imagedata() - words = string.split(imagedata[1]) - imgwidth = string.atoi(words[1]) - imgheight = string.atoi(words[3]) + words = imagedata[1].split() + imgwidth = int(words[1]) + imgheight = int(words[3]) return imagedata, imgwidth, imgheight def getImageData(self,preserveAspectRatio=False): "Gets data, height, width - whatever type of image" image = self.image - if type(image) == StringType: + if isStrType(image): self.filename = image if os.path.splitext(image)[1] in ['.jpg', '.JPG', '.jpeg', '.JPEG']: try: @@ -189,7 +187,7 @@ dict['Height'] = self.height dict['BitsPerComponent'] = 8 dict['ColorSpace'] = pdfdoc.PDFName(self.colorSpace) - content = string.join(self.imageData[3:-1], '\n') + '\n' + content = '\n'.join(self.imageData[3:-1]) + '\n' strm = pdfdoc.PDFStream(dictionary=dict, content=content) return strm.format(document) diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfgen/pycanvas.py --- a/src/reportlab/pdfgen/pycanvas.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfgen/pycanvas.py Tue Apr 30 14:28:14 2013 +0100 @@ -149,7 +149,7 @@ arguments = "" for arg in args : arguments = arguments + ("%s, " % repr(arg)) - for (kw, val) in list(kwargs.items()) : + for kw, val in kwargs.items() : arguments = arguments+ ("%s=%s, " % (kw, repr(val))) if arguments[-2:] == ", " : arguments = arguments[:-2] diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/pdfgen/textobject.py --- a/src/reportlab/pdfgen/textobject.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/pdfgen/textobject.py Tue Apr 30 14:28:14 2013 +0100 @@ -9,10 +9,11 @@ Progress Reports: 8.83, 2000-01-13, gmcm: created from pdfgen.py """ +import sys import string from types import * from reportlab.lib.colors import Color, CMYKColor, CMYKColorSep, toColor, black, white, _CMYK_black, _CMYK_white -from reportlab.lib.utils import fp_str +from reportlab.lib.utils import fp_str, isStrType, isPython3 from reportlab.pdfbase import pdfmetrics class _PDFColorSetter: @@ -78,7 +79,7 @@ self._code.append('%s k' % fp_str(aColor)) else: raise ValueError('Unknown color %r' % aColor) - elif isinstance(aColor,str): + elif isStrType(aColor): self.setFillColor(toColor(aColor)) else: raise ValueError('Unknown color %r' % aColor) @@ -114,7 +115,7 @@ self._code.append('%s K' % fp_str(aColor)) else: raise ValueError('Unknown color %r' % aColor) - elif isinstance(aColor,str): + elif isStrType(aColor): self.setStrokeColor(toColor(aColor)) else: raise ValueError('Unknown color %r' % aColor) @@ -187,7 +188,7 @@ self._code.append('ET') if self._clipping: self._code.append('%d Tr' % (self._textRenderMode^4)) - return string.join(self._code, ' ') + return ' '.join(self._code) def setTextOrigin(self, x, y): if self._canvas.bottomup: @@ -224,11 +225,11 @@ # Check if we have a previous move cursor call, and combine # them if possible. if self._code and self._code[-1][-3:]==' Td': - L = string.split(self._code[-1]) + L = self._code[-1].split() if len(L)==3: del self._code[-1] else: - self._code[-1] = string.join(L[:-4]) + self._code[-1] = ''.join(L[:-4]) # Work out the last movement lastDx = float(L[-3]) @@ -383,7 +384,7 @@ else: #convert to T1 coding fc = font - if not isinstance(text,str): + if not isPython3 and not isinstance(text,unicode): try: text = text.decode('utf8') except UnicodeDecodeError as e: @@ -431,10 +432,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,str): - lines = string.split(string.strip(stuff), '\n') + if isStrType(stuff): + lines = '\n'.split(stuff.strip()) if trim==1: - lines = list(map(string.strip,lines)) + lines = [s.strip() for s in lines] elif isinstance(stuff,(tuple,list)): lines = stuff else: @@ -445,6 +446,6 @@ for line in lines: self.textLine(line) - def __bool__(self): + def __nonzero__(self): 'PDFTextObject is true if it has something done after the init' return self._code != ['BT'] diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/platypus/doctemplate.py --- a/src/reportlab/platypus/doctemplate.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/platypus/doctemplate.py Tue Apr 30 14:28:14 2013 +0100 @@ -463,7 +463,7 @@ self._nameSpace = dict(doc=self) self._lifetimes = {} - for k in list(self._initArgs.keys()): + for k in self._initArgs.keys(): if k not in kw: v = self._initArgs[k] else: diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/platypus/para.py --- a/src/reportlab/platypus/para.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/platypus/para.py Tue Apr 30 14:28:14 2013 +0100 @@ -988,13 +988,13 @@ def __init__(self, name, parent=None, **kw): mydict = self.__dict__ if parent: - for (a,b) in list(parent.__dict__.items()): + for a,b in parent.__dict__.items(): mydict[a]=b - for (a,b) in list(kw.items()): + for a,b in kw.items(): mydict[a] = b def addAttributes(self, dictionary): - for key in list(dictionary.keys()): + for key in dictionary.keys(): value = dictionary[key] if value is not None: if hasattr(StyleAttributeConverters, key): @@ -1186,7 +1186,7 @@ result = {} from reportlab.lib.styles import getSampleStyleSheet styles = getSampleStyleSheet() - for (stylenamekey, stylenamevalue) in list(DEFAULT_ALIASES.items()): + for stylenamekey, stylenamevalue in 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 list(DEFAULT_ALIASES.items()): + for stylenamekey, stylenamevalue in DEFAULT_ALIASES.items(): if stylenamekey in stylesheet: result[stylenamekey] = stylesheet[stylenamekey] # Then make aliases - for (stylenamekey, stylenamevalue) in list(DEFAULT_ALIASES.items()): + for stylenamekey, stylenamevalue in 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 list(DEFAULT_ALIASES.items()): + for stylenamekey, stylenamevalue in DEFAULT_ALIASES.items(): if stylenamekey not in result and stylenamevalue in styles: result[stylenamekey] = styles[stylenamevalue] return result @@ -1490,7 +1490,7 @@ L = [ "<" + tagname ] a = L.append if not attdict: attdict = {} - for (k, v) in list(attdict.items()): + for k, v in attdict.items(): a(" %s=%s" % (k,v)) if content: a(">") @@ -1915,7 +1915,6 @@ def getOp(self, tuple, engine): from reportlab.lib.sequencer import getSequencer - import math globalsequencer = getSequencer() attr = self.attdict try: @@ -1923,7 +1922,7 @@ except KeyError: id = None try: - base = math.atoi(attr['base']) + base = int(attr['base']) except: base=0 globalsequencer.reset(id, base) @@ -1994,7 +1993,7 @@ def handleSpecialCharacters(engine, text, program=None): from .paraparser import greeks - from string import whitespace, atoi, atoi_error + from string import whitespace standard={'lt':'<', 'gt':'>', 'amp':'&'} # add space prefix if space here if text[0:1] in whitespace: @@ -2025,10 +2024,10 @@ if name[0]=='#': try: if name[1] == 'x': - n = atoi(name[2:], 16) + n = int(name[2:], 16) else: - n = atoi(name[1:]) - except atoi_error: + n = int(name[1:]) + except ValueError: n = -1 if n>=0: fragment = chr(n).encode('utf8')+fragment[semi+1:] diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/platypus/paraparser.py --- a/src/reportlab/platypus/paraparser.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/platypus/paraparser.py Tue Apr 30 14:28:14 2013 +0100 @@ -218,7 +218,7 @@ _addAttributeNames(_linkAttrMap) def _applyAttributes(obj, attr): - for k, v in list(attr.items()): + for k, v in 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) @@ -972,13 +972,13 @@ def _pop(self,**kw): frag = self._stack[-1] del self._stack[-1] - for k, v in list(kw.items()): + for k, v in kw.items(): assert getattr(frag,k)==v return frag def getAttributes(self,attr,attrMap): A = {} - for k, v in list(attr.items()): + for k, v in attr.items(): if not self.caseSensitive: k = string.lower(k) if k in list(attrMap.keys()): diff -r 29c11b905751 -r 99aa837b6703 src/reportlab/platypus/tables.py --- a/src/reportlab/platypus/tables.py Sun Feb 17 12:13:56 2013 +0000 +++ b/src/reportlab/platypus/tables.py Tue Apr 30 14:28:14 2013 +0100 @@ -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 list(spanCons.keys())]) #RS=[endrowspan,.....] + msr = max([x[1] for x in spanCons.keys()]) #RS=[endrowspan,.....] if hmax>=msr: break if None not in H: hmax = lim @@ -761,7 +761,7 @@ desiredWidths = [] totalDesired = 0 effectiveRemaining = remaining - for colNo, minimum in list(minimums.items()): + for colNo, minimum in minimums.items(): w = W[colNo] if _endswith(w,'%'): desired = (float(w[:-1])/percentTotal)*availWidth @@ -821,7 +821,7 @@ assert adjusted >= minimum W[colNo] = adjusted else: - for colNo, minimum in list(minimums.items()): + for colNo, minimum in minimums.items(): W[colNo] = minimum if verbose: print('new widths are:', W) self._argW = self._colWidths = W @@ -986,7 +986,7 @@ spanRects[coord] = (x, y, width, height) for _ in hBlocks, vBlocks: - for value in list(_.values()): + for value in _.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 list(tblstyle._opts.items()): + for k,v in tblstyle._opts.items(): setattr(self,k,v) for a in ('spaceBefore','spaceAfter'): if not hasattr(self,a) and hasattr(tblstyle,a): diff -r 29c11b905751 -r 99aa837b6703 tests/test_lib_utils.py --- a/tests/test_lib_utils.py Sun Feb 17 12:13:56 2013 +0000 +++ b/tests/test_lib_utils.py Tue Apr 30 14:28:14 2013 +0100 @@ -115,8 +115,8 @@ def test10(self): "test open and read of a simple relative file" - from reportlab.lib.utils import open_and_read, getStringIO - b = getStringIO(_rel_open_and_read('../docs/images/Edit_Prefs.gif')) + from reportlab.lib.utils import open_and_read, getBytesIO + b = getBytesIO(_rel_open_and_read('../docs/images/Edit_Prefs.gif')) b = open_and_read(b) diff -r 29c11b905751 -r 99aa837b6703 tests/test_rl_accel.py --- a/tests/test_rl_accel.py Sun Feb 17 12:13:56 2013 +0000 +++ b/tests/test_rl_accel.py Tue Apr 30 14:28:14 2013 +0100 @@ -119,7 +119,7 @@ def __init__(self,**kwd): self.__dict__.update(kwd) def __str__(self): - V=['%s=%r' % v for v in list(self.__dict__.items())] + V=['%s=%r' % v for v in self.__dict__.items()] V.sort() return 'ABag(%s)' % ','.join(V) diff -r 29c11b905751 -r 99aa837b6703 tools/docco/examples.py --- a/tools/docco/examples.py Sun Feb 17 12:13:56 2013 +0000 +++ b/tools/docco/examples.py Tue Apr 30 14:28:14 2013 +0100 @@ -856,7 +856,7 @@ Dprime = {} from types import StringType from string import strip -for (a,b) in list(g.items()): +for a,b in g.items(): if a[:4]=="test" and type(b) is StringType: #print 'for', a #print b diff -r 29c11b905751 -r 99aa837b6703 tools/docco/graphdocpy.py --- a/tools/docco/graphdocpy.py Sun Feb 17 12:13:56 2013 +0000 +++ b/tools/docco/graphdocpy.py Tue Apr 30 14:28:14 2013 +0100 @@ -26,9 +26,9 @@ from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.enums import TA_CENTER, TA_LEFT -from reportlab.lib.utils import getStringIO +from reportlab.lib.utils import getBytesIO #from StringIO import StringIO -#getStringIO=StringIO +#getBytesIO=StringIO from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.pdfgen import canvas from reportlab.platypus.flowables import Flowable, Spacer @@ -470,7 +470,7 @@ for key in keys: value = props[key] - f = getStringIO() + f = getBytesIO() pprint.pprint(value, f) value = f.getvalue()[:-1] valueLines = string.split(value, '\n') @@ -654,7 +654,7 @@ value = props[key] # Method 3 - f = getStringIO() + f = getBytesIO() pprint.pprint(value, f) value = f.getvalue()[:-1] valueLines = string.split(value, '\n') diff -r 29c11b905751 -r 99aa837b6703 tools/docco/rl_doc_utils.py --- a/tools/docco/rl_doc_utils.py Sun Feb 17 12:13:56 2013 +0000 +++ b/tools/docco/rl_doc_utils.py Tue Apr 30 14:28:14 2013 +0100 @@ -308,7 +308,7 @@ def getStyleText(self, style): """Converts style to preformatted block of text""" lines = [] - for (key, value) in list(style.__dict__.items()): + for key, value in style.__dict__.items(): lines.append('%s = %s' % (key, value)) lines.sort() return string.join(lines, '\n') @@ -346,7 +346,7 @@ def getStyleText(self, style): """Converts style to preformatted block of text""" lines = [] - for (key, value) in list(style.__dict__.items()): + for key, value in style.__dict__.items(): if key not in ('name','parent'): lines.append('%s = %s' % (key, value)) return string.join(lines, '\n') diff -r 29c11b905751 -r 99aa837b6703 tools/docco/t_parse.py --- a/tools/docco/t_parse.py Sun Feb 17 12:13:56 2013 +0000 +++ b/tools/docco/t_parse.py Tue Apr 30 14:28:14 2013 +0100 @@ -113,7 +113,7 @@ raise ValueError("Marks must be single characters: "+repr(mark)) # compile the regular expressions if needed self.marker_dict = marker_dict = {} - for (mark, rgex) in list(marker_to_regex_dict.items()): + for mark, rgex in marker_to_regex_dict.items(): if type(rgex) == StringType: rgex = re.compile(rgex) marker_dict[mark] = rgex diff -r 29c11b905751 -r 99aa837b6703 tools/pythonpoint/demos/examples.py --- a/tools/pythonpoint/demos/examples.py Sun Feb 17 12:13:56 2013 +0000 +++ b/tools/pythonpoint/demos/examples.py Tue Apr 30 14:28:14 2013 +0100 @@ -787,7 +787,7 @@ Dprime = {} from types import StringType from string import strip -for (a,b) in list(g.items()): +for a,b in g.items()): if a[:4]=="test" and type(b) is StringType: #print 'for', a #print b diff -r 29c11b905751 -r 99aa837b6703 tools/pythonpoint/pythonpoint.py --- a/tools/pythonpoint/pythonpoint.py Sun Feb 17 12:13:56 2013 +0000 +++ b/tools/pythonpoint/pythonpoint.py Tue Apr 30 14:28:14 2013 +0100 @@ -77,7 +77,7 @@ from reportlab.lib import styles from reportlab.lib import colors from reportlab.lib.units import cm -from reportlab.lib.utils import getStringIO +from reportlab.lib.utils import getBytesIO from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY from reportlab.pdfbase import pdfmetrics from reportlab.pdfgen import canvas @@ -352,7 +352,7 @@ if self.verbose: print(filename) #canv = canvas.Canvas(filename, pagesize = pageSize) - outfile = getStringIO() + outfile = getBytesIO() if self.notes: #translate the page from landscape to portrait pageSize= pageSize[1], pageSize[0] @@ -403,7 +403,7 @@ if self.sourceFilename : filename = os.path.splitext(self.sourceFilename)[0] + '.pdf' - outfile = getStringIO() + outfile = getBytesIO() doc = SimpleDocTemplate(outfile, pagesize=rl_config.defaultPageSize, showBoundary=0) doc.leftMargin = 1*cm doc.rightMargin = 1*cm diff -r 29c11b905751 -r 99aa837b6703 tools/pythonpoint/stdparser.py --- a/tools/pythonpoint/stdparser.py Sun Feb 17 12:13:56 2013 +0000 +++ b/tools/pythonpoint/stdparser.py Tue Apr 30 14:28:14 2013 +0100 @@ -786,7 +786,7 @@ def unknown_starttag(self, tag, attrs): if self._curPara: echo = '<%s' % tag - for (key, value) in list(attrs.items()): + for key, value in attrs.items(): echo = echo + ' %s="%s"' % (key, value) echo = echo + '>' self._curPara.rawtext = self._curPara.rawtext + echo