Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-reportlab for openSUSE:Factory checked in at 2021-01-15 19:44:31 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-reportlab (Old) and /work/SRC/openSUSE:Factory/.python-reportlab.new.28504 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-reportlab" Fri Jan 15 19:44:31 2021 rev:29 rq:862304 version:3.5.59 Changes: -------- --- /work/SRC/openSUSE:Factory/python-reportlab/python-reportlab.changes 2020-12-12 20:32:07.253836799 +0100 +++ /work/SRC/openSUSE:Factory/.python-reportlab.new.28504/python-reportlab.changes 2021-01-15 19:44:47.405893354 +0100 @@ -1,0 +2,17 @@ +Mon Jan 11 12:31:13 UTC 2021 - Antonio Larrosa <alarr...@suse.com> + +- Update to 3.5.59 + * Allow variant corners in Canvas.roundRect + * Allow tables to have rounded corners +- Update to 3.5.58 + * added ddfStyle to Label + * allowed for embedded(and ordinary)Hyphenation to pre-empt splitting when embeddedHyphenation>=2 + * fix extension escapePDF so it can handle unicode + * fix poundsign in Ean5BarcodeWidget + * Table can use __styledWrap__ for sizing + * test fixes so 3.9 and 2.7 produce same pdf +- Update to 3.5.57 + * added .github action wheel.yml + * micro change to userguide doc + +------------------------------------------------------------------- Old: ---- reportlab-3.5.56.tar.gz New: ---- reportlab-3.5.59.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-reportlab.spec ++++++ --- /var/tmp/diff_new_pack.vq6OvA/_old 2021-01-15 19:44:48.217894562 +0100 +++ /var/tmp/diff_new_pack.vq6OvA/_new 2021-01-15 19:44:48.221894568 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-reportlab # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define oldpython python Name: python-reportlab -Version: 3.5.56 +Version: 3.5.59 Release: 0 Summary: The Reportlab Toolkit License: BSD-3-Clause ++++++ reportlab-3.5.56.tar.gz -> reportlab-3.5.59.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/CHANGES.md new/reportlab-3.5.59/CHANGES.md --- old/reportlab-3.5.56/CHANGES.md 2020-12-01 17:29:04.000000000 +0100 +++ new/reportlab-3.5.59/CHANGES.md 2021-01-01 19:09:10.000000000 +0100 @@ -11,6 +11,25 @@ The contributors lists are in no order and apologies to those accidentally not mentioned. If we missed you, please let us know! +CHANGES 3.5.58 01/01/2021 +--------------------------- + * Allow variant corners in Canvas.roundRect + * Allow tables to have rounded corners + +CHANGES 3.5.57 27/12/2020 +--------------------------- + * added ddfStyle to Label + * allowed for embedded(and ordinary)Hyphenation to pre-empt splitting when embeddedHyphenation>=2 + * fix extension escapePDF so it can handle unicode + * fix poundsign in Ean5BarcodeWidget + * Table can use __styledWrap__ for sizing + * test fixes so 3.9 and 2.7 produce same pdf + +CHANGES 3.5.56 10/12/2020 +--------------------------- + * added .github action wheel.yml + * micro change to userguide doc + RELEASE 3.5.56 01/12/2020 --------------------------- * micro changes for Big Sur in C extensions diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/PKG-INFO new/reportlab-3.5.59/PKG-INFO --- old/reportlab-3.5.56/PKG-INFO 2020-12-01 17:29:31.000000000 +0100 +++ new/reportlab-3.5.59/PKG-INFO 2021-01-04 15:52:21.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: reportlab -Version: 3.5.56 +Version: 3.5.59 Summary: The Reportlab Toolkit Home-page: http://www.reportlab.com/ Author: Andy Robinson, Robin Becker, the ReportLab team and the community diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/docs/userguide/ch5_paragraphs.py new/reportlab-3.5.59/docs/userguide/ch5_paragraphs.py --- old/reportlab-3.5.56/docs/userguide/ch5_paragraphs.py 2020-12-01 17:29:04.000000000 +0100 +++ new/reportlab-3.5.59/docs/userguide/ch5_paragraphs.py 2020-12-27 12:44:36.000000000 +0100 @@ -345,7 +345,7 @@ This <img/> <img src="../images/testimg.gif" width="10"/> has width <b>10</b>.<br/><br/> </para>""","Inline images") disc("""The $src$ attribute can refer to a remote location eg $src="https://www.reportlab.com/images/logo.gif"$. By default we set $rl_config.trustedShemes$ to $['https','http', 'file', 'data', 'ftp']$ and -$rl_config.trustedHosts=None$ the latter meaning no-restriction. You can modify these variables using one of the override files eg $reportlab_settings.py$ or $~/.reportlab_settings$. Or as comma seprated strings in the +$rl_config.trustedHosts=None$ the latter meaning no-restriction. You can modify these variables using one of the override files eg $reportlab_settings.py$ or $~/.reportlab_settings$. Or as comma separated strings in the environment variables $RL_trustedSchemes$ & $RL_trustedHosts$. Note that the $trustedHosts$ values may contain <b>glob</b> wild cars so <i>*.reportlab.com</i> will match the obvious domains. <br/><span color="red"><b>*NB*</b></span> use of <i>trustedHosts</i> and or <i>trustedSchemes</i> may not control behaviour & actions when $URI$ patterns are detected by the viewer application.""") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/docs/userguide/ch6_tables.py new/reportlab-3.5.59/docs/userguide/ch6_tables.py --- old/reportlab-3.5.56/docs/userguide/ch6_tables.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/docs/userguide/ch6_tables.py 2021-01-04 15:51:54.000000000 +0100 @@ -57,7 +57,7 @@ disc("""These are the main methods which are of interest to the client programmer.""") heading4("""$Table(data, colWidths=None, rowHeights=None, style=None, splitByRow=1, -repeatRows=0, repeatCols=0, rowSplitRange=None, spaceBefore=None, spaceAfter=None)$""") +repeatRows=0, repeatCols=0, rowSplitRange=None, spaceBefore=None, spaceAfter=None, cornerRadii=None)$""") disc("""The $data$ argument is a sequence of sequences of cell values each of which should be convertible to a string value using the $str$ function or should be a Flowable instance (such as a $Paragraph$) or a list (or tuple) of such instances. @@ -91,8 +91,11 @@ that should be repeated when the $Table$ is asked to split itself. If it is a tuple it should specify which of the leading rows should be repeated; this allows for cases where the first appearance of the table hsa more leading rows than later split parts. The $repeatCols$ argument is currently ignored as a $Table$ cannot be split by column.""") -disc("""The $spaceBefore$ & $spaceAfter$ arguments may be used to put extra space before or after the table when renedered in a $platypus$ story.""") disc("""The $rowSplitRange$ argument may be used to control the splitting of the table to a subset of its rows; that can be to prevent splitting too close to the beginning or end of the table.""") +disc("""The $spaceBefore$ & $spaceAfter$ arguments may be used to put extra space before or after the table when renedered in a $platypus$ story.""") +disc("""The $style$ argument can be an initial style for the table.""") +disc("""The $cornerRadii$ argument can be a list of the top left, top right, bottom left and bottom right radii. +A positive non-zero radius indicates that the corner should be rounded. This argument will override any $ROUNDEDCORNERS$ command in the argument $style$ list (ie it has pririty).""") heading4('$Table.setStyle(tblStyle)$') disc(""" This method applies a particular instance of class $TableStyle$ (discussed below) @@ -340,6 +343,17 @@ """) disc("""demands that the cells in columns $sc$ - $ec$ and rows $sr$ - $er$ may not be split.""") +eg("") +eg("") +disc("""To control $Table$ corner rounding the $ROUNDEDCORNERS$ command may be used +The style specification +""") +eg(""" +ROUNDEDCORNERS, [tl, tr, bl, br] +""") +disc("""specifies the radii of the top left, top right, bottom left and bottom right. A value of $0$ indicates a square corner. replace the whole array by $None$ to turn off all rounding. +<br/>Borders at a rounded corner are curved by an octant.""") + heading3("""Special $TableStyle$ Indeces""") disc("""In any style command the first row index may be set to one of the special strings $'splitlast'$ or $'splitfirst'$ to indicate that the style should be used only for the last row of diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/src/reportlab/__init__.py new/reportlab-3.5.59/src/reportlab/__init__.py --- old/reportlab-3.5.56/src/reportlab/__init__.py 2020-12-01 17:29:04.000000000 +0100 +++ new/reportlab-3.5.59/src/reportlab/__init__.py 2021-01-04 15:51:54.000000000 +0100 @@ -1,9 +1,9 @@ #Copyright ReportLab Europe Ltd. 2000-2018 #see license.txt for license details __doc__="""The Reportlab PDF generation library.""" -Version = "3.5.56" +Version = "3.5.59" __version__=Version -__date__='20201201' +__date__='20210104' import sys, os diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/src/reportlab/graphics/barcode/eanbc.py new/reportlab-3.5.59/src/reportlab/graphics/barcode/eanbc.py --- old/reportlab-3.5.56/src/reportlab/graphics/barcode/eanbc.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/src/reportlab/graphics/barcode/eanbc.py 2020-12-27 12:44:36.000000000 +0100 @@ -461,7 +461,7 @@ if s[0] in '3456': price = '$' elif s[0] in '01': - price = '\xc2\xa3' + price = asNative(b'\xc2\xa3') if price is None: return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/src/reportlab/graphics/charts/textlabels.py new/reportlab-3.5.59/src/reportlab/graphics/charts/textlabels.py --- old/reportlab-3.5.56/src/reportlab/graphics/charts/textlabels.py 2020-01-22 15:40:54.000000000 +0100 +++ new/reportlab-3.5.59/src/reportlab/graphics/charts/textlabels.py 2020-12-27 12:44:36.000000000 +0100 @@ -16,7 +16,7 @@ from reportlab.graphics.widgetbase import Widget, PropHolder from reportlab.graphics.shapes import _baseGFontName, DirectDraw from reportlab.platypus import XPreformatted, Paragraph, Flowable -from reportlab.lib.styles import ParagraphStyle +from reportlab.lib.styles import ParagraphStyle, PropertySet from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER _ta2al = dict(start=TA_LEFT,end=TA_RIGHT,middle=TA_CENTER) @@ -153,6 +153,7 @@ customDrawChanger = AttrMapValue(isNoneOrCallable,desc="An instance of CustomDrawChanger to modify the behavior at draw time", _advancedUsage=1), ddf = AttrMapValue(NoneOr(isSubclassOf(DirectDraw),'NoneOrDirectDraw'),desc="A DirectDrawFlowable instance", _advancedUsage=1), ddfKlass = AttrMapValue(NoneOr(isSubclassOf(Flowable),'NoneOrDirectDraw'),desc="A DirectDrawFlowable instance", _advancedUsage=1), + ddfStyle = AttrMapValue(NoneOr(isSubclassOf(PropertySet)),desc="A style for a ddfKlass or None", _advancedUsage=1), ) def __init__(self,**kw): @@ -187,6 +188,7 @@ useAscentDescent = False, ddf = DirectDrawFlowable, ddfKlass = None, + ddfStyle = None, ) def setText(self, text): @@ -288,12 +290,14 @@ else: if self.ddf is None: raise RuntimeError('DirectDrawFlowable class is not available you need the rlextra package as well as reportlab') - sty = self._style = ParagraphStyle('xlabel-generated', + sty = dict( + name='xlabel-generated', fontName=self.fontName, fontSize=self.fontSize, fillColor=self.fillColor, strokeColor=self.strokeColor, ) + sty = self._style = (ddfStyle.clone if self.ddfStyle else ParagraphStyle)(**sty) self._getBaseLineRatio() if self.useAscentDescent: sty.autoLeading = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/src/reportlab/lib/utils.py new/reportlab-3.5.59/src/reportlab/lib/utils.py --- old/reportlab-3.5.56/src/reportlab/lib/utils.py 2020-10-29 13:35:05.000000000 +0100 +++ new/reportlab-3.5.59/src/reportlab/lib/utils.py 2021-01-04 15:51:54.000000000 +0100 @@ -16,6 +16,16 @@ from reportlab.lib.rltempfile import get_rl_tempfile, get_rl_tempdir, _rl_getuid from . rl_safe_eval import rl_safe_exec, rl_safe_eval, safer_globals +class __UNSET__(object): + @staticmethod + def __bool__(): + return False + @staticmethod + def __str__(): + return '__UNSET__' + __repr__ = __str__ +__UNSET__ = __UNSET__() + try: import cPickle as pickle except ImportError: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/src/reportlab/pdfgen/canvas.py new/reportlab-3.5.59/src/reportlab/pdfgen/canvas.py --- old/reportlab-3.5.56/src/reportlab/pdfgen/canvas.py 2020-10-02 17:51:34.000000000 +0200 +++ new/reportlab-3.5.59/src/reportlab/pdfgen/canvas.py 2020-12-27 12:44:36.000000000 +0100 @@ -23,7 +23,7 @@ from reportlab.pdfgen import pdfgeom, pathobject from reportlab.pdfgen.textobject import PDFTextObject, _PDFColorSetter from reportlab.lib.colors import black, _chooseEnforceColorSpace, Color, CMYKColor, toColor -from reportlab.lib.utils import import_zlib, ImageReader, isSeq, isStr, isUnicode, _digester +from reportlab.lib.utils import import_zlib, ImageReader, isSeq, isStr, isUnicode, _digester, asUnicode from reportlab.lib.rl_accel import fp_str, escapePDF from reportlab.lib.boxstuff import aspectRatioFix @@ -1595,8 +1595,7 @@ def drawString(self, x, y, text, mode=None, charSpace=0, direction=None, wordSpace=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') + text = asUnicode(text) #we could inline this for speed if needed t = self.beginText(x, y, direction=direction) if mode is not None: t.setTextRenderMode(mode) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/src/reportlab/pdfgen/pathobject.py new/reportlab-3.5.59/src/reportlab/pdfgen/pathobject.py --- old/reportlab-3.5.56/src/reportlab/pdfgen/pathobject.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/src/reportlab/pdfgen/pathobject.py 2021-01-01 19:09:10.000000000 +0100 @@ -25,7 +25,7 @@ Path objects are probably not long, so we pack onto one line - the code argument allows a canvas to get the operatiosn appended directly so + the code argument allows a canvas to get the operations appended directly so avoiding the final getCode """ def __init__(self,code=None): @@ -95,31 +95,43 @@ #use a precomputed set of factors for the bezier approximation #to a circle. There are six relevant points on the x axis and y axis. #sketch them and it should all make sense! - t = 0.4472 * radius - - x0 = x - x1 = x0 + t - x2 = x0 + radius - x3 = x0 + width - radius - x4 = x0 + width - t - x5 = x0 + width - - y0 = y - y1 = y0 + t - y2 = y0 + radius - y3 = y0 + height - radius - y4 = y0 + height - t - y5 = y0 + height - - self.moveTo(x2, y0) - self.lineTo(x3, y0) #bottom row - self.curveTo(x4, y0, x5, y1, x5, y2) #bottom right - self.lineTo(x5, y3) #right edge - self.curveTo(x5, y4, x4, y5, x3, y5) #top right - self.lineTo(x2, y5) #top row - self.curveTo(x1, y5, x0, y4, x0, y3) #top left - self.lineTo(x0, y2) #left edge - self.curveTo(x0, y1, x1, y0, x2, y0) #bottom left + m = 0.4472 #radius multiplier + xhi = x,x+width + xlo, xhi = min(xhi), max(xhi) + yhi = y,y+height + ylo, yhi = min(yhi), max(yhi) + if isinstance(radius,(list,tuple)): + r = [max(0,r) for r in radius] + if len(r)<4: r += (4-len(r))*[0] + self.moveTo(xlo + r[2], ylo) #start at bottom left + self.lineTo(xhi - r[3], ylo) #bottom row + if r[3]>0: + t = m*r[3] + self.curveTo(xhi - t, ylo, xhi, ylo + t, xhi, ylo + r[3]) #bottom right + self.lineTo(xhi, yhi - r[1]) #right edge + if r[1]>0: + t = m*r[1] + self.curveTo(xhi, yhi - t, xhi - t, yhi, xhi - r[1], yhi) #top right + self.lineTo(xlo + r[0], yhi) #top row + if r[0]>0: + t = m*r[0] + self.curveTo(xlo + t, yhi, xlo, yhi - t, xlo, yhi - r[0]) #top left + self.lineTo(xlo, ylo + r[2]) #left edge + if r[2]>0: + t = m*r[2] + self.curveTo(xlo, ylo + t, xlo + t, ylo, xlo + r[2], ylo) #bottom left + # 4 radii top left top right bittom left bottom right + else: + t = m * radius + self.moveTo(xlo + radius, ylo) + self.lineTo(xhi - radius, ylo) #bottom row + self.curveTo(xhi - t, ylo, xhi, ylo + t, xhi, ylo + radius) #bottom right + self.lineTo(xhi, yhi - radius) #right edge + self.curveTo(xhi, yhi - t, xhi - t, yhi, xhi - radius, yhi) #top right + self.lineTo(xlo + radius, yhi) #top row + self.curveTo(xlo + t, yhi, xlo, yhi - t, xlo, yhi - radius) #top left + self.lineTo(xlo, ylo + radius) #left edge + self.curveTo(xlo, ylo + t, xlo + t, ylo, xlo + radius, ylo) #bottom left self.close() def close(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/src/reportlab/platypus/paragraph.py new/reportlab-3.5.59/src/reportlab/platypus/paragraph.py --- old/reportlab-3.5.56/src/reportlab/platypus/paragraph.py 2020-07-20 09:39:52.000000000 +0200 +++ new/reportlab-3.5.59/src/reportlab/platypus/paragraph.py 2020-12-27 12:44:36.000000000 +0100 @@ -2014,6 +2014,7 @@ hyphenator = None uriWasteReduce = style.uriWasteReduce embeddedHyphenation = style.embeddedHyphenation + hyphenation2 = embeddedHyphenation>1 spaceShrinkage = style.spaceShrinkage splitLongWords = style.splitLongWords attemptHyphenation = hyphenator or uriWasteReduce or embeddedHyphenation @@ -2078,6 +2079,17 @@ self._hyphenations += 1 forcedSplit = 1 continue + elif hyphenation2 and len(cLine): + hsw = word.__shysplit__( + fontName, fontSize, + 0 + hyw - 1e-8, + maxWidth, + encoding = self.encoding, + ) + if hsw: + words[0:0] = [word] + forcedSplit = 1 + word = None elif attemptHyphenation: hyOk = not getattr(f,'nobr',False) hsw = _hyphenateWord(hyphenator if hyOk else None, @@ -2089,7 +2101,16 @@ self._hyphenations += 1 forcedSplit = 1 continue - if splitLongWords and not isinstance(word,_SplitWord): + elif hyphenation2 and len(cLine): + hsw = _hyphenateWord(hyphenator if hyOk else None, + fontName, fontSize, word, wordWidth, wordWidth, maxWidth, + uriWasteReduce if hyOk else False, + embeddedHyphenation and hyOk, hymwl) + if hsw: + words[0:0] = [word] + forcedSplit = 1 + word = None + if splitLongWords and not (isinstance(word,_SplitWord) or forcedSplit): nmw = min(lineno,maxlineno) if wordWidth>max(maxWidths[nmw:nmw+1]): #a long word @@ -2099,7 +2120,7 @@ continue if newWidth <= (maxWidth+spaceShrink) or not len(cLine) or forcedSplit: # fit one more on this line - cLine.append(word) + if word: cLine.append(word) if forcedSplit: forcedSplit = 0 if newWidth > self._width_max: self._width_max = newWidth @@ -2170,6 +2191,13 @@ FW.pop(-1) #remove this as we are doing this one again self._hyphenations += 1 continue + elif hyphenation2 and len(FW)>1: #only if we are not the first word on the line + hsw = w.shyphenate(wordWidth, maxWidth) + if hsw: + _words[0:0] = [_InjectedFrag([0,(f.clone(_fkind=_FK_BREAK,text=''),'')]),w] + FW.pop(-1) #remove this as we are doing this one again + continue + #else: try to split an overlong word elif attemptHyphenation: hyOk = not getattr(f,'nobr',False) hsw = _hyphenateFragWord(hyphenator if hyOk else None, @@ -2182,6 +2210,16 @@ FW.pop(-1) #remove this as we are doing this one again self._hyphenations += 1 continue + elif hyphenation2 and len(FW)>1: + hsw = _hyphenateFragWord(hyphenator if hyOk else None, + w,wordWidth,maxWidth, + uriWasteReduce if hyOk else False, + embeddedHyphenation and hyOk, hymwl) + if hsw: + _words[0:0] = [_InjectedFrag([0,(f.clone(_fkind=_FK_BREAK,text=''),'')]),w] + FW.pop(-1) #remove this as we are doing this one again + continue + #else: try to split an overlong word if splitLongWords and not isinstance(w,_SplitFrag): nmw = min(lineno,maxlineno) if wordWidth>max(maxWidths[nmw:nmw+1]): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/src/reportlab/platypus/tables.py new/reportlab-3.5.59/src/reportlab/platypus/tables.py --- old/reportlab-3.5.56/src/reportlab/platypus/tables.py 2020-08-07 09:31:22.000000000 +0200 +++ new/reportlab-3.5.59/src/reportlab/platypus/tables.py 2021-01-04 15:51:54.000000000 +0100 @@ -27,12 +27,14 @@ from reportlab import rl_config, xrange, ascii from reportlab.lib.styles import PropertySet, ParagraphStyle, _baseFontName from reportlab.lib import colors -from reportlab.lib.utils import annotateException, IdentStr, flatten, isStr, asNative, strTypes +from reportlab.lib.utils import annotateException, IdentStr, flatten, isStr, asNative, strTypes, __UNSET__ +from reportlab.lib.validators import isListOfNumbersOrNone from reportlab.lib.rl_accel import fp_str from reportlab.lib.abag import ABag as CellFrame from reportlab.pdfbase.pdfmetrics import stringWidth from reportlab.platypus.doctemplate import Indenter, NullActionFlowable from reportlab.platypus.flowables import LIIndenter +from collections import namedtuple LINECAPS={None: None, 'butt':0,'round':1,'projecting':2,'squared':2} LINEJOINS={None: None, 'miter':0, 'mitre':0, 'round':1,'bevel':2} @@ -138,6 +140,41 @@ R[j] = v return R +def _calcBezierPoints(P, kind): + '''calculate all or half of a bezier curve + kind==0 all, 1=first half else second half''' + if kind==0: + return P + else: + Q0 = (0.5*(P[0][0]+P[1][0]),0.5*(P[0][1]+P[1][1])) + Q1 = (0.5*(P[1][0]+P[2][0]),0.5*(P[1][1]+P[2][1])) + Q2 = (0.5*(P[2][0]+P[3][0]),0.5*(P[2][1]+P[3][1])) + R0 = (0.5*(Q0[0]+Q1[0]),0.5*(Q0[1]+Q1[1])) + R1 = (0.5*(Q1[0]+Q2[0]),0.5*(Q1[1]+Q2[1])) + S0 = (0.5*(R0[0]+R1[0]),0.5*(R0[1]+R1[1])) + return [P[0],Q0,R0,S0] if kind==1 else [S0,R1,Q2,P[3]] + +def _quadrantDef(xpos, ypos, corner, r, kind=0, direction='left-right', m=0.4472): + t = m*r + if xpos=='right' and ypos=='bottom': #bottom right + xhi,ylo = corner + P = [(xhi - r, ylo),(xhi-t, ylo), (xhi, ylo + t), (xhi, ylo + r)] + elif xpos=='right' and ypos=='top': #top right + xhi,yhi = corner + P = [(xhi, yhi - r),(xhi, yhi - t), (xhi - t, yhi), (xhi - r, yhi)] + elif xpos=='left' and ypos=='top': #top left + xlo,yhi = corner + P = [(xlo + r, yhi),(xlo + t, yhi), (xlo, yhi - t), (xlo, yhi - r)] + elif xpos=='left' and ypos=='bottom': #bottom left + xlo,ylo = corner + P = [(xlo, ylo + r),(xlo, ylo + t), (xlo + t, ylo), (xlo + r, ylo)] + else: + raise ValueError('Unknown quadrant position %s' % repr((xpos,ypos))) + if direction=='left-right' and P[0][0]>P[-1][0] or direction=='bottom-top' and P[0][1]>P[-1][1]: + P.reverse() + P = _calcBezierPoints(P, kind) + return P + def _hLine(canvLine, scp, ecp, y, hBlocks, FUZZ=rl_config._FUZZ): ''' Draw horizontal lines; do not draw through regions specified in hBlocks @@ -208,11 +245,17 @@ class _ExpandedCellTuple(tuple): pass + +RoundingRectDef = namedtuple('RoundingRectDefs','x0 y0 w h x1 y1 ar SL') +RoundingRectLine = namedtuple('RoundingRectLine','xs ys xe ye weight color cap dash join') + class Table(Flowable): def __init__(self, data, colWidths=None, rowHeights=None, style=None, repeatRows=0, repeatCols=0, splitByRow=1, emptyTableAction=None, ident=None, hAlign=None,vAlign=None, normalizedData=0, cellStyles=None, rowSplitRange=None, - spaceBefore=None,spaceAfter=None, longTableOptimize=None, minRowHeights=None): + spaceBefore=None,spaceAfter=None, longTableOptimize=None, minRowHeights=None, + cornerRadii=__UNSET__, #or [topLeft, topRight, bottomLeft bottomRight] + ): self.ident = ident self.hAlign = hAlign or 'CENTER' self.vAlign = vAlign or 'MIDDLE' @@ -297,6 +340,9 @@ if style: self.setStyle(style) + if cornerRadii is not __UNSET__: #instance argument overrides + self._setCornerRadii(cornerRadii) + self._rowSplitRange = rowSplitRange if spaceBefore is not None: self.spaceBefore = spaceBefore @@ -311,6 +357,7 @@ minRowHeights = minRowHeights+(nrows-lmrh)*minRowHeights.__class__((0,)) self._minRowHeights = minRowHeights + def __repr__(self): "incomplete, but better than nothing" r = getattr(self,'_rowHeights','[unknown]') @@ -507,9 +554,15 @@ if ew is None: return None w = max(w,ew) return w - elif isinstance(v,Flowable) and v._fixedWidth: - if hasattr(v, 'width') and isinstance(v.width,(int,float)): return v.width - if hasattr(v, 'drawWidth') and isinstance(v.drawWidth,(int,float)): return v.drawWidth + elif isinstance(v,Flowable): + if v._fixedWidth: + if hasattr(v, 'width') and isinstance(v.width,(int,float)): return v.width + if hasattr(v, 'drawWidth') and isinstance(v.drawWidth,(int,float)): return v.drawWidth + if hasattr(v,'__styledWrap__'): #very experimental + try: + return getattr(v,'__styledWrap__')(s)[0] + except: + pass # Even if something is fixedWidth, the attribute to check is not # necessarily consistent (cf. Image.drawWidth). Therefore, we'll # be extra-careful and fall through to this code if necessary. @@ -715,7 +768,7 @@ and assign some best-guess values.""" W = list(self._argW) # _calc_pc(self._argW,availWidth) - verbose = 0 + #verbose = 1 totalDefined = 0.0 percentDefined = 0 percentTotal = 0 @@ -733,8 +786,7 @@ else: assert isinstance(w,(int,float)) totalDefined = totalDefined + w - if verbose: print('prelim width calculation. %d columns, %d undefined width, %0.2f units remain' % ( - self._ncols, numberUndefined, availWidth - totalDefined)) + #if verbose: print('prelim width calculation. %d columns, %d undefined width, %0.2f units remain' % (self._ncols, numberUndefined, availWidth - totalDefined)) #check columnwise in each None column to see if they are sizable. given = [] @@ -753,6 +805,7 @@ style = self._cellStyles[rowNo][colNo] new = elementWidth(value,style) or 0 new += style.leftPadding+style.rightPadding + #if verbose: print('[%d,%d] new=%r-->%r' % (rowNo,colNo,new - style.leftPadding+style.rightPadding, new)) final = max(final, new) siz = siz and self._canGetWidth(value) # irrelevant now? if siz: @@ -765,21 +818,22 @@ given.append(colNo) if len(given) == self._ncols: return - if verbose: print('predefined width: ',given) - if verbose: print('uncomputable width: ',unsizeable) - if verbose: print('computable width: ',sizeable) + #if verbose: print('predefined width: ',given) + #if verbose: print('uncomputable width: ',unsizeable) + #if verbose: print('computable width: ',sizeable) + #if verbose: print('minimums=%r' % (list(sorted(list(minimums.items()))),)) # how much width is left: remaining = availWidth - (totalMinimum + totalDefined) if remaining > 0: # we have some room left; fill it. - definedPercentage = (totalDefined/availWidth)*100 + definedPercentage = (totalDefined/float(availWidth))*100 percentTotal += definedPercentage if numberUndefined and percentTotal < 100: undefined = numberGreedyUndefined or numberUndefined - defaultWeight = (100-percentTotal)/undefined + defaultWeight = (100-percentTotal)/float(undefined) percentTotal = 100 - defaultDesired = (defaultWeight/percentTotal)*availWidth + defaultDesired = (defaultWeight/float(percentTotal))*availWidth else: defaultWeight = defaultDesired = 1 # we now calculate how wide each column wanted to be, and then @@ -826,7 +880,7 @@ # column is (104/264), which, multiplied by the desired # width of 264, is 104: the amount assigned to the remaining # column. - proportion = effectiveRemaining/totalDesired + proportion = effectiveRemaining/float(totalDesired) # we sort the desired widths by difference between desired and # and minimum values, a value called "disappointment" in the # code. This means that the columns with a bigger @@ -841,7 +895,7 @@ totalDesired -= desired effectiveRemaining -= minimum if totalDesired: - proportion = effectiveRemaining/totalDesired + proportion = effectiveRemaining/float(totalDesired) else: finalSet.append((minimum, desired, colNo)) for minimum, desired, colNo in finalSet: @@ -851,7 +905,7 @@ else: for colNo, minimum in minimums.items(): W[colNo] = minimum - if verbose: print('new widths are:', W) + #if verbose: print('new widths are:', W) self._argW = self._colWidths = W return W @@ -1091,6 +1145,8 @@ assert len(cmd) == 10 self._linecmds.append(tuple(cmd)) + elif cmd[0]=="ROUNDEDCORNERS": + self._setCornerRadii(cmd[1]) else: (op, (sc, sr), (ec, er)), values = cmd[:3] , cmd[3:] if sr in ('splitfirst','splitlast'): @@ -1104,25 +1160,48 @@ def _drawLines(self): ccap, cdash, cjoin = None, None, None - self.canv.saveState() - for op, (sc,sr), (ec,er), weight, color, cap, dash, join, count, space in self._linecmds: - if isinstance(sr,strTypes) and sr.startswith('split'): continue - if cap!=None and ccap!=cap: - self.canv.setLineCap(cap) - ccap = cap - if dash is None or dash == []: - if cdash is not None: - self.canv.setDash() - cdash = None - elif dash != cdash: - self.canv.setDash(dash) - cdash = dash - if join is not None and cjoin!=join: - self.canv.setLineJoin(join) - cjoin = join - sc, ec, sr, er = self.normCellRange(sc,ec,sr,er) - getattr(self,_LineOpMap.get(op, '_drawUnknown' ))( (sc, sr), (ec, er), weight, color, count, space) - self.canv.restoreState() + canv = self.canv + canv.saveState() + + rrd = self._roundingRectDef + if rrd: #we are collection some lines + SL = rrd.SL + SL[:] = [] #empty saved lines list + ocanvline = canv.line + aSL = SL.append + def rcCanvLine(xs, ys, xe, ye): + if ( + (xs==xe and (xs>=rrd.x1 or xs<=rrd.x0)) #vertical line that needs to be saved + or + (ys==ye and (ys>=rrd.y1 or ys<=rrd.y0)) #horizontal line that needs to be saved + ): + aSL(RoundingRectLine(xs,ys,xe,ye,weight,color,cap,dash,join)) + else: + ocanvline(xs,ys,xe,ye) + canv.line = rcCanvLine + + try: + for op, (sc,sr), (ec,er), weight, color, cap, dash, join, count, space in self._linecmds: + if isinstance(sr,strTypes) and sr.startswith('split'): continue + if cap!=None and ccap!=cap: + canv.setLineCap(cap) + ccap = cap + if dash is None or dash == []: + if cdash is not None: + canv.setDash() + cdash = None + elif dash != cdash: + canv.setDash(dash) + cdash = dash + if join is not None and cjoin!=join: + canv.setLineJoin(join) + cjoin = join + sc, ec, sr, er = self.normCellRange(sc,ec,sr,er) + getattr(self,_LineOpMap.get(op, '_drawUnknown' ))( (sc, sr), (ec, er), weight, color, count, space) + finally: + if rrd: + canv.line = ocanvline + canv.restoreState() self._curcolor = None def _drawUnknown(self, start, end, weight, color, count, space): @@ -1306,12 +1385,14 @@ splitH = self._rowHeights else: splitH = self._argH + cornerRadii = getattr(self,'_cornerRadii',None) R0 = self.__class__( data[:n], colWidths=self._colWidths, rowHeights=splitH[:n], repeatRows=repeatRows, repeatCols=repeatCols, splitByRow=splitByRow, normalizedData=1, cellStyles=self._cellStyles[:n], ident=ident, spaceBefore=getattr(self,'spaceBefore',None), - longTableOptimize=lto) + longTableOptimize=lto, + cornerRadii=cornerRadii[:2] if cornerRadii else None) nrows = self._nrows ncols = self._ncols @@ -1392,6 +1473,7 @@ ident=ident, spaceAfter=getattr(self,'spaceAfter',None), longTableOptimize=lto, + cornerRadii = cornerRadii, ) R1._cr_1_1(n,nrows,repeatRows,A) #linecommands R1._cr_1_1(n,nrows,repeatRows,self._bkgrndcmds,_srflMode=True) @@ -1405,6 +1487,7 @@ ident=ident, spaceAfter=getattr(self,'spaceAfter',None), longTableOptimize=lto, + cornerRadii = ([0,0] + cornerRadii[2:]) if cornerRadii else None, ) R1._cr_1_0(n,A) R1._cr_1_0(n,self._bkgrndcmds,_srflMode=True) @@ -1463,7 +1546,117 @@ else: raise NotImplementedError + def _makeRoundedCornersClip(self, FUZZ=rl_config._FUZZ): + self._roundingRectDef = None + cornerRadii = getattr(self,'_cornerRadii',None) + if not cornerRadii or max(cornerRadii)<=FUZZ: return + nrows = self._nrows + ncols = self._ncols + ar = [min(self._rowHeights[i],self._colWidths[j],cornerRadii[k]) for + k,(i,j) in enumerate(( + (0,0), + (0,ncols-1), + (nrows-1,0), + (nrows-1, ncols-1), + ))] + rp = self._rowpositions + cp = self._colpositions + + x0 = cp[0] + y0 = rp[nrows] + x1 = cp[ncols] + y1 = rp[0] + w = x1 - x0 + h = y1 - y0 + self._roundingRectDef = RoundingRectDef(x0, y0, w, h, x1, y1, ar, []) + P = self.canv.beginPath() + P.roundRect(x0, y0, w, h, ar) + c = self.canv + c.addLiteral('%begin table rect clip') + c.clipPath(P,stroke=0) + c.addLiteral('%end table rect clip') + + def _restoreRoundingObscuredLines(self): + x0, y0, w, h, x1, y1, ar, SL = self._roundingRectDef + if not SL: return + canv = self.canv + canv.saveState() + ccap = cdash = cjoin = self._curweight = self._curcolor = None + line = canv.line + cornerRadii = self._cornerRadii + for (xs,ys,xe,ye,weight,color,cap,dash,join) in SL: + if cap!=None and ccap!=cap: + canv.setLineCap(cap) + ccap = cap + if dash is None or dash == []: + if cdash is not None: + canv.setDash() + cdash = None + elif dash != cdash: + canv.setDash(dash) + cdash = dash + if join is not None and cjoin!=join: + canv.setLineJoin(join) + cjoin = join + self._prepLine(weight, color) + if ys==ye: + #horizontal line + if ys>y1 or ys<y0: + line(xs,ys,xe,ye) #simple line that's outside the clip + continue + #which corners are involved + if ys==y0: + ypos = 'bottom' + r0 = ar[2] + r1 = ar[3] + else: #ys==y1 + ypos = 'top' + r0 = ar[0] + r1 = ar[1] + if xs>=x0+r0 and xe<=x1-r1: + line(xs,ys,xe,ye) #simple line with no rounding + continue + #we have some rounding so we must use a path + c0 = _quadrantDef('left',ypos,(xs,ys), r0, kind=2, direction='left-right') if xs<x0+r0 else None + c1 = _quadrantDef('right',ypos,(xe,ye), r1, kind=1, direction='left-right') if xe>x1-r1 else None + else: + #vertical line + if xs>x1 or xs<x0: + line(xs,ys,xe,ye) #simple line that's outside the clip + continue + #which corners are involved + if xs==x0: + xpos = 'left' + r0 = ar[2] + r1 = ar[0] + else: #xs==x1 + xpos = 'right' + r0 = ar[3] + r1 = ar[1] + if ys>=y0+r0 and ye<=y1-r1: + line(xs,ys,xe,ye) #simple line with no rounding + continue + #we have some rounding so we must use a path + c0 = _quadrantDef(xpos,'bottom',(xs,ys), r0, kind=2, direction='bottom-top') if ys<y0+r0 else None + c1 = _quadrantDef(xpos,'top',(xe,ye), r1, kind=1, direction='bottom-top') if ye>y1-r1 else None + P = canv.beginPath() + if c0: + P.moveTo(*c0[0]) + P.curveTo(c0[1][0],c0[1][1],c0[2][0],c0[2][1], c0[3][0],c0[3][1]) + else: + P.moveTo(xs,ys) + if not c1: + P.lineTo(xe,ye) + else: + P.lineTo(*c1[0]) + P.curveTo(c1[1][0],c1[1][1],c1[2][0],c1[2][1], c1[3][0],c1[3][1]) + canv.drawPath(P, stroke=1, fill=0) + canv.restoreState() + def draw(self): + c = self.canv + c.saveState() + self._makeRoundedCornersClip() self._curweight = self._curcolor = self._curcellstyle = None self._drawBkgrnd() if not self._spanCmds: @@ -1483,6 +1676,9 @@ cellstyle = self._cellStyles[rowNo][colNo] self._drawCell(cellval, cellstyle, (x, y), (width, height)) self._drawLines() + c.restoreState() + if self._roundingRectDef: + self._restoreRoundingObscuredLines() def _drawBkgrnd(self): nrows = self._nrows @@ -1649,6 +1845,12 @@ #external hyperlink self.canv.linkRect("", cellstyle.destination, Rect=(colpos, rowpos, colpos + colwidth, rowpos + rowheight), relative=1) + def _setCornerRadii(self, cornerRadii): + if isListOfNumbersOrNone(cornerRadii): + self._cornerRadii = None if not cornerRadii else list(cornerRadii) + (max(4-len(cornerRadii),0)*[0]) + else: + raise ValueError('cornerRadii should be None or a list/tuple of numeric radii') + _LineOpMap = { 'GRID':'_drawGrid', 'BOX':'_drawBox', 'OUTLINE':'_drawBox', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/src/reportlab.egg-info/PKG-INFO new/reportlab-3.5.59/src/reportlab.egg-info/PKG-INFO --- old/reportlab-3.5.56/src/reportlab.egg-info/PKG-INFO 2020-12-01 17:29:31.000000000 +0100 +++ new/reportlab-3.5.59/src/reportlab.egg-info/PKG-INFO 2021-01-04 15:52:21.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: reportlab -Version: 3.5.56 +Version: 3.5.59 Summary: The Reportlab Toolkit Home-page: http://www.reportlab.com/ Author: Andy Robinson, Robin Becker, the ReportLab team and the community diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/src/rl_addons/rl_accel/_rl_accel.c new/reportlab-3.5.59/src/rl_addons/rl_accel/_rl_accel.c --- old/reportlab-3.5.56/src/rl_addons/rl_accel/_rl_accel.c 2020-09-24 15:27:24.000000000 +0200 +++ new/reportlab-3.5.59/src/rl_addons/rl_accel/_rl_accel.c 2020-12-27 12:44:36.000000000 +0100 @@ -30,7 +30,7 @@ #ifndef min # define min(a,b) ((a)<(b)?(a):(b)) #endif -#define VERSION "0.75" +#define VERSION "0.80" #define MODULE "_rl_accel" struct module_state { @@ -435,11 +435,37 @@ static PyObject *escapePDF(PyObject *module, PyObject* args) { - unsigned char *text; - Py_ssize_t textLen; + unsigned char *inData; + Py_ssize_t length; + PyObject *retVal=NULL, *inObj, *_o1=NULL; - if (!PyArg_ParseTuple(args, "s#:escapePDF", &text, &textLen)) return NULL; - return _escapePDF(text,textLen); + if (!PyArg_ParseTuple(args, "O:escapePDF", &inObj)) return NULL; + if(PyUnicode_Check(inObj)){ + _o1 = PyUnicode_AsLatin1String(inObj); + if(!_o1){ + PyErr_SetString(PyExc_ValueError,"argument not decodable as latin1"); + ERROR_EXIT(); + } + inData = PyBytes_AsString(_o1); + inObj = _o1; + if(!inData){ + PyErr_SetString(PyExc_ValueError,"argument not converted to internal char string"); + ERROR_EXIT(); + } + } + else if(!PyBytes_Check(inObj)){ + PyErr_SetString(PyExc_ValueError,"argument should be " BYTESNAME " or latin1 decodable " STRNAME); + ERROR_EXIT(); + } + inData = PyBytes_AsString(inObj); + length = PyBytes_GET_SIZE(inObj); + retVal = _escapePDF(inData,length); +L_exit: + Py_XDECREF(_o1); + return retVal; +L_ERR: + ADD_TB(module,"excapePDF"); + goto L_exit; } static PyObject *sameFrag(PyObject *module, PyObject* args) @@ -1240,7 +1266,7 @@ PyDoc_STRVAR(__DOC__, "_rl_accel contains various accelerated utilities\n\ \n\ -\tescapePDF makes a string safe for PDF\n\ +\tescapePDF makes a unicode or latin1 bytes safe for PDF\n\ \n\ \tasciiBase85Encode does what is says\n\ \tasciiBase85Decode does what is says\n\ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_multibyte_jpn.py new/reportlab-3.5.59/tests/test_multibyte_jpn.py --- old/reportlab-3.5.56/tests/test_multibyte_jpn.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_multibyte_jpn.py 2020-12-27 12:44:36.000000000 +0100 @@ -56,14 +56,16 @@ # work in post Unicode world. pdfmetrics.registerFont(CIDFont('HeiseiMin-W3','90ms-RKSJ-V')) c.setFont('HeiseiMin-W3-90ms-RKSJ-V', 16) - c.drawString(450, 650, '\223\214\213\236 vertical Shift-JIS') - height = c.stringWidth('\223\214\213\236 vertical Shift-JIS', 'HeiseiMin-W3-90ms-RKSJ-V', 16) + s = u'\223\214\213\236 vertical Shift-JIS' #these are octal numbers + c.drawString(450, 650, s) + height = c.stringWidth(s, 'HeiseiMin-W3-90ms-RKSJ-V', 16) c.rect(450-8,650,16,-height) pdfmetrics.registerFont(CIDFont('HeiseiMin-W3','EUC-V')) c.setFont('HeiseiMin-W3-EUC-V', 16) - c.drawString(475, 650, '\xC5\xEC\xB5\xFE vertical EUC') - height = c.stringWidth('\xC5\xEC\xB5\xFE vertical EUC', 'HeiseiMin-W3-EUC-V', 16) + s = u'\xC5\xEC\xB5\xFE vertical EUC' + c.drawString(475, 650, s) + height = c.stringWidth(s, 'HeiseiMin-W3-EUC-V', 16) c.rect(475-8,650,16,-height) @@ -76,8 +78,9 @@ wordWrap="CJK" ) - gatwickText = '\xe3\x82\xac\xe3\x83\x88\xe3\x82\xa6\xe3\x82\xa3\xe3\x83\x83\xe3\x82\xaf\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xa8\xe9\x80\xa3\xe7\xb5\xa1\xe9\x80\x9a\xe8\xb7\xaf\xe3\x81\xa7\xe7\x9b\xb4\xe7\xb5\x90\xe3\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3\x82\x8b\xe5\x94\xaf\xe4\xb8\x80\xe3\x81\xae\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xa7\xe3\x81\x82\xe3\x82\x8b\xe5\xbd\x93\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xaf\xe3\x80\x81\xe8\xa1\x97\xe3\x81\xae\xe4\xb8\xad\xe5\xbf\x83\xe9\x83\xa8\xe3\x81\x8b\xe3\x82\x8930\xe5\x88\x86\xe3\x81\xae\xe5\xa0\xb4\xe6\x89\x80\xe3\x81\xab\xe3\x81\x94\xe3\x81\x96\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe5\x85\xa8\xe5\xae\xa2\xe5\xae\xa4\xe3\x81\xab\xe9\xab\x98\xe9\x80\x9f\xe3\x82\xa4\xe3\x83\xb3\xe3\x82\xbf\xe3\x83\xbc\xe3\x83\x8d\xe3\x83\x83\xe3\x83\x88\xe7\x92\xb0\xe5\xa2\x83\xe3\x82\x92\xe5\xae\x8c\xe5\x82\x99\xe3\x81\x97\xe3\x81\xa6\xe3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe3\x83\x95\xe3\x82\xa1 \xe3\x83\x9f\xe3\x83\xaa\xe3\x83\xbc\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xaf5\xe5\x90\x8d\xe6\xa7\x98\xe3\x81\xbe\xe3\x81\xa7\xe3\x81\x8a\xe6\xb3\x8a\xe3\x82\x8a\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe3\x81\xbe\xe3\x81\x9f\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xae\xe3\x81\x8a\xe5\xae\xa2\xe6\xa7\x98\xe3\x81\xaf\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xa9\xe3\x82\xa6\xe3\x83\xb3\xe3\x82\xb8\xe3\x82\x92\xe3\x81\x94\xe5\x88\xa9\xe7\x94\xa8\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe4\xba\x8b\xe5\x89\x8d\xe3\x81\xab\xe3\x81\x94\xe4\xba\x88\xe7\xb4\x84\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x82\x8b\xe3\x82\xbf\xe3\x82\xa4\xe3\x83\xa0\xe3\x83\x88\xe3\x82\xa5\xe3\x83\x95\xe3\x83\xa9\xe3\x82\xa4\xe3\x83\xbb\xe3\x83\x91 \xe3\x83\x83\xe3\x82\xb1\xe3\x83\xbc\xe3\x82\xb8\xe3\x81\xab\xe3\x81\xaf\xe3\x80\x81\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xae\xe9\xa7\x90\xe8\xbb\x8a\xe6\x96\x99\xe9\x87\x91\xe3\x81\x8c\xe5\x90\xab\xe3\x81\xbe\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82' - gatwickText2= '\xe3\x82\xac\xe3\x83\x88\xe3\x82\xa6\xe3\x82\xa3\xe3\x83\x83\xe3\x82\xaf<font color=red>\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xa8\xe9\x80\xa3\xe7\xb5\xa1\xe9\x80\x9a\xe8\xb7\xaf\xe3\x81\xa7\xe7\x9b\xb4\xe7\xb5\x90</font>\xe3\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3\x82\x8b\xe5\x94\xaf\xe4\xb8\x80\xe3\x81\xae\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xa7\xe3\x81\x82\xe3\x82\x8b\xe5\xbd\x93\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xaf\xe3\x80\x81\xe8\xa1\x97\xe3\x81\xae\xe4\xb8\xad\xe5\xbf\x83\xe9\x83\xa8\xe3\x81\x8b\xe3\x82\x8930\xe5\x88\x86\xe3\x81\xae\xe5\xa0\xb4\xe6\x89\x80\xe3\x81\xab\xe3\x81\x94\xe3\x81\x96\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe5\x85\xa8\xe5\xae\xa2\xe5\xae\xa4\xe3\x81\xab\xe9\xab\x98\xe9\x80\x9f\xe3\x82\xa4\xe3\x83\xb3\xe3\x82\xbf\xe3\x83\xbc\xe3\x83\x8d\xe3\x83\x83\xe3\x83\x88<link fg="blue" href="http://www.reportlab.com">\xe7\x92\xb0\xe5\xa2\x83\xe3\x82\x92\xe5\xae\x8c\xe5\x82\x99</link>\xe3\x81\x97\xe3\x81\xa6<u>\xe 3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99</u>\xe3\x80\x82\xe3\x83\x95\xe3\x82\xa1\xe3\x83\x9f\xe3\x83\xaa\xe3\x83\xbc\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xaf5\xe5\x90\x8d\xe6\xa7\x98\xe3\x81\xbe\xe3\x81\xa7\xe3\x81\x8a\xe6\xb3\x8a\xe3\x82\x8a\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe3\x81\xbe\xe3\x81\x9f\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xae\xe3\x81\x8a\xe5\xae\xa2\xe6\xa7\x98\xe3\x81\xaf\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xa9\xe3\x82\xa6\xe3\x83\xb3\xe3\x82\xb8\xe3\x82\x92\xe3\x81\x94\xe5\x88\xa9\xe7\x94\xa8\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe4\xba\x8b\xe5\x89\x8d\xe3\x81\xab\xe3\x81\x94\xe4\xba\x88\xe7\xb4\x84\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x82\x8b\xe3\x82\xbf\xe3\x82\xa4\xe3\x83\xa 0\xe3\x83\x88\xe3\x82\xa5\xe3\x83\x95\xe3\x83\xa9\xe3\x82\xa4\xe3\x83\xbb\xe3\x83\x91\xe3\x83\x83\xe3\x82\xb1\xe3\x83\xbc\xe3\x82\xb8\xe3\x81\xab\xe3\x81\xaf\xe3\x80\x81\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xae\xe9\xa7\x90\xe8\xbb\x8a\xe6\x96\x99\xe9\x87\x91\xe3\x81\x8c\xe5\x90\xab\xe3\x81\xbe\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82' + #this is utf8 + gatwickText = b'\xe3\x82\xac\xe3\x83\x88\xe3\x82\xa6\xe3\x82\xa3\xe3\x83\x83\xe3\x82\xaf\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xa8\xe9\x80\xa3\xe7\xb5\xa1\xe9\x80\x9a\xe8\xb7\xaf\xe3\x81\xa7\xe7\x9b\xb4\xe7\xb5\x90\xe3\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3\x82\x8b\xe5\x94\xaf\xe4\xb8\x80\xe3\x81\xae\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xa7\xe3\x81\x82\xe3\x82\x8b\xe5\xbd\x93\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xaf\xe3\x80\x81\xe8\xa1\x97\xe3\x81\xae\xe4\xb8\xad\xe5\xbf\x83\xe9\x83\xa8\xe3\x81\x8b\xe3\x82\x8930\xe5\x88\x86\xe3\x81\xae\xe5\xa0\xb4\xe6\x89\x80\xe3\x81\xab\xe3\x81\x94\xe3\x81\x96\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe5\x85\xa8\xe5\xae\xa2\xe5\xae\xa4\xe3\x81\xab\xe9\xab\x98\xe9\x80\x9f\xe3\x82\xa4\xe3\x83\xb3\xe3\x82\xbf\xe3\x83\xbc\xe3\x83\x8d\xe3\x83\x83\xe3\x83\x88\xe7\x92\xb0\xe5\xa2\x83\xe3\x82\x92\xe5\xae\x8c\xe5\x82\x99\xe3\x81\x97\xe3\x81\xa6\xe3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe3\x83\x95\xe3\x82\xa 1\xe3\x83\x9f\xe3\x83\xaa\xe3\x83\xbc\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xaf5\xe5\x90\x8d\xe6\xa7\x98\xe3\x81\xbe\xe3\x81\xa7\xe3\x81\x8a\xe6\xb3\x8a\xe3\x82\x8a\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe3\x81\xbe\xe3\x81\x9f\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xae\xe3\x81\x8a\xe5\xae\xa2\xe6\xa7\x98\xe3\x81\xaf\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xa9\xe3\x82\xa6\xe3\x83\xb3\xe3\x82\xb8\xe3\x82\x92\xe3\x81\x94\xe5\x88\xa9\xe7\x94\xa8\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe4\xba\x8b\xe5\x89\x8d\xe3\x81\xab\xe3\x81\x94\xe4\xba\x88\xe7\xb4\x84\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x82\x8b\xe3\x82\xbf\xe3\x82\xa4\xe3\x83\xa0\xe3\x83\x88\xe3\x82\xa5\xe3\x83\x95\xe3\x83\xa9\xe3\x82\xa4\xe3\x83\xbb\xe3\x83\x9 1\xe3\x83\x83\xe3\x82\xb1\xe3\x83\xbc\xe3\x82\xb8\xe3\x81\xab\xe3\x81\xaf\xe3\x80\x81\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xae\xe9\xa7\x90\xe8\xbb\x8a\xe6\x96\x99\xe9\x87\x91\xe3\x81\x8c\xe5\x90\xab\xe3\x81\xbe\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82' + gatwickText2= b'\xe3\x82\xac\xe3\x83\x88\xe3\x82\xa6\xe3\x82\xa3\xe3\x83\x83\xe3\x82\xaf<font color=red>\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xa8\xe9\x80\xa3\xe7\xb5\xa1\xe9\x80\x9a\xe8\xb7\xaf\xe3\x81\xa7\xe7\x9b\xb4\xe7\xb5\x90</font>\xe3\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3\x82\x8b\xe5\x94\xaf\xe4\xb8\x80\xe3\x81\xae\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xa7\xe3\x81\x82\xe3\x82\x8b\xe5\xbd\x93\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xaf\xe3\x80\x81\xe8\xa1\x97\xe3\x81\xae\xe4\xb8\xad\xe5\xbf\x83\xe9\x83\xa8\xe3\x81\x8b\xe3\x82\x8930\xe5\x88\x86\xe3\x81\xae\xe5\xa0\xb4\xe6\x89\x80\xe3\x81\xab\xe3\x81\x94\xe3\x81\x96\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe5\x85\xa8\xe5\xae\xa2\xe5\xae\xa4\xe3\x81\xab\xe9\xab\x98\xe9\x80\x9f\xe3\x82\xa4\xe3\x83\xb3\xe3\x82\xbf\xe3\x83\xbc\xe3\x83\x8d\xe3\x83\x83\xe3\x83\x88<link fg="blue" href="http://www.reportlab.com">\xe7\x92\xb0\xe5\xa2\x83\xe3\x82\x92\xe5\xae\x8c\xe5\x82\x99</link>\xe3\x81\x97\xe3\x81\xa6<u>\x e3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99</u>\xe3\x80\x82\xe3\x83\x95\xe3\x82\xa1\xe3\x83\x9f\xe3\x83\xaa\xe3\x83\xbc\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xaf5\xe5\x90\x8d\xe6\xa7\x98\xe3\x81\xbe\xe3\x81\xa7\xe3\x81\x8a\xe6\xb3\x8a\xe3\x82\x8a\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe3\x81\xbe\xe3\x81\x9f\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xae\xe3\x81\x8a\xe5\xae\xa2\xe6\xa7\x98\xe3\x81\xaf\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xa9\xe3\x82\xa6\xe3\x83\xb3\xe3\x82\xb8\xe3\x82\x92\xe3\x81\x94\xe5\x88\xa9\xe7\x94\xa8\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe4\xba\x8b\xe5\x89\x8d\xe3\x81\xab\xe3\x81\x94\xe4\xba\x88\xe7\xb4\x84\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x82\x8b\xe3\x82\xbf\xe3\x82\xa4\xe3\x83\x a0\xe3\x83\x88\xe3\x82\xa5\xe3\x83\x95\xe3\x83\xa9\xe3\x82\xa4\xe3\x83\xbb\xe3\x83\x91\xe3\x83\x83\xe3\x82\xb1\xe3\x83\xbc\xe3\x82\xb8\xe3\x81\xab\xe3\x81\xaf\xe3\x80\x81\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xae\xe9\xa7\x90\xe8\xbb\x8a\xe6\x96\x99\xe9\x87\x91\xe3\x81\x8c\xe5\x90\xab\xe3\x81\xbe\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82' c.setFont('HeiseiMin-W3', 12) jPara = Paragraph(gatwickText, jStyle) @@ -253,16 +256,23 @@ ## c.showPage() from reportlab.lib import textsplit - + def sascii(x): + s = ascii(x) + if s.startswith('u') or s.startswith('b'): s = s[1:] + if s.startswith("'") or s.startswith('"'): s = s[1:] + if s.startswith('\\u') or s.startswith('\\x'): s = s[1:] + if s.endswith("'") or s.endswith('"'): s = s[:-1] + return s + c.setFont('HeiseiMin-W3', 14) y = 700 - c.drawString(70, y, 'cannot end line') + c.drawString(70, y, 'cannot start line') y -= 20 for group in textsplit.CANNOT_START_LINE: c.drawString(70, y, group) y -= 20 c.setFont('Helvetica',10) - c.drawString(70, y, ' '.join([ascii(x)[4:-1] for x in group])) + c.drawString(70, y, ' '.join([sascii(x) for x in group])) c.setFont('HeiseiMin-W3', 14) y -= 20 @@ -275,7 +285,7 @@ c.drawString(70, y, group) y -= 20 c.setFont('Helvetica',10) - c.drawString(70, y, ' '.join([ascii(x)[2:] for x in group])) + c.drawString(70, y, ' '.join([sascii(x) for x in group])) c.setFont('HeiseiMin-W3', 14) y -= 20 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_paragraphs.py new/reportlab-3.5.59/tests/test_paragraphs.py --- old/reportlab-3.5.56/tests/test_paragraphs.py 2020-07-20 09:39:52.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_paragraphs.py 2020-12-27 12:44:36.000000000 +0100 @@ -5,13 +5,14 @@ from reportlab import xrange from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) -import unittest, os +import unittest, os, random from reportlab.platypus import Paragraph, SimpleDocTemplate, XBox, Indenter, XPreformatted, PageBreak, Spacer from reportlab.lib.styles import ParagraphStyle from reportlab.lib.units import inch from reportlab.lib.abag import ABag from reportlab.lib.colors import red, black, navy, white, green from reportlab.lib.randomtext import randomText +from reportlab.rl_config import invariant as rl_invariant from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY from reportlab.rl_config import defaultPageSize, rtlSupport from reportlab.pdfbase import ttfonts @@ -83,7 +84,7 @@ 2. ... 3. ... """ - + if rl_invariant: random.seed(1854640162) story = [] SA = story.append diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_pdfbase_ttfonts.py new/reportlab-3.5.59/tests/test_pdfbase_ttfonts.py --- old/reportlab-3.5.56/tests/test_pdfbase_ttfonts.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_pdfbase_ttfonts.py 2020-12-27 12:44:36.000000000 +0100 @@ -47,7 +47,7 @@ font = _fonts[fontName] doc = c._doc kfunc = font.face.charToGlyph.keys if isPy3 else font.face.charToGlyph.iterkeys - for s in kfunc(): + for s in sorted(list(kfunc())): if s<0x10000: font.splitString(uniChr(s),doc) state = font.state[doc] @@ -55,7 +55,7 @@ #print('len(assignments)=%d'% len(state.assignments)) nzero = 0 ifunc = state.assignments.items if isPy3 else state.assignments.iteritems - for code, n in ifunc(): + for code, n in sorted(list(ifunc())): if code==0: nzero += 1 cn[n] = uniChr(code) if nzero>1: print('%s there were %d zero codes' % (fontName,nzero)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_pdfgen_general.py new/reportlab-3.5.59/tests/test_pdfgen_general.py --- old/reportlab-3.5.56/tests/test_pdfgen_general.py 2020-09-18 15:27:00.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_pdfgen_general.py 2021-01-01 19:09:10.000000000 +0100 @@ -463,6 +463,12 @@ t.textLine('canvas.rect(x, y, width, height) - x,y is lower left') c.roundRect(inch,6.25*inch,2*inch,0.6*inch,0.1*inch) + c.saveState() + c.setStrokeColor(red) + c.roundRect(inch*1.1,6.35*inch,1.8*inch,0.4*inch,[0.1*inch,0,0.09*inch,0]) + c.setStrokeColor(green) + c.roundRect(inch*1.15,6.40*inch,1.7*inch,0.3*inch,[0,0.1*inch,0,0.09*inch]) + c.restoreState() t.setTextOrigin(4*inch, 6.55*inch) t.textLine('canvas.roundRect(x,y,width,height,radius)') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_breaking.py new/reportlab-3.5.59/tests/test_platypus_breaking.py --- old/reportlab-3.5.56/tests/test_platypus_breaking.py 2020-09-02 14:34:06.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_platypus_breaking.py 2020-12-27 12:44:36.000000000 +0100 @@ -5,7 +5,8 @@ __version__='3.3.0' from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) -import sys, os, time, re +import sys, os, time, re, random +from reportlab.rl_config import invariant as rl_invariant from operator import truth import unittest from reportlab.platypus.flowables import Flowable, KeepTogether, KeepTogetherSplitAtTop @@ -63,6 +64,7 @@ def _test0(self): "This makes one long multi-page paragraph in test_platypus_breaking." + if rl_invariant: random.seed(1532760416) def RT(k,theme='PYTHON',sentences=1,cache={}): if k not in cache: cache[k] = randomText(theme=theme,sentences=sentences) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_cjk_wrap.py new/reportlab-3.5.59/tests/test_platypus_cjk_wrap.py --- old/reportlab-3.5.56/tests/test_platypus_cjk_wrap.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_platypus_cjk_wrap.py 2020-12-27 12:44:36.000000000 +0100 @@ -20,10 +20,10 @@ #says "Japanese is difficult, isn't it?" -shortText = '\u65e5\u672c\u8a9e\u306f\u96e3\u3057\u3044\u3067\u3059\u306d\uff01' +shortText = u'\u65e5\u672c\u8a9e\u306f\u96e3\u3057\u3044\u3067\u3059\u306d\uff01' -gatwickText = '\xe3\x82\xac\xe3\x83\x88\xe3\x82\xa6\xe3\x82\xa3\xe3\x83\x83\xe3\x82\xaf\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xa8\xe9\x80\xa3\xe7\xb5\xa1\xe9\x80\x9a\xe8\xb7\xaf\xe3\x81\xa7\xe7\x9b\xb4\xe7\xb5\x90\xe3\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3\x82\x8b\xe5\x94\xaf\xe4\xb8\x80\xe3\x81\xae\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xa7\xe3\x81\x82\xe3\x82\x8b\xe5\xbd\x93\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xaf\xe3\x80\x81VERYLONGENGLISHGOESHERE\xe8\xa1\x97\xe3\x81\xae\xe4\xb8\xad\xe5\xbf\x83\xe9\x83\xa8\xe3\x81\x8b\xe3\x82\x8930\xe5\x88\x86\xe3\x81\xae\xe5\xa0\xb4\xe6\x89\x80\xe3\x81\xab\xe3\x81\x94\xe3\x81\x96\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe5\x85\xa8\xe5\xae\xa2\xe5\xae\xa4\xe3\x81\xab\xe9\xab\x98\xe9\x80\x9f\xe3\x82\xa4\xe3\x83\xb3\xe3\x82\xbf\xe3\x83\xbc\xe3\x83\x8d\xe3\x83\x83\xe3\x83\x88\xe7\x92\xb0\xe5\xa2\x83\xe3\x82\x92\xe5\xae\x8c\xe5\x82\x99\xe3\x81\x97\xe3\x81\xa6\xe3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe3\x83\ x95\xe3\x82\xa1\xe3\x83\x9f\xe3\x83\xaa\xe3\x83\xbc\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xaf5\xe5\x90\x8d\xe6\xa7\x98\xe3\x81\xbe\xe3\x81\xa7\xe3\x81\x8a\xe6\xb3\x8a\xe3\x82\x8a\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe3\x81\xbe\xe3\x81\x9f\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xae\xe3\x81\x8a\xe5\xae\xa2\xe6\xa7\x98\xe3\x81\xaf\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xa9\xe3\x82\xa6\xe3\x83\xb3\xe3\x82\xb8\xe3\x82\x92\xe3\x81\x94\xe5\x88\xa9\xe7\x94\xa8\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe4\xba\x8b\xe5\x89\x8d\xe3\x81\xab\xe3\x81\x94\xe4\xba\x88\xe7\xb4\x84\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x82\x8b\xe3\x82\xbf\xe3\x82\xa4\xe3\x83\xa0\xe3\x83\x88\xe3\x82\xa5\xe3\x83\x95\xe3\x83\xa9\xe3\x82\xa4\xe3\x83\ xbb\xe3\x83\x91\xe3\x83\x83\xe3\x82\xb1\xe3\x83\xbc\xe3\x82\xb8\xe3\x81\xab\xe3\x81\xaf\xe3\x80\x81\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xae\xe9\xa7\x90\xe8\xbb\x8a\xe6\x96\x99\xe9\x87\x91\xe3\x81\x8c\xe5\x90\xab\xe3\x81\xbe\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82' +gatwickText = b'\xe3\x82\xac\xe3\x83\x88\xe3\x82\xa6\xe3\x82\xa3\xe3\x83\x83\xe3\x82\xaf\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xa8\xe9\x80\xa3\xe7\xb5\xa1\xe9\x80\x9a\xe8\xb7\xaf\xe3\x81\xa7\xe7\x9b\xb4\xe7\xb5\x90\xe3\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3\x82\x8b\xe5\x94\xaf\xe4\xb8\x80\xe3\x81\xae\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xa7\xe3\x81\x82\xe3\x82\x8b\xe5\xbd\x93\xe3\x83\x9b\xe3\x83\x86\xe3\x83\xab\xe3\x81\xaf\xe3\x80\x81VERYLONGENGLISHGOESHERE\xe8\xa1\x97\xe3\x81\xae\xe4\xb8\xad\xe5\xbf\x83\xe9\x83\xa8\xe3\x81\x8b\xe3\x82\x8930\xe5\x88\x86\xe3\x81\xae\xe5\xa0\xb4\xe6\x89\x80\xe3\x81\xab\xe3\x81\x94\xe3\x81\x96\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe5\x85\xa8\xe5\xae\xa2\xe5\xae\xa4\xe3\x81\xab\xe9\xab\x98\xe9\x80\x9f\xe3\x82\xa4\xe3\x83\xb3\xe3\x82\xbf\xe3\x83\xbc\xe3\x83\x8d\xe3\x83\x83\xe3\x83\x88\xe7\x92\xb0\xe5\xa2\x83\xe3\x82\x92\xe5\xae\x8c\xe5\x82\x99\xe3\x81\x97\xe3\x81\xa6\xe3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe3\x83 \x95\xe3\x82\xa1\xe3\x83\x9f\xe3\x83\xaa\xe3\x83\xbc\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xaf5\xe5\x90\x8d\xe6\xa7\x98\xe3\x81\xbe\xe3\x81\xa7\xe3\x81\x8a\xe6\xb3\x8a\xe3\x82\x8a\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe3\x81\xbe\xe3\x81\x9f\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xab\xe3\x83\xbc\xe3\x83\xa0\xe3\x81\xae\xe3\x81\x8a\xe5\xae\xa2\xe6\xa7\x98\xe3\x81\xaf\xe3\x80\x81\xe3\x82\xa8\xe3\x82\xb0\xe3\x82\xbc\xe3\x82\xaf\xe3\x83\x86\xe3\x82\xa3\xe3\x83\x96\xe3\x83\xa9\xe3\x82\xa6\xe3\x83\xb3\xe3\x82\xb8\xe3\x82\x92\xe3\x81\x94\xe5\x88\xa9\xe7\x94\xa8\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82\xe4\xba\x8b\xe5\x89\x8d\xe3\x81\xab\xe3\x81\x94\xe4\xba\x88\xe7\xb4\x84\xe3\x81\x84\xe3\x81\x9f\xe3\x81\xa0\xe3\x81\x91\xe3\x82\x8b\xe3\x82\xbf\xe3\x82\xa4\xe3\x83\xa0\xe3\x83\x88\xe3\x82\xa5\xe3\x83\x95\xe3\x83\xa9\xe3\x82\xa4\xe3\x83 \xbb\xe3\x83\x91\xe3\x83\x83\xe3\x82\xb1\xe3\x83\xbc\xe3\x82\xb8\xe3\x81\xab\xe3\x81\xaf\xe3\x80\x81\xe7\xa9\xba\xe6\xb8\xaf\xe3\x81\xae\xe9\xa7\x90\xe8\xbb\x8a\xe6\x96\x99\xe9\x87\x91\xe3\x81\x8c\xe5\x90\xab\xe3\x81\xbe\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x8a\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82' def myMainPageFrame(canvas, doc): "The page frame used for all PDF documents." diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_indents.py new/reportlab-3.5.59/tests/test_platypus_indents.py --- old/reportlab-3.5.56/tests/test_platypus_indents.py 2020-01-22 15:40:54.000000000 +0100 +++ new/reportlab-3.5.59/tests/test_platypus_indents.py 2020-12-27 12:44:36.000000000 +0100 @@ -7,6 +7,7 @@ from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) import sys, os, random +from reportlab.rl_config import invariant as rl_invariant from operator import truth import unittest from reportlab.pdfbase.pdfmetrics import stringWidth @@ -65,6 +66,7 @@ def test0(self): "IndentTestCase test0" + if rl_invariant: random.seed(1479316371) # Build story. story = [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_index.py new/reportlab-3.5.59/tests/test_platypus_index.py --- old/reportlab-3.5.56/tests/test_platypus_index.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_platypus_index.py 2020-12-27 12:44:36.000000000 +0100 @@ -6,7 +6,8 @@ from reportlab import xrange from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) -import sys, os +import sys, os, random +from reportlab.rl_config import invariant as rl_invariant from os.path import join, basename, splitext from math import sqrt import unittest @@ -83,6 +84,7 @@ Index terms are grouped by their first 2, and first 3 characters. The page numbers should be clickable and link to the indexed word. ''' + if rl_invariant: random.seed(1753799561) # Build story. for headers in False, True: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_leftright.py new/reportlab-3.5.59/tests/test_platypus_leftright.py --- old/reportlab-3.5.56/tests/test_platypus_leftright.py 2020-01-22 15:40:54.000000000 +0100 +++ new/reportlab-3.5.59/tests/test_platypus_leftright.py 2020-12-27 12:44:36.000000000 +0100 @@ -5,7 +5,8 @@ __version__='3.3.0' from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) -import sys, os, time +import sys, os, time, random +from reportlab.rl_config import invariant as rl_invariant from operator import truth import unittest from reportlab.platypus.flowables import Flowable @@ -88,6 +89,7 @@ def testIt(self): "LeftRightTestCase.testit" + if rl_invariant: random.seed(464568862) # Build story. story = [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_lists.py new/reportlab-3.5.59/tests/test_platypus_lists.py --- old/reportlab-3.5.56/tests/test_platypus_lists.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_platypus_lists.py 2020-12-27 12:44:36.000000000 +0100 @@ -3,7 +3,8 @@ from reportlab import xrange from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) -import os,unittest +import os,unittest, random +from reportlab.rl_config import invariant as rl_invariant from reportlab.platypus import Spacer, SimpleDocTemplate, Table, TableStyle, ListFlowable, ListItem, \ Paragraph, PageBreak, DDIndenter, MultiCol from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle @@ -60,6 +61,7 @@ "Make documents with tables" def test1(self): + if rl_invariant: random.seed(888147853) styleSheet = getSampleStyleSheet() doc = SimpleDocTemplate(outputfile('test_platypus_lists1.pdf'),showBoundary=True) story=[] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_paragraphs.py new/reportlab-3.5.59/tests/test_platypus_paragraphs.py --- old/reportlab-3.5.56/tests/test_platypus_paragraphs.py 2020-10-29 17:06:02.000000000 +0100 +++ new/reportlab-3.5.59/tests/test_platypus_paragraphs.py 2020-12-27 12:44:36.000000000 +0100 @@ -15,7 +15,7 @@ from reportlab.lib.colors import Color from reportlab.lib.units import cm from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY -from reportlab.lib.utils import _className, asBytes, asUnicode +from reportlab.lib.utils import _className, asBytes, asUnicode, asNative from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.platypus.xpreformatted import XPreformatted from reportlab.platypus.frames import Frame, ShowBoundaryValue @@ -186,13 +186,74 @@ style = ParagraphStyle( 'normal', fontName='Helvetica', fontSize=12, embeddedHyphenation=1, splitLongWords=0, hyphenationLang='en-GB') - text = 'Super\xc2\xadcali\xc2\xadfragi\xc2\xadlistic\xc2\xadexpi\xc2\xadali\xc2\xaddocious' + shy = asNative(u'\xad') + text = shy.join(('Super','cali','fragi','listic','expi','ali','docious')) f.addFromList([Paragraph(text, style)], c) text = u'<span color="red">Super</span><span color="pink">­cali­</span>fragi­listic­expi­ali­docious' f.addFromList([Paragraph(text, style)], c) c.showPage() c.save() + def test_platypus_paragraphs_embedded2(self): + from hashlib import md5 as hashlib_md5 + + fontName = 'Helvetica' + fontSize = 10 + + texts = [asUnicode(text) for text + in [ + b'UU\xc2\xadDIS\xc2\xadTU\xc2\xadSA\xc2\xadLA JA TAI\xc2\xadMIK\xc2\xadKO', + b'NUO\xc2\xadRI KAS\xc2\xadVA\xc2\xadTUS\xc2\xadMET\xc2\xadSIK\xc2\xadK\xc3\x96', + b'VART\xc2\xadTU\xc2\xadNUT KAS\xc2\xadVA\xc2\xadTUS\xc2\xadMET\xc2\xadSIK\xc2\xadK\xc3\x96', + b'UU\xc2\xadDIS\xc2\xadTUS-KYP\xc2\xadS\xc3\x84 MET\xc2\xadSIK\xc2\xadK\xc3\x96', + b'SIE\xc2\xadMEN- JA SUO-JUS\xc2\xadPUU-MET\xc2\xadSIK\xc2\xadK\xc3\x96', + b'E\xc2\xadRI-I\xc2\xadK\xc3\x84\xc2\xadIS-RA\xc2\xadKEN\xc2\xadTEI\xc2\xadNEN MET\xc2\xadSIK\xc2\xadK\xc3\x96', + ] + ] + maxWidth = stringWidth('VARTTUNUT KAS', fontName, fontSize)+0.5 + span = lambda _t, _c: "<span color='%s'>%s</span>" % (_c, _t) + + pagesize = (20+maxWidth, 800) + c = Canvas(outputfile('test_platypus_paragraphs_embedded2.pdf'), pagesize=pagesize) + + expected = [ + (163, b'\x7f\xd7_^\x07\x9c!u\x02\xb4\x13z\xb5y6C'), + (163, b'\xab\x82\xbf\xb3\xfc\xb5\xaau\x15\xb1<\x8eX\xbe35'), + (163, b'LL\xb1\xfd.\x8a\x8bk\xde\xcdK\x16P\xebWh'), + (163, b'\xa9fj\xdd\xb9\x11N\xcf\xbb\x12\xfb\xd9\xa5\xf0v<'), + (163, b'\x18r\x98\x17\xd8&\x8c\x01{\xf3|r\xca\xccQy'), + (163, b'\xb7\xf2\x0f/d\xe9<\xd1B?\xe5\x8c\xcbO\x06?'), + ] + observed = [] + for eh in 0, 1, 2: + for slw in 0, 1: + f = Frame(10, 10, maxWidth, 780, + showBoundary=ShowBoundaryValue(dashArray=(1,1)), + leftPadding=0, + rightPadding=0, + topPadding=0, + bottomPadding=0, + ) + style = ParagraphStyle( + 'normal', fontName=fontName, fontSize=fontSize, + embeddedHyphenation=eh, splitLongWords=slw, + hyphenationLang=None) + f.addFromList([Paragraph('slw=%d eh=%d' % (slw,eh), style)], c) + for text in texts: + f.addFromList([Paragraph(text, style)], c) + mfText = text.split(u'\xad') + mfText[0] = span(mfText[0],'red') + if len(mfText)>1: + mfText[1] = span(mfText[1],'pink') + if len(mfText)>2: + mfText[-1] = span(mfText[-1],'blue') + mfText = u'­'.join(mfText) + f.addFromList([Paragraph(mfText, style)], c) + observed.append((len(c._code), hashlib_md5(b"".join((asBytes(b,"latin1") for b in c._code))).digest())) + c.showPage() + c.save() + self.assertEqual(observed, expected) + def test_lele_img(self): from reportlab.pdfgen.canvas import Canvas from reportlab.platypus import Paragraph @@ -621,9 +682,9 @@ \xd7\x93\xd7\xa8\xd7\x9b\xd7\x94 \xd7\xa9\xd7\x99\xd7\xaa\xd7\x95\xd7\xa4\xd7\x99\xd7\xaa \xd7\x90\xd7\xaa\xd7\x94 \xd7\x93\xd7\xaa.''' gif = os.path.join(testsFolder,'pythonpowered.gif') - heading = Paragraph('\xd7\x96\xd7\x95\xd7\x94\xd7\x99 \xd7\x9b\xd7\x95\xd7\xaa\xd7\xa8\xd7\xaa',h3) + heading = Paragraph(b'\xd7\x96\xd7\x95\xd7\x94\xd7\x99 \xd7\x9b\xd7\x95\xd7\xaa\xd7\xa8\xd7\xaa',h3) story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(text,bt)])) - heading = Paragraph('\xd7\x96\xd7\x95\xd7\x94\xd7\x99 \xd7\x9b\xd7\x95\xd7\xaa\xd7\xa8\xd7\xaa',h3) + heading = Paragraph(b'\xd7\x96\xd7\x95\xd7\x94\xd7\x99 \xd7\x9b\xd7\x95\xd7\xaa\xd7\xa8\xd7\xaa',h3) story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(text1,bt)])) doc = MyDocTemplate(outputfile('test_platypus_imageandflowables_rtl.pdf'),showBoundary=1) doc.multiBuild(story) @@ -1311,7 +1372,7 @@ bt = getSampleStyleSheet()['BodyText'] bt.fontName = 'DejaVuSans' doc = SimpleDocTemplate(fn) - story = [Paragraph('<b>%s</b>' % title,bt)] + story = [Paragraph('<b>%s</b>' % asNative(title),bt)] story.extend([Paragraph(bu('&%s; = <span color="red">&%s;</span>' % (k,k)), bt) for k, v in alphaSortedItems(greeks)]) doc.build(story) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_pleaseturnover.py new/reportlab-3.5.59/tests/test_platypus_pleaseturnover.py --- old/reportlab-3.5.56/tests/test_platypus_pleaseturnover.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_platypus_pleaseturnover.py 2020-12-27 12:44:36.000000000 +0100 @@ -5,8 +5,7 @@ __version__='3.3.0' from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) -import sys -import unittest +import sys, unittest from reportlab.platypus.flowables import Flowable, PTOContainer, KeepInFrame from reportlab.platypus import FrameBG from reportlab.lib.units import cm @@ -16,7 +15,6 @@ from reportlab.platypus.paragraph import Paragraph from reportlab.platypus.tables import Table from reportlab.platypus.frames import Frame -from reportlab.lib.randomtext import randomText from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate, FrameBreak def myMainPageFrame(canvas, doc): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_preformatted.py new/reportlab-3.5.59/tests/test_platypus_preformatted.py --- old/reportlab-3.5.56/tests/test_platypus_preformatted.py 2020-01-22 15:40:54.000000000 +0100 +++ new/reportlab-3.5.59/tests/test_platypus_preformatted.py 2020-12-27 12:44:36.000000000 +0100 @@ -5,7 +5,7 @@ __version__='3.3.0' from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) -import sys, os, random +import sys, os from operator import truth import unittest from reportlab.pdfbase.pdfmetrics import stringWidth diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_programming.py new/reportlab-3.5.59/tests/test_platypus_programming.py --- old/reportlab-3.5.56/tests/test_platypus_programming.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_platypus_programming.py 2020-12-27 12:44:36.000000000 +0100 @@ -7,8 +7,7 @@ """ from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) -import sys -import unittest +import sys, unittest class PlatypusProgrammingTestCase(unittest.TestCase): "test platypus programming" @@ -60,6 +59,9 @@ from reportlab.platypus import Paragraph from reportlab.lib import colors from reportlab.lib.randomtext import randomText, PYTHON + import random + from reportlab.rl_config import invariant as rl_invariant + if rl_invariant: random.seed(2103696747) # Build story. story = [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_tables.py new/reportlab-3.5.59/tests/test_platypus_tables.py --- old/reportlab-3.5.56/tests/test_platypus_tables.py 2020-12-01 17:29:04.000000000 +0100 +++ new/reportlab-3.5.59/tests/test_platypus_tables.py 2021-01-04 15:51:54.000000000 +0100 @@ -1066,6 +1066,72 @@ self.assertEqual(len(T[1]._bkgrndcmds),3) doc.build(story) + def test5(self): + '''test rounded corners''' + story = [] + story_add = story.append + ts_tables = [ + ('BACKGROUND',(0,0),(-1,0),colors.pink), + ('BACKGROUND',(0,1),(-1,1),colors.lightblue), + ('ROWBACKGROUNDS',(0,2),(-1,-1),(colors.lightgrey,None)), + ('TEXTCOLOR',(0,0),(-1,0),colors.green), + ('TEXTCOLOR',(0,1),(-1,1),colors.red), + ('LINEABOVE', (0,0), (-1,0), 1, colors.purple), + ('LINEBELOW', (0,0), (-1,0), 2, colors.purple), + ('LINEABOVE', (0,1), (-1,1), 1, colors.orange), + ('LINEBELOW', (0,1), (-1,1), 2, colors.orange), + ('LINEBEFORE', (0,0), (0,-1), 1, colors.red), + ('LINEAFTER', (-1,0), (-1,-1), 1, colors.blue), + ('LINEBELOW', (0,-1), (-1,-1), 1, colors.green), + ('FONT', (2,2), (5,8), 'Times-Bold'), + ] + data = self.data34 + from reportlab.platypus import Paragraph, Table, SimpleDocTemplate, PageBreak + from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle + styleSheet = getSampleStyleSheet() + bodyText = styleSheet['BodyText'] + + story_add(Paragraph('The whole table',bodyText)) + t = Table(data[:], style=ts_tables, repeatRows=2, cornerRadii=[5,6,4,3]) + story_add(t) + t = Table(data[:], style=ts_tables, repeatRows=2, cornerRadii=[5,6,4,5]) + T = t.split(4*72,90) + story_add(Paragraph('The split table part 0',bodyText)) + story_add(T[0]) + story_add(Paragraph('The split table part 1',bodyText)) + story_add(T[1]) + story_add(PageBreak()) + ts2 = ts_tables+[('ROUNDEDCORNERS',[5,6,4,3])] + story_add(Paragraph('Rounded corners via style',bodyText)) + t = Table(data[:], style=ts2, repeatRows=2) + story_add(t) + t = Table(data[:], style=ts2, repeatRows=2) + T = t.split(4*72,90) + story_add(Paragraph('The split table part 0',bodyText)) + story_add(T[0]) + story_add(Paragraph('The split table part 1',bodyText)) + story_add(T[1]) + story_add(PageBreak()) + story_add(Paragraph('Rounded corners via style overridden by instance argument',bodyText)) + t = Table(data[:], style=ts2, repeatRows=2, cornerRadii=(0,3,5,0)) + story_add(t) + t = Table(data[:], style=ts2, repeatRows=2, cornerRadii=t._cornerRadii) + T = t.split(4*72,90) + story_add(Paragraph('The split table part 0',bodyText)) + story_add(T[0]) + story_add(Paragraph('The split table part 1',bodyText)) + story_add(T[1]) + story_add(Paragraph('Rounded corners double linebelow',bodyText)) + ts3 = ts_tables[:] + ts3.remove(('LINEBELOW', (0,-1), (-1,-1), 1, colors.green)) + ts3.append(('LINEBELOW', (0,-1), (-1,-1), 1, colors.green, 1, None, None, 3,1)) + t = Table(data[:], style=ts3, repeatRows=2, cornerRadii=[0,0,6,7])#[4,5,6,7]) + story_add(t) + doc = SimpleDocTemplate(outputfile('test_platypus_tables_rounded_corners.pdf'), showBoundary=0) + doc.build(story) + assert(T[0]._cornerRadii==[0,3,0,0]) + assert(T[1]._cornerRadii==[0,3,5,0]) + def makeSuite(): return makeSuiteForClasses(TablesTestCase) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_toc.py new/reportlab-3.5.59/tests/test_platypus_toc.py --- old/reportlab-3.5.56/tests/test_platypus_toc.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_platypus_toc.py 2020-12-27 12:44:36.000000000 +0100 @@ -13,6 +13,7 @@ from os.path import join, basename, splitext from math import sqrt import random +from reportlab.rl_config import invariant as rl_invariant import unittest from reportlab.lib.units import inch, cm from reportlab.lib.pagesizes import A4 @@ -133,7 +134,7 @@ 3. Only entries of every second level has links ... """ - + if rl_invariant: random.seed(2077179149) maxLevels = 12 # Create styles to be used for document headers @@ -181,7 +182,7 @@ with the right headings to make it go faster. We used a simple 100-chapter document with one level. """ - + if rl_invariant: random.seed(1216902530) chapters = 30 #goes over one page headerStyle = makeHeaderStyle(0) @@ -281,6 +282,7 @@ self.assertTrue(hasattr(doc,'seq')) def test2(self): + if rl_invariant: random.seed(530125105) chapters = 20 #so we know we use only one page from reportlab.lib.colors import pink diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_wrapping.py new/reportlab-3.5.59/tests/test_platypus_wrapping.py --- old/reportlab-3.5.56/tests/test_platypus_wrapping.py 2020-01-22 15:40:54.000000000 +0100 +++ new/reportlab-3.5.59/tests/test_platypus_wrapping.py 2020-12-27 12:44:36.000000000 +0100 @@ -5,7 +5,7 @@ __version__='3.3.0' from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) -import sys, os, random +import sys, os from operator import truth import unittest from reportlab.pdfbase.pdfmetrics import stringWidth diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_platypus_xref.py new/reportlab-3.5.59/tests/test_platypus_xref.py --- old/reportlab-3.5.56/tests/test_platypus_xref.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_platypus_xref.py 2020-12-27 12:44:36.000000000 +0100 @@ -5,7 +5,8 @@ __version__='3.3.0' from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation setOutDir(__name__) -import sys, os, time +import sys, os, time, random +from reportlab.rl_config import invariant as rl_invariant from operator import truth import unittest from reportlab.lib import colors @@ -69,6 +70,7 @@ def _test0(self): "This makes one long multi-page paragraph." from reportlab.platypus.flowables import DocAssign, DocExec, DocPara, DocIf, DocWhile + if rl_invariant: random.seed(1629812163) # Build story. story = [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_rl_accel.py new/reportlab-3.5.59/tests/test_rl_accel.py --- old/reportlab-3.5.56/tests/test_rl_accel.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_rl_accel.py 2020-12-27 12:44:36.000000000 +0100 @@ -81,8 +81,15 @@ def testEscapePDF(self): for func, kind in getFuncs('escapePDF'): - assert func('(test)')=='\\(test\\)',"%s escapePDF('(test)')=='\\\\(test\\\\)' fails with value %s!" % ( - kind,ascii(func('(test)'))) + for s, sx in ( + ('(test)', r'\(test\)'), + (r'\(test)', r'\\\(test\)'), + (b'\223\214\213\236',r'\223\214\213\236'), + (u'\223\214\213\236',r'\223\214\213\236'), + ): + r = func(s) + assert r==sx,"%s escapePDF('%s')=='%s' fails with value '%s'!" % ( + kind,s,sx,r) def testCalcChecksum(self): for func, kind in getFuncs('calcChecksum'): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reportlab-3.5.56/tests/test_source_chars.py new/reportlab-3.5.59/tests/test_source_chars.py --- old/reportlab-3.5.56/tests/test_source_chars.py 2019-10-01 17:38:11.000000000 +0200 +++ new/reportlab-3.5.59/tests/test_source_chars.py 2020-12-27 12:44:36.000000000 +0100 @@ -23,6 +23,9 @@ self.output = open(outputfile(os.path.splitext(os.path.basename(fn))[0]+'.txt'),'w') + def tearDown(self): + self.output.close() + def checkFileForTabs(self, filename): txt = open_and_read(filename, 'r') chunks = txt.split('\t')