"Fossies" - the Fresh Open Source Software Archive

Member "reportlab-3.5.32/tests/test_platypus_paragraphs.py" (19 Oct 2019, 92008 Bytes) of package /linux/privat/reportlab-3.5.32.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "test_platypus_paragraphs.py": 3.5.28_vs_3.5.31.

    1 #Copyright ReportLab Europe Ltd. 2000-2017
    2 #see license.txt for license details
    3 """Tests for the reportlab.platypus.paragraphs module.
    4 """
    5 __version__='3.3.0'
    6 from reportlab.lib.testutils import setOutDir,makeSuiteForClasses, outputfile, printLocation
    7 setOutDir(__name__)
    8 import sys, os, unittest
    9 from operator import truth
   10 from reportlab.pdfgen.canvas import Canvas
   11 from reportlab.pdfbase.pdfmetrics import stringWidth, registerFont, registerFontFamily
   12 from reportlab.pdfbase.ttfonts import TTFont
   13 from reportlab.platypus.paraparser import ParaParser
   14 from reportlab.platypus.flowables import Flowable, DocAssert
   15 from reportlab.lib.colors import Color
   16 from reportlab.lib.units import cm
   17 from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
   18 from reportlab.lib.utils import _className, asBytes, asUnicode
   19 from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
   20 from reportlab.platypus.xpreformatted import XPreformatted
   21 from reportlab.platypus.frames import Frame, ShowBoundaryValue
   22 from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate, PageBreak, NextPageTemplate
   23 from reportlab.platypus import tableofcontents
   24 from reportlab.platypus.tableofcontents import TableOfContents
   25 from reportlab.platypus.tables import TableStyle, Table
   26 from reportlab.platypus.paragraph import Paragraph, _getFragWords, _splitWord, _fragWordSplitRep, ABag, pyphen
   27 from reportlab.rl_config import rtlSupport
   28 
   29 def myMainPageFrame(canvas, doc):
   30     "The page frame used for all PDF documents."
   31 
   32     canvas.saveState()
   33 
   34     canvas.rect(2.5*cm, 2.5*cm, 15*cm, 25*cm)
   35     canvas.setFont('Times-Roman', 12)
   36     pageNumber = canvas.getPageNumber()
   37     canvas.drawString(10*cm, cm, str(pageNumber))
   38 
   39     canvas.restoreState()
   40 
   41 class MyDocTemplate(BaseDocTemplate):
   42     _invalidInitArgs = ('pageTemplates',)
   43 
   44     def __init__(self, filename, **kw):
   45         frame1 = Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1')
   46         frame2 = Frame(2.5*cm, 2.5*cm, 310, 25*cm, id='F2')
   47         self.allowSplitting = 0
   48         BaseDocTemplate.__init__(self, filename, **kw)
   49         template = PageTemplate('normal', [frame1], myMainPageFrame)
   50         template1 = PageTemplate('special', [frame2], myMainPageFrame)
   51         template2 = PageTemplate('template2', [Frame(395, 108, 165, 645, id='second2')])
   52         self.addPageTemplates([template,template1,template2])
   53 
   54 class ParagraphCorners(unittest.TestCase):
   55     "some corner cases which should parse"
   56     def check(self,text,bt = getSampleStyleSheet()['BodyText']):
   57         try:
   58             P = Paragraph(text,style=bt)
   59         except:
   60             raise AssertionError("'%s' should parse"%text)
   61             
   62     def test0(self):
   63         self.check('<para />')
   64         self.check('<para/>')
   65         self.check('\t\t\t\n\n\n<para />')
   66         self.check('\t\t\t\n\n\n<para/>')
   67         self.check('<para\t\t\t\t/>')
   68         self.check('<para></para>')
   69         self.check('<para>      </para>')
   70         self.check('\t\t\n\t\t\t   <para>      </para>')
   71 
   72     def test1(self):
   73         "This makes several special paragraphs."
   74 
   75         # Build story.
   76         story = []
   77         styleSheet = getSampleStyleSheet()
   78         bt = styleSheet['BodyText']
   79         btN = ParagraphStyle('BodyTextTTNone',parent=bt,textTransform='none')
   80         btL = ParagraphStyle('BodyTextTTLower',parent=bt,textTransform='lowercase')
   81         btU = ParagraphStyle('BodyTextTTUpper',parent=bt,textTransform='uppercase')
   82         btC = ParagraphStyle('BodyTextTTCapitalize',parent=bt,textTransform='capitalize')
   83         story.append(Paragraph('''This should be ORDINARY text.''',style=bt))
   84         story.append(Paragraph('''This should be ORDINARY text.''',style=btN))
   85         story.append(Paragraph('''This should be LOWER text.''',style=btL))
   86         story.append(Paragraph('''This should be upper text.''',style=btU))
   87         story.append(Paragraph('''This should be cAPITALIZED text.''',style=btC))
   88 
   89         story.append(Paragraph('''T<i>hi</i>s shoul<font color="red">d b</font>e <b>ORDINARY</b> text.''',style=bt))
   90         story.append(Paragraph('''T<i>hi</i>s shoul<font color="red">d b</font>e <b>ORDINARY</b> text.''',style=btN))
   91         story.append(Paragraph('''T<i>hi</i>s shoul<font color="red">d b</font>e <b>LOWER</b> text.''',style=btL))
   92         story.append(Paragraph('''T<i>hi</i>s shoul<font color="red">d b</font>e <b>upper</b> text.''',style=btU))
   93         story.append(Paragraph('''T<i>hi</i>s shoul<font color="red">d b</font>e <b>cAPITALIZED</b> text.''',style=btC))
   94         doc = MyDocTemplate(outputfile('test_platypus_specialparagraphs.pdf'))
   95         doc.multiBuild(story)
   96 
   97     def test2(self):
   98         '''CJK splitting in multi-frag case'''
   99         style = ParagraphStyle('test', wordWrap = 'CJK')
  100         p = Paragraph('bla <i>blub</i> '*130 , style)
  101         aW,aH=439.275590551,121.88976378
  102         w,h=p.wrap(aW,aH)
  103         S=p.split(aW,aH)
  104         assert len(S)==2, 'Multi frag CJK splitting failed'
  105         w0,h0=S[0].wrap(aW,aH)
  106         assert h0<=aH,'Multi-frag CJK split[0] has wrong height %s >= available %s' % (H0,aH)
  107         w1,h1=S[1].wrap(aW,aH)
  108         assert h0+h1==h, 'Multi-frag-CJK split[0].height(%s)+split[1].height(%s) don\'t add to original %s' % (h0,h1,h)
  109 
  110     def test3(self):
  111         '''compare CJK splitting in some edge cases'''
  112         from reportlab.platypus.paragraph import Paragraph
  113         from reportlab.lib.styles import ParagraphStyle
  114         from reportlab.pdfbase import pdfmetrics
  115         from reportlab.lib.enums import TA_LEFT
  116         sty = ParagraphStyle('A')
  117         sty.fontSize = 15
  118         sty.leading = sty.fontSize*1.2
  119         sty.fontName = 'Courier'
  120         sty.alignment = TA_LEFT
  121         sty.wordWrap = 'CJK'
  122         p0=Paragraph('ABCDEFGHIJKL]N',sty)
  123         p1=Paragraph('AB<font color="red">C</font>DEFGHIJKL]N',sty)
  124         canv = Canvas(outputfile('test_platypus_paragraph_cjk3.pdf'))
  125         ix = len(canv._code)
  126         aW = pdfmetrics.stringWidth('ABCD','Courier',15)
  127         w,h=p0.wrap(aW,1000000)
  128         y = canv._pagesize[1]-72-h
  129         p0.drawOn(canv,72,y)
  130         w,h=p1.wrap(aW,1000000)
  131         y -= h+10
  132         p1.drawOn(canv,72,y)
  133         w,h=p0.wrap(aW*0.25-2,1000000)
  134         y -= h+10
  135         p0.drawOn(canv,72,y)
  136         w,h=p1.wrap(aW/4.-2,1000000)
  137         y -= h+10
  138         p1.drawOn(canv,72,y)
  139         assert canv._code[ix:]==['q', '1 0 0 1 72 697.8898 cm', 'q', '0 0 0 rg', 'BT 1 0 0 1 0 57 Tm /F2 15 Tf 18 TL (ABCD) Tj T* (EFGH) Tj T* (IJKL]) Tj T* (N) Tj T* ET', 'Q', 'Q', 'q', '1 0 0 1 72 615.8898 cm', 'q', 'BT 1 0 0 1 0 57 Tm 18 TL /F2 15 Tf 0 0 0 rg (AB) Tj 1 0 0 rg (C) Tj 0 0 0 rg (D) Tj T* (EFGH) Tj T* (IJKL]) Tj T* (N) Tj T* ET', 'Q', 'Q', 'q', '1 0 0 1 72 353.8898 cm', 'q', '0 0 0 rg', 'BT 1 0 0 1 0 237 Tm /F2 15 Tf 18 TL (A) Tj T* (B) Tj T* (C) Tj T* (D) Tj T* (E) Tj T* (F) Tj T* (G) Tj T* (H) Tj T* (I) Tj T* (J) Tj T* (K) Tj T* (L) Tj T* (]) Tj T* (N) Tj T* ET', 'Q', 'Q', 'q', '1 0 0 1 72 91.88976 cm', 'q', 'BT 1 0 0 1 0 237 Tm 18 TL /F2 15 Tf 0 0 0 rg (A) Tj T* (B) Tj T* 1 0 0 rg (C) Tj T* 0 0 0 rg (D) Tj T* (E) Tj T* (F) Tj T* (G) Tj T* (H) Tj T* (I) Tj T* (J) Tj T* (K) Tj T* (L) Tj T* (]) Tj T* (N) Tj T* ET', 'Q', 'Q']
  140         canv.showPage()
  141         canv.save()
  142         
  143 class ParagraphSplitTestCase(unittest.TestCase):
  144     "Test multi-page splitting of paragraphs (eyeball-test)."
  145 
  146     def test0(self):
  147         "This makes one long multi-page paragraph."
  148 
  149         # Build story.
  150         story = []
  151         styleSheet = getSampleStyleSheet()
  152         bt = styleSheet['BodyText']
  153         text = '''If you imagine that the box of X's tothe left is
  154 an image, what I want to be able to do is flow a
  155 series of paragraphs around the image
  156 so that once the bottom of the image is reached, then text will flow back to the
  157 left margin. I know that it would be possible to something like this
  158 using tables, but I can't see how to have a generic solution.
  159 There are two examples of this in the demonstration section of the reportlab
  160 site.
  161 If you look at the "minimal" euro python conference brochure, at the end of the
  162 timetable section (page 8), there are adverts for "AdSu" and "O'Reilly". I can
  163 see how the AdSu one might be done generically, but the O'Reilly, unsure...
  164 I guess I'm hoping that I've missed something, and that
  165 it's actually easy to do using platypus.
  166 '''
  167         from reportlab.platypus.flowables import ParagraphAndImage, Image
  168         from reportlab.lib.testutils import testsFolder
  169         gif = os.path.join(testsFolder,'pythonpowered.gif')
  170         story.append(ParagraphAndImage(Paragraph(text,bt),Image(gif)))
  171         phrase = 'This should be a paragraph spanning at least three pages. '
  172         description = ''.join([('%d: '%i)+phrase for i in range(250)])
  173         story.append(ParagraphAndImage(Paragraph(description, bt),Image(gif),side='left'))
  174 
  175         doc = MyDocTemplate(outputfile('test_platypus_paragraphandimage.pdf'))
  176         doc.multiBuild(story)
  177 
  178     def test1(self):
  179         "This makes one long multi-page paragraph."
  180 
  181         # Build story.
  182         story = []
  183         styleSheet = getSampleStyleSheet()
  184         h3 = styleSheet['Heading3']
  185         bt = styleSheet['BodyText']
  186         st=ParagraphStyle(
  187                             name="base",
  188                             fontName="Helvetica",
  189                             leading=12,
  190                             leftIndent=0,
  191                             firstLineIndent=0,
  192                             spaceBefore = 9.5,
  193                             fontSize=9.5,
  194                             )
  195         text = b'''If you imagine that the box of X's to the left is
  196 an image, what I want to be able to do is flow a
  197 series of paragraphs around the image
  198 so that once the bottom of the image is reached, then text will flow back to the
  199 left margin. I know that it would be possible to something like this
  200 using tables, but I can't see how to have a generic solution.
  201 There are two examples of this in the demonstration section of the reportlab
  202 site.
  203 If you look at the "minimal" euro python conference brochure, at the end of the
  204 timetable section (page 8), there are adverts for "AdSu" and "O'Reilly". I can
  205 see how the AdSu one might be done generically, but the O'Reilly, unsure...
  206 I guess I'm hoping that I've missed something, and that
  207 it's actually easy to do using platypus.We can do greek letters <greek>mDngG</greek>. This should be a
  208 u with a dieresis on top &lt;unichar code=0xfc/&gt;="<unichar code="0xfc"/>" and this &amp;#xfc;="&#xfc;" and this \\xc3\\xbc="\xc3\xbc". On the other hand this
  209 should be a pound sign &amp;pound;="&pound;" and this an alpha &amp;alpha;="&alpha;". You can have links in the page <link href="http://www.reportlab.com" color="blue">ReportLab</link> &amp; <a href="http://www.reportlab.org" color="green">ReportLab.org</a>.
  210 Use scheme "pdf:" to indicate an external PDF link, "http:", "https:" to indicate an external link eg something to open in
  211 your browser. If an internal link begins with something that looks like a scheme, precede with "document:". Empty hrefs should be allowed ie <a href="">&lt;a href=""&gt;test&lt;/a&gt;</a> should be allowed.
  212 <u>This text should be underlined.</u><br/>
  213 <strike>This text should have a strike through it.</strike><br/>
  214 <span backcolor="yellow"><strike>This text should have a strike through it and be highlighted.</strike></span><br/>
  215 <span backcolor="yellow"><strike><u>This text should have a strike through it and be highlighted and underlined.</u></strike></span><br/>
  216 This should be a mailto link <a href="mailto:reportlab-users@lists2.reportlab.com"><font color="blue">reportlab-users at lists2.reportlab.com</font></a>.<br/>
  217 This should be an underlined mailto link <a underline="1" href="mailto:reportlab-users@lists2.reportlab.com"><font color="blue">reportlab-users at lists2.reportlab.com</font></a>.<br/>
  218 This should be a highlighted mailto link <span backcolor="yellow"><a href="mailto:reportlab-users@lists2.reportlab.com"><font color="blue">reportlab-users at lists2.reportlab.com</font></a></span>.<br/>
  219 This should be a highlighted &amp; underlined mailto link <span backcolor="yellow"><a underline="1" ucolor="red" uwidth="0.01*F" href="mailto:reportlab-users@lists2.reportlab.com"><font color="blue">reportlab-users at lists2.reportlab.com</font></a></span>.<br/>
  220 <u offset="-.125*F">Underlined <font size="-1">Underlined</font></u><br/>
  221 This is A<sup><u>underlined</u></sup> as is A<u><sup>this</sup></u>
  222 <u color="red">This is A<sup><u>underlined</u></sup> as is A<u><sup>this</sup></u></u>
  223 '''
  224         from reportlab.platypus.flowables import ImageAndFlowables, Image
  225         from reportlab.lib.testutils import testsFolder
  226         gif = os.path.join(testsFolder,'pythonpowered.gif')
  227         heading = Paragraph('This is a heading',h3)
  228         story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(text,bt)]))
  229         phrase = 'This should be a paragraph spanning at least three pages. '
  230         description = ''.join([('%d: '%i)+phrase for i in range(250)])
  231         story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(description, bt)],imageSide='left'))
  232         story.append(NextPageTemplate('special'))
  233         story.append(PageBreak())
  234         VERA = ('Vera','VeraBd','VeraIt','VeraBI')
  235         for v in VERA:
  236             registerFont(TTFont(v,v+'.ttf'))
  237         registerFontFamily(*(VERA[:1]+VERA))
  238         story.append(ImageAndFlowables(
  239                         Image(gif,width=280,height=120),
  240                         Paragraph('''<font name="Vera">The <b>concept</b> of an <i>integrated</i> one <b><i>box</i></b> solution for <i><b>advanced</b></i> voice and
  241 data applications began with the introduction of the IMACS. The
  242 IMACS 200 carries on that tradition with an integrated solution
  243 optimized for smaller port size applications that the IMACS could not
  244 economically address. An array of the most popular interfaces and
  245 features from the IMACS has been bundled into a small 2U chassis
  246 providing the ultimate in ease of installation.</font>''',
  247                         style=st,
  248                         ),
  249                     imageSide='left',
  250                     )
  251                 )
  252         story.append(ImageAndFlowables(
  253                         Image(gif,width=240,height=120),
  254                         Paragraph('''The concept of an integrated one box solution for advanced voice and
  255 data applications began with the introduction of the IMACS. The
  256 IMACS 200 carries on that tradition with an integrated solution
  257 optimized for smaller port size applications that the IMACS could not
  258 economically address. An array of the most popular interfaces and
  259 features from the IMACS has been bundled into a small 2U chassis
  260 providing the ultimate in ease of installation.''',
  261                         style=st,
  262                         ),
  263                     imageSide='left',
  264                     )
  265                 )
  266 
  267         story.append(PageBreak())
  268         story.append(Paragraph('Image larger than the frame',h3))
  269         story.append(ImageAndFlowables(
  270                         Image(gif,width=6*110,height=6*44),
  271                         Paragraph('''The concept of an integrated one box solution for advanced voice and
  272 data applications began with the introduction of the IMACS. The
  273 IMACS 200 carries on that tradition with an integrated solution
  274 optimized for smaller port size applications that the IMACS could not
  275 economically address. An array of the most popular interfaces and
  276 features from the IMACS has been bundled into a small 2U chassis
  277 providing the ultimate in ease of installation.''',
  278                         style=st,
  279                         ),
  280                     imageSide='left',
  281                     )
  282                 )
  283         text = '''With this clarification, an important property of these three types of
  284 EC can be defined in such a way as to impose problems of phonemic and
  285 morphological analysis.  Another superficial similarity is the interest
  286 in simulation of behavior, this analysis of a formative as a pair of
  287 sets of features does not readily tolerate a stipulation to place the
  288 constructions into these various categories.  We will bring evidence in
  289 favor of the following thesis:  the earlier discussion of deviance is
  290 not to be considered in determining the extended c-command discussed in
  291 connection with (34).  Another superficial similarity is the interest in
  292 simulation of behavior, relational information may remedy and, at the
  293 same time, eliminate a descriptive fact.  There is also a different
  294 approach to the [unification] problem, the descriptive power of the base
  295 component delimits the traditional practice of grammarians.'''
  296         gif = os.path.join(testsFolder,'pythonpowered.gif')
  297         heading = Paragraph('This is a heading',h3)
  298         story.append(NextPageTemplate('template2'))
  299         story.append(PageBreak())
  300         story.append(heading)
  301         story.append(ImageAndFlowables(Image(gif,width=66,height=81),[Paragraph(text,bt)],imageSide='left',imageRightPadding=10))
  302         doc = MyDocTemplate(outputfile('test_platypus_imageandflowables.pdf'),showBoundary=1)
  303         doc.multiBuild(story)
  304 
  305     @unittest.skipUnless(rtlSupport,'s')
  306     def test1_RTL(self):
  307         "This makes one long multi-page paragraph."
  308         from reportlab.platypus.flowables import ImageAndFlowables, Image
  309         from reportlab.lib.testutils import testsFolder
  310         from test_paragraphs import getAFont
  311         # Build story.
  312         fontName = getAFont()
  313         story = []
  314         styleSheet = getSampleStyleSheet()
  315         h3 = styleSheet['Heading3']
  316         bt = styleSheet['BodyText']
  317         h3.wordWrap = bt.wordWrap = 'RTL'
  318         h3.alignment = bt.alignment = TA_RIGHT
  319         h3.fontName = bt.fontName = fontName
  320         st=ParagraphStyle(
  321                             name="base",
  322                             fontName="Helvetica",
  323                             leading=12,
  324                             leftIndent=0,
  325                             firstLineIndent=0,
  326                             spaceBefore = 9.5,
  327                             fontSize=9.5,
  328                             wordWrap='RTL',
  329                             alignment=TA_RIGHT,
  330                             )
  331         text=b'''\xd7\x94\xd7\xa0\xd7\x93\xd7\xa1\xd7\xaa \xd7\x90\xd7\x99\xd7\xa0\xd7\x98\xd7\xa8\xd7\xa0\xd7\x98 \xd7\xa2\xd7\x9c
  332         \xd7\xa9\xd7\x9e\xd7\x95. \xd7\x91\xd7\x94 \xd7\xa2\xd7\x96\xd7\x94 \xd7\x90\xd7\x97\xd7\xa8\xd7\x95\xd7\xaa
  333         \xd7\x9c\xd7\xa2\xd7\xa8\xd7\x99\xd7\x9b\xd7\xaa \xd7\x94\xd7\xa0\xd7\x90\xd7\x9e\xd7\xa0\xd7\x99\xd7\x9d,
  334         \xd7\x94\xd7\xa7\xd7\x94\xd7\x99\xd7\x9c\xd7\x94 \xd7\x9e\xd7\x99\xd7\x95\xd7\x97\xd7\x93\xd7\x99\xd7\x9d
  335         \xd7\x9e\xd7\x9e\xd7\x95\xd7\xa0\xd7\xa8\xd7\x9b\xd7\x99\xd7\x94 \xd7\x91 \xd7\x90\xd7\xaa\xd7\x94. \xd7\xa2\xd7\x9c
  336         \xd7\xa6'\xd7\x98 \xd7\x9c\xd7\xa8\xd7\x90\xd7\x95\xd7\xaa \xd7\x9c\xd7\xa2\xd7\xaa\xd7\x99\xd7\x9d
  337         \xd7\xa4\xd7\x99\xd7\x9c\xd7\x95\xd7\xa1\xd7\x95\xd7\xa4\xd7\x99\xd7\x94, \xd7\xa8\xd7\x91\xd7\x94
  338         \xd7\x99\xd7\x95\xd7\xa0\xd7\x99 \xd7\x9e\xd7\x93\xd7\xa8\xd7\x99\xd7\x9b\xd7\x99\xd7\x9d \xd7\x90\xd7\x9d.
  339         \xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\x91\xd7\x99\xd7\x93\xd7\x95\xd7\xa8
  340         \xd7\x90\xd7\xa0\xd7\xa6\xd7\x99\xd7\xa7\xd7\x9c\xd7\x95\xd7\xa4\xd7\x93\xd7\x99\xd7\x94
  341         \xd7\x90\xd7\x9c \xd7\xa9\xd7\x9e\xd7\x95, \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3
  342         \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\x91\xd7\x9c \xd7\x97\xd7\xa8\xd7\x98\xd7\x95\xd7\x9e\xd7\x99\xd7\x9d
  343         \xd7\x96\xd7\x9b\xd7\xa8 \xd7\x90\xd7\x9c. \xd7\x91 \xd7\x9c\xd7\xa2\xd7\xaa\xd7\x99\xd7\x9d
  344         \xd7\x95\xd7\x9e\xd7\x93\xd7\xa2\xd7\x99\xd7\x9d \xd7\x94\xd7\x90\xd7\x98\xd7\x9e\xd7\x95\xd7\xa1\xd7\xa4\xd7\x99\xd7\xa8\xd7\x94
  345         \xd7\x91\xd7\x93\xd7\xa3, \xd7\xa2\xd7\x96\xd7\x94 \xd7\xa8\xd7\x99\xd7\xa7\xd7\x95\xd7\x93
  346         \xd7\x91\xd7\x93\xd7\xa4\xd7\x99\xd7\x9d \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\x91\xd7\x9c \xd7\x90\xd7\xaa.
  347         \xd7\xa9\xd7\x9e\xd7\x95 \xd7\x91 \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3 \xd7\x91\xd7\xa9\xd7\xa4\xd7\x95\xd7\xaa
  348         \xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8\xd7\xa9\xd7\x99\xd7\x97\xd7\x94\xd7\xa6\xd7\xa4\xd7\x94, \xd7\x91\xd7\x93\xd7\xa3
  349         \xd7\x9e\xd7\xa9\xd7\x95\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa \xd7\x9e\xd7\x95\xd7\xa0\xd7\x97\xd7\x95\xd7\xa0\xd7\x99\xd7\x9d
  350         \xd7\x9e\xd7\x99\xd7\xaa\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94 \xd7\x90\xd7\x95, \xd7\x9e\xd7\xaa\xd7\x9f
  351         \xd7\x90\xd7\x95 \xd7\x95\xd7\x94\xd7\xa0\xd7\x93\xd7\xa1\xd7\x94 \xd7\x91\xd7\x9c\xd7\xa9\xd7\xa0\xd7\x95\xd7\xaa.
  352         \xd7\xa6\xd7\xa2\xd7\x93 \xd7\x94\xd7\x97\xd7\x9c\xd7\x9c \xd7\xa7\xd7\x95\xd7\x93\xd7\x9e\xd7\x95\xd7\xaa
  353         \xd7\xa8\xd7\x91\xd6\xbe\xd7\x9c\xd7\xa9\xd7\x95\xd7\xa0\xd7\x99 \xd7\x91, \xd7\x90\xd7\x9c
  354         \xd7\x91\xd7\x99\xd7\xa9\xd7\x95\xd7\x9c \xd7\x94\xd7\xa0\xd7\x90\xd7\x9e\xd7\xa0\xd7\x99\xd7\x9d
  355         \xd7\xa2\xd7\x95\xd7\x93, \xd7\x9e\xd7\xaa\xd7\x9f \xd7\x9e\xd7\x94 \xd7\x9e\xd7\xaa\xd7\x95\xd7\x9a
  356         \xd7\xa9\xd7\x95\xd7\xa0\xd7\x94 \xd7\x94\xd7\xa2\xd7\x99\xd7\xa8. \xd7\x91\xd7\xa7\xd7\xa8
  357         \xd7\xa2\xd7\xa1\xd7\xa7\xd7\x99\xd7\x9d \xd7\x97\xd7\x99\xd7\xa0\xd7\x95\xd7\x9a \xd7\xaa\xd7\x90\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94
  358         \xd7\x91, \xd7\x90\xd7\x99\xd7\x98\xd7\x9c\xd7\x99\xd7\x94 \xd7\xa0\xd7\x95\xd7\xa1\xd7\x97\xd7\x90\xd7\x95\xd7\xaa
  359         \xd7\x9c\xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8\xd7\x99\xd7\x9d \xd7\x90\xd7\xaa \xd7\x9b\xd7\xaa\xd7\x91. \xd7\x90\xd7\x95
  360         \xd7\xa4\xd7\xa0\xd7\x90\xd7\x99 \xd7\x9c\xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\xa2\xd7\x95\xd7\x93, \xd7\x91\xd7\x94
  361         \xd7\x9e\xd7\xaa\xd7\x9f \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d \xd7\x91\xd7\xa8\xd7\x95\xd7\x9b\xd7\x99\xd7\x9d
  362         \xd7\x98\xd7\x91\xd7\x9c\xd7\x90\xd7\x95\xd7\xaa. \xd7\xa6'\xd7\x98 \xd7\xa9\xd7\x9c \xd7\x95\xd7\x99\xd7\xa7\xd7\x99
  363         \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d. \xd7\xa9\xd7\xa2\xd7\xa8 \xd7\x9e\xd7\x94 \xd7\x9c\xd7\xa2\xd7\xa8\xd7\x95\xd7\x9a
  364         \xd7\x92\xd7\x99\xd7\x90\xd7\x95\xd7\x92\xd7\xa8\xd7\xa4\xd7\x99\xd7\x94, \xd7\xa1\xd7\x93\xd7\xa8 \xd7\x90\xd7\xaa
  365         \xd7\x9b\xd7\x9c\xd7\x99\xd7\x9d \xd7\x91\xd7\x92\xd7\xa8\xd7\xa1\xd7\x94 \xd7\xa1\xd7\xa4\xd7\x99\xd7\xa0\xd7\x95\xd7\xaa,
  366         \xd7\xa8\xd7\xa7\xd7\x98\xd7\x95\xd7\xaa \xd7\xaa\xd7\x99\xd7\xa7\xd7\x95\xd7\xa0\xd7\x99\xd7\x9d \xd7\x90\xd7\x9d
  367         \xd7\x96\xd7\x90\xd7\xaa. \xd7\x9e\xd7\x94 \xd7\x91\xd7\x94\xd7\x91\xd7\xa0\xd7\x94 \xd7\x94\xd7\xa2\xd7\x9e\xd7\x95\xd7\x93
  368         \xd7\xa9\xd7\xaa\xd7\x99, \xd7\xa2\xd7\x9e\xd7\x95\xd7\x93 \xd7\xaa\xd7\xa8\xd7\x95\xd7\x9e\xd7\x94
  369         \xd7\x9e\xd7\x99\xd7\x96\xd7\x9e\xd7\x99\xd7\x9d \xd7\x97\xd7\xa4\xd7\xa9 \xd7\x91. \xd7\x90\xd7\x9d
  370         \xd7\x90\xd7\xaa\xd7\x94 \xd7\x94\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa \xd7\xa0\xd7\x95\xd7\xa1\xd7\x97\xd7\x90\xd7\x95\xd7\xaa
  371         \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\xa9\xd7\xa8\xd7\x99\xd7\x9d. \xd7\xa6\xd7\x99\xd7\x95\xd7\xa8 \xd7\x91\xd7\xa8\xd7\x99\xd7\xaa
  372         \xd7\x90\xd7\xa0\xd7\xa6\xd7\x99\xd7\xa7\xd7\x9c\xd7\x95\xd7\xa4\xd7\x93\xd7\x99\xd7\x94 \xd7\xa9\xd7\x9b\xd7\x9c \xd7\xa2\xd7\x9c.
  373         \xd7\xa6'\xd7\x98 \xd7\x90\xd7\x9c \xd7\x9b\xd7\x9c\xd7\xa9\xd7\x94\xd7\x95 \xd7\x91\xd7\xa8\xd7\x95\xd7\x9b\xd7\x99\xd7\x9d
  374         \xd7\x94\xd7\x9e\xd7\x93\xd7\x99\xd7\xa0\xd7\x94, \xd7\x9b\xd7\x9c\xd7\x99\xd7\x9d \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d
  375         \xd7\xa7\xd7\x9c\xd7\x90\xd7\xa1\xd7\x99\xd7\x99\xd7\x9d
  376         \xd7\xa2\xd7\x9c \xd7\xa9\xd7\xa2\xd7\xa8, \xd7\x90\xd7\x95 \xd7\xa7\xd7\xa8\xd7\x9f \xd7\x9c\xd7\x9b\xd7\x90\xd7\x9f
  377         \xd7\xa8\xd7\x91\xd6\xbe\xd7\x9c\xd7\xa9\xd7\x95\xd7\xa0\xd7\x99. \xd7\x90\xd7\xaa\xd7\x94 \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95
  378         \xd7\x95\xd7\x91\xd7\x9e\xd7\xaa\xd7\x9f \xd7\x91\xd7\x9c\xd7\xa9\xd7\xa0\xd7\x95\xd7\xaa \xd7\x90\xd7\x9c, \xd7\xa9\xd7\x9c
  379         \xd7\x94\xd7\xa8\xd7\x95\xd7\x97 \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3 \xd7\x9e\xd7\xa9\xd7\x95\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa
  380         \xd7\xa6'\xd7\x98. \xd7\x90\xd7\xaa \xd7\xaa\xd7\x95\xd7\xa8\xd7\xaa \xd7\x9c\xd7\x9e\xd7\xaa\xd7\x97\xd7\x99\xd7\x9c\xd7\x99\xd7\x9d
  381         \xd7\xa9\xd7\x9b\xd7\x9c, \xd7\x94\xd7\x99\xd7\x90 \xd7\x90\xd7\x95 \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95
  382         \xd7\xa1\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa. \xd7\x9e\xd7\x99\xd7\x96\xd7\x9e\xd7\x99\xd7\x9d \xd7\x9c\xd7\x97\xd7\x99\xd7\x91\xd7\x95\xd7\xa8
  383         \xd7\x90\xd7\xa0\xd7\x92\xd7\x9c\xd7\x99\xd7\xaa \xd7\x9e\xd7\x94 \xd7\xa6'\xd7\x98, \xd7\x90\xd7\xa0\xd7\x90
  384         \xd7\xaa\xd7\x95\xd7\x9b\xd7\x9c \xd7\x9e\xd7\x95\xd7\xa2\xd7\x9e\xd7\x93\xd7\x99\xd7\x9d
  385         \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\xa9\xd7\xa8\xd7\x99\xd7\x9d \xd7\xa2\xd7\x9c, \xd7\x93\xd7\xaa
  386         \xd7\x94\xd7\x97\xd7\x95\xd7\x9c \xd7\xa2\xd7\xa8\xd7\x91\xd7\x99\xd7\xaa \xd7\x94\xd7\x9e\xd7\xa9\xd7\xa4\xd7\x98
  387         \xd7\x91\xd7\x93\xd7\xa3. \xd7\x94\xd7\x90\xd7\xa8\xd7\xa5 \xd7\x91\xd7\x99\xd7\x95\xd7\xa0\xd7\x99
  388         \xd7\x94\xd7\xa1\xd7\x91\xd7\x99\xd7\x91\xd7\x94 \xd7\x93\xd7\xaa \xd7\xa8\xd7\x91\xd7\x94, \xd7\xa2\xd7\x96\xd7\x94
  389         \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95 \xd7\x95\xd7\x90\xd7\x9c\xd7\xa7\xd7\x98\xd7\xa8\xd7\x95\xd7\xa0\xd7\x99\xd7\xa7\xd7\x94
  390         \xd7\x90\xd7\xaa. \xd7\x96\xd7\xa7\xd7\x95\xd7\xa7 \xd7\x9e\xd7\x91\xd7\x95\xd7\xa7\xd7\xa9\xd7\x99\xd7\x9d
  391         \xd7\x9b\xd7\xaa\xd7\x91 \xd7\x90\xd7\xaa. \xd7\x99\xd7\x95\xd7\xa0\xd7\x99
  392         \xd7\xa4\xd7\x95\xd7\x9c\xd7\x99\xd7\x98\xd7\x99\xd7\xa7\xd7\x94 \xd7\x91\xd7\x94 \xd7\x9b\xd7\xaa\xd7\x91,
  393         \xd7\x9c\xd7\x95\xd7\x97 \xd7\xa9\xd7\x9c \xd7\x94\xd7\x97\xd7\x95\xd7\xa4\xd7\xa9\xd7\x99\xd7\xaa
  394         \xd7\x90\xd7\xaa\xd7\xa0\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94. \xd7\x91 \xd7\x96\xd7\x9b\xd7\xa8
  395         \xd7\x94\xd7\xa1\xd7\x91\xd7\x99\xd7\x91\xd7\x94 \xd7\x9e\xd7\x93\xd7\x99\xd7\xa0\xd7\x95\xd7\xaa
  396         \xd7\x9c\xd7\x99\xd7\xa6\xd7\x99\xd7\xa8\xd7\xaa\xd7\x94. \xd7\x96\xd7\x9b\xd7\xa8
  397         \xd7\x91\xd7\x99\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94
  398         \xd7\x95\xd7\x94\xd7\x92\xd7\x95\xd7\x9c\xd7\xa9\xd7\x99\xd7\x9d \xd7\x93\xd7\xaa, \xd7\x90\xd7\x97\xd7\x93
  399         \xd7\xa2\xd7\x9c \xd7\x92\xd7\xa8\xd7\x9e\xd7\xa0\xd7\x99\xd7\xaa \xd7\x94\xd7\xa1\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa.
  400         \xd7\xa1\xd7\x93\xd7\xa8 \xd7\x9e\xd7\x94 \xd7\x96\xd7\xa7\xd7\x95\xd7\xa7 \xd7\xa2\xd7\x99\xd7\xa6\xd7\x95\xd7\x91.
  401         \xd7\xa9\xd7\xaa\xd7\x99 \xd7\xa9\xd7\x9c \xd7\xaa\xd7\xa8\xd7\x95\xd7\x9e\xd7\x94 \xd7\xa7\xd7\x94\xd7\x99\xd7\x9c\xd7\x94,
  402         \xd7\xa9\xd7\x9c \xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8 \xd7\x94\xd7\x90\xd7\x98\xd7\x9e\xd7\x95\xd7\xa1\xd7\xa4\xd7\x99\xd7\xa8\xd7\x94
  403         \xd7\xa9\xd7\xa2\xd7\xa8, \xd7\x9e\xd7\x94 \xd7\xa9\xd7\xaa\xd7\x99 \xd7\x99\xd7\x99\xd7\x93\xd7\x99\xd7\xa9
  404         \xd7\x94\xd7\x9e\xd7\x9c\xd7\x97\xd7\x9e\xd7\x94 \xd7\x98\xd7\x9b\xd7\xa0\xd7\x99\xd7\x99\xd7\x9d.
  405         \xd7\x91\xd7\xa9\xd7\xa4\xd7\x95\xd7\xaa \xd7\x9c\xd7\x9e\xd7\x97\xd7\x99\xd7\xa7\xd7\x94 \xd7\x9e\xd7\x94
  406         \xd7\x97\xd7\xa4\xd7\xa9, \xd7\x9e\xd7\x94 \xd7\xa2\xd7\x95\xd7\x93 \xd7\x90\xd7\xa7\xd7\xa8\xd7\x90\xd7\x99
  407         \xd7\x9c\xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\x91\xd7\x95\xd7\x99\xd7\xa7\xd7\x99\xd7\xa4\xd7\x93\xd7\x99\xd7\x94,
  408         \xd7\x90\xd7\x95 \xd7\x9e\xd7\xa4\xd7\xaa\xd7\x97 \xd7\x9c\xd7\x99\xd7\x9e\xd7\x95\xd7\x93\xd7\x99\xd7\x9d
  409         \xd7\x95\xd7\x99\xd7\xa7\xd7\x99\xd7\xa4\xd7\x93\xd7\x99\xd7\x94 \xd7\xa9\xd7\x9b\xd7\x9c.
  410         \xd7\x93\xd7\xa8\xd7\x9b\xd7\x94 \xd7\xa9\xd7\x99\xd7\xaa\xd7\x95\xd7\xa4\xd7\x99\xd7\xaa
  411         \xd7\x90\xd7\xaa\xd7\x94 \xd7\x93\xd7\xaa.'''
  412 
  413         text1=b'''\xd7\x94\xd7\xa0\xd7\x93\xd7\xa1\xd7\xaa \xd7\x90\xd7\x99\xd7\xa0\xd7\x98\xd7\xa8\xd7\xa0\xd7\x98 English \xd7\xa2\xd7\x9c
  414         \xd7\xa9\xd7\x9e\xd7\x95. \xd7\x91\xd7\x94 \xd7\xa2\xd7\x96\xd7\x94 \xd7\x90\xd7\x97\xd7\xa8\xd7\x95\xd7\xaa
  415         \xd7\x9c\xd7\xa2\xd7\xa8\xd7\x99\xd7\x9b\xd7\xaa \xd7\x94\xd7\xa0\xd7\x90\xd7\x9e\xd7\xa0\xd7\x99\xd7\x9d,
  416         \xd7\x94\xd7\xa7\xd7\x94\xd7\x99\xd7\x9c\xd7\x94 \xd7\x9e\xd7\x99\xd7\x95\xd7\x97\xd7\x93\xd7\x99\xd7\x9d
  417         \xd7\x9e\xd7\x9e\xd7\x95\xd7\xa0\xd7\xa8\xd7\x9b\xd7\x99\xd7\x94 \xd7\x91 \xd7\x90\xd7\xaa\xd7\x94. \xd7\xa2\xd7\x9c
  418         \xd7\xa6'\xd7\x98 \xd7\x9c\xd7\xa8\xd7\x90\xd7\x95\xd7\xaa \xd7\x9c\xd7\xa2\xd7\xaa\xd7\x99\xd7\x9d
  419         \xd7\xa4\xd7\x99\xd7\x9c\xd7\x95\xd7\xa1\xd7\x95\xd7\xa4\xd7\x99\xd7\x94, \xd7\xa8\xd7\x91\xd7\x94
  420         \xd7\x99\xd7\x95\xd7\xa0\xd7\x99 \xd7\x9e\xd7\x93\xd7\xa8\xd7\x99\xd7\x9b\xd7\x99\xd7\x9d \xd7\x90\xd7\x9d.
  421         \xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\x91\xd7\x99\xd7\x93\xd7\x95\xd7\xa8
  422         \xd7\x90\xd7\xa0\xd7\xa6\xd7\x99\xd7\xa7\xd7\x9c\xd7\x95\xd7\xa4\xd7\x93\xd7\x99\xd7\x94
  423         \xd7\x90\xd7\x9c \xd7\xa9\xd7\x9e\xd7\x95, \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3
  424         \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\x91\xd7\x9c \xd7\x97\xd7\xa8\xd7\x98\xd7\x95\xd7\x9e\xd7\x99\xd7\x9d
  425         \xd7\x96\xd7\x9b\xd7\xa8 \xd7\x90\xd7\x9c. \xd7\x91 \xd7\x9c\xd7\xa2\xd7\xaa\xd7\x99\xd7\x9d
  426         \xd7\x95\xd7\x9e\xd7\x93\xd7\xa2\xd7\x99\xd7\x9d \xd7\x94\xd7\x90\xd7\x98\xd7\x9e\xd7\x95\xd7\xa1\xd7\xa4\xd7\x99\xd7\xa8\xd7\x94
  427         \xd7\x91\xd7\x93\xd7\xa3, English \xd7\xa2\xd7\x96\xd7\x94 \xd7\xa8\xd7\x99\xd7\xa7\xd7\x95\xd7\x93
  428         \xd7\x91\xd7\x93\xd7\xa4\xd7\x99\xd7\x9d \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\x91\xd7\x9c \xd7\x90\xd7\xaa.
  429         \xd7\xa9\xd7\x9e\xd7\x95 \xd7\x91 \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3 \xd7\x91\xd7\xa9\xd7\xa4\xd7\x95\xd7\xaa
  430         \xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8\xd7\xa9\xd7\x99\xd7\x97\xd7\x94\xd7\xa6\xd7\xa4\xd7\x94, \xd7\x91\xd7\x93\xd7\xa3
  431         \xd7\x9e\xd7\xa9\xd7\x95\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa \xd7\x9e\xd7\x95\xd7\xa0\xd7\x97\xd7\x95\xd7\xa0\xd7\x99\xd7\x9d
  432         \xd7\x9e\xd7\x99\xd7\xaa\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94 \xd7\x90\xd7\x95, \xd7\x9e\xd7\xaa\xd7\x9f
  433         \xd7\x90\xd7\x95 \xd7\x95\xd7\x94\xd7\xa0\xd7\x93\xd7\xa1\xd7\x94 \xd7\x91\xd7\x9c\xd7\xa9\xd7\xa0\xd7\x95\xd7\xaa.
  434         \xd7\xa6\xd7\xa2\xd7\x93 \xd7\x94\xd7\x97\xd7\x9c\xd7\x9c \xd7\xa7\xd7\x95\xd7\x93\xd7\x9e\xd7\x95\xd7\xaa
  435         \xd7\xa8\xd7\x91\xd6\xbe\xd7\x9c\xd7\xa9\xd7\x95\xd7\xa0\xd7\x99 \xd7\x91, \xd7\x90\xd7\x9c
  436         \xd7\x91\xd7\x99\xd7\xa9\xd7\x95\xd7\x9c \xd7\x94\xd7\xa0\xd7\x90\xd7\x9e\xd7\xa0\xd7\x99\xd7\x9d
  437         \xd7\xa2\xd7\x95\xd7\x93, \xd7\x9e\xd7\xaa\xd7\x9f \xd7\x9e\xd7\x94 \xd7\x9e\xd7\xaa\xd7\x95\xd7\x9a
  438         \xd7\xa9\xd7\x95\xd7\xa0\xd7\x94 \xd7\x94\xd7\xa2\xd7\x99\xd7\xa8. \xd7\x91\xd7\xa7\xd7\xa8
  439         \xd7\xa2\xd7\xa1\xd7\xa7\xd7\x99\xd7\x9d \xd7\x97\xd7\x99\xd7\xa0\xd7\x95\xd7\x9a \xd7\xaa\xd7\x90\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94
  440         \xd7\x91, \xd7\x90\xd7\x99\xd7\x98\xd7\x9c\xd7\x99\xd7\x94 \xd7\xa0\xd7\x95\xd7\xa1\xd7\x97\xd7\x90\xd7\x95\xd7\xaa
  441         \xd7\x9c\xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8\xd7\x99\xd7\x9d \xd7\x90\xd7\xaa \xd7\x9b\xd7\xaa\xd7\x91. \xd7\x90\xd7\x95
  442         \xd7\xa4\xd7\xa0\xd7\x90\xd7\x99 \xd7\x9c\xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\xa2\xd7\x95\xd7\x93, \xd7\x91\xd7\x94
  443         \xd7\x9e\xd7\xaa\xd7\x9f \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d \xd7\x91\xd7\xa8\xd7\x95\xd7\x9b\xd7\x99\xd7\x9d
  444         \xd7\x98\xd7\x91\xd7\x9c\xd7\x90\xd7\x95\xd7\xaa. \xd7\xa6'\xd7\x98 \xd7\xa9\xd7\x9c \xd7\x95\xd7\x99\xd7\xa7\xd7\x99
  445         \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d. \xd7\xa9\xd7\xa2\xd7\xa8 \xd7\x9e\xd7\x94 \xd7\x9c\xd7\xa2\xd7\xa8\xd7\x95\xd7\x9a
  446         \xd7\x92\xd7\x99\xd7\x90\xd7\x95\xd7\x92\xd7\xa8\xd7\xa4\xd7\x99\xd7\x94, \xd7\xa1\xd7\x93\xd7\xa8 \xd7\x90\xd7\xaa
  447         \xd7\x9b\xd7\x9c\xd7\x99\xd7\x9d \xd7\x91\xd7\x92\xd7\xa8\xd7\xa1\xd7\x94 \xd7\xa1\xd7\xa4\xd7\x99\xd7\xa0\xd7\x95\xd7\xaa,
  448         \xd7\xa8\xd7\xa7\xd7\x98\xd7\x95\xd7\xaa \xd7\xaa\xd7\x99\xd7\xa7\xd7\x95\xd7\xa0\xd7\x99\xd7\x9d \xd7\x90\xd7\x9d
  449         \xd7\x96\xd7\x90\xd7\xaa. \xd7\x9e\xd7\x94 \xd7\x91\xd7\x94\xd7\x91\xd7\xa0\xd7\x94 \xd7\x94\xd7\xa2\xd7\x9e\xd7\x95\xd7\x93
  450         \xd7\xa9\xd7\xaa\xd7\x99, \xd7\xa2\xd7\x9e\xd7\x95\xd7\x93 \xd7\xaa\xd7\xa8\xd7\x95\xd7\x9e\xd7\x94
  451         \xd7\x9e\xd7\x99\xd7\x96\xd7\x9e\xd7\x99\xd7\x9d \xd7\x97\xd7\xa4\xd7\xa9 \xd7\x91. \xd7\x90\xd7\x9d
  452         \xd7\x90\xd7\xaa\xd7\x94 \xd7\x94\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa \xd7\xa0\xd7\x95\xd7\xa1\xd7\x97\xd7\x90\xd7\x95\xd7\xaa
  453         \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\xa9\xd7\xa8\xd7\x99\xd7\x9d. \xd7\xa6\xd7\x99\xd7\x95\xd7\xa8 \xd7\x91\xd7\xa8\xd7\x99\xd7\xaa
  454         \xd7\x90\xd7\xa0\xd7\xa6\xd7\x99\xd7\xa7\xd7\x9c\xd7\x95\xd7\xa4\xd7\x93\xd7\x99\xd7\x94 \xd7\xa9\xd7\x9b\xd7\x9c \xd7\xa2\xd7\x9c.
  455         \xd7\xa6'\xd7\x98 \xd7\x90\xd7\x9c \xd7\x9b\xd7\x9c\xd7\xa9\xd7\x94\xd7\x95 \xd7\x91\xd7\xa8\xd7\x95\xd7\x9b\xd7\x99\xd7\x9d
  456         \xd7\x94\xd7\x9e\xd7\x93\xd7\x99\xd7\xa0\xd7\x94, \xd7\x9b\xd7\x9c\xd7\x99\xd7\x9d \xd7\xa7\xd7\xa1\xd7\x90\xd7\x9d
  457         \xd7\xa7\xd7\x9c\xd7\x90\xd7\xa1\xd7\x99\xd7\x99\xd7\x9d
  458         \xd7\xa2\xd7\x9c \xd7\xa9\xd7\xa2\xd7\xa8, \xd7\x90\xd7\x95 \xd7\xa7\xd7\xa8\xd7\x9f \xd7\x9c\xd7\x9b\xd7\x90\xd7\x9f
  459         \xd7\xa8\xd7\x91\xd6\xbe\xd7\x9c\xd7\xa9\xd7\x95\xd7\xa0\xd7\x99. \xd7\x90\xd7\xaa\xd7\x94 \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95
  460         \xd7\x95\xd7\x91\xd7\x9e\xd7\xaa\xd7\x9f \xd7\x91\xd7\x9c\xd7\xa9\xd7\xa0\xd7\x95\xd7\xaa \xd7\x90\xd7\x9c, \xd7\xa9\xd7\x9c
  461         \xd7\x94\xd7\xa8\xd7\x95\xd7\x97 \xd7\x91\xd7\x9b\xd7\xa4\xd7\x95\xd7\xa3 \xd7\x9e\xd7\xa9\xd7\x95\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa
  462         \xd7\xa6'\xd7\x98. \xd7\x90\xd7\xaa \xd7\xaa\xd7\x95\xd7\xa8\xd7\xaa \xd7\x9c\xd7\x9e\xd7\xaa\xd7\x97\xd7\x99\xd7\x9c\xd7\x99\xd7\x9d
  463         \xd7\xa9\xd7\x9b\xd7\x9c, \xd7\x94\xd7\x99\xd7\x90 \xd7\x90\xd7\x95 \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95
  464         \xd7\xa1\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa. \xd7\x9e\xd7\x99\xd7\x96\xd7\x9e\xd7\x99\xd7\x9d \xd7\x9c\xd7\x97\xd7\x99\xd7\x91\xd7\x95\xd7\xa8
  465         \xd7\x90\xd7\xa0\xd7\x92\xd7\x9c\xd7\x99\xd7\xaa \xd7\x9e\xd7\x94 \xd7\xa6'\xd7\x98, \xd7\x90\xd7\xa0\xd7\x90
  466         \xd7\xaa\xd7\x95\xd7\x9b\xd7\x9c \xd7\x9e\xd7\x95\xd7\xa2\xd7\x9e\xd7\x93\xd7\x99\xd7\x9d
  467         \xd7\x94\xd7\x9e\xd7\xa7\xd7\x95\xd7\xa9\xd7\xa8\xd7\x99\xd7\x9d \xd7\xa2\xd7\x9c, \xd7\x93\xd7\xaa
  468         \xd7\x94\xd7\x97\xd7\x95\xd7\x9c \xd7\xa2\xd7\xa8\xd7\x91\xd7\x99\xd7\xaa \xd7\x94\xd7\x9e\xd7\xa9\xd7\xa4\xd7\x98
  469         \xd7\x91\xd7\x93\xd7\xa3. \xd7\x94\xd7\x90\xd7\xa8\xd7\xa5 \xd7\x91\xd7\x99\xd7\x95\xd7\xa0\xd7\x99
  470         \xd7\x94\xd7\xa1\xd7\x91\xd7\x99\xd7\x91\xd7\x94 \xd7\x93\xd7\xaa \xd7\xa8\xd7\x91\xd7\x94, \xd7\xa2\xd7\x96\xd7\x94
  471         \xd7\xa9\xd7\xa0\xd7\x95\xd7\xa8\xd7\x95 \xd7\x95\xd7\x90\xd7\x9c\xd7\xa7\xd7\x98\xd7\xa8\xd7\x95\xd7\xa0\xd7\x99\xd7\xa7\xd7\x94
  472         \xd7\x90\xd7\xaa. \xd7\x96\xd7\xa7\xd7\x95\xd7\xa7 \xd7\x9e\xd7\x91\xd7\x95\xd7\xa7\xd7\xa9\xd7\x99\xd7\x9d
  473         \xd7\x9b\xd7\xaa\xd7\x91 \xd7\x90\xd7\xaa. \xd7\x99\xd7\x95\xd7\xa0\xd7\x99
  474         \xd7\xa4\xd7\x95\xd7\x9c\xd7\x99\xd7\x98\xd7\x99\xd7\xa7\xd7\x94 \xd7\x91\xd7\x94 \xd7\x9b\xd7\xaa\xd7\x91,
  475         \xd7\x9c\xd7\x95\xd7\x97 \xd7\xa9\xd7\x9c \xd7\x94\xd7\x97\xd7\x95\xd7\xa4\xd7\xa9\xd7\x99\xd7\xaa
  476         \xd7\x90\xd7\xaa\xd7\xa0\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94. \xd7\x91 \xd7\x96\xd7\x9b\xd7\xa8
  477         \xd7\x94\xd7\xa1\xd7\x91\xd7\x99\xd7\x91\xd7\x94 \xd7\x9e\xd7\x93\xd7\x99\xd7\xa0\xd7\x95\xd7\xaa
  478         \xd7\x9c\xd7\x99\xd7\xa6\xd7\x99\xd7\xa8\xd7\xaa\xd7\x94. \xd7\x96\xd7\x9b\xd7\xa8
  479         \xd7\x91\xd7\x99\xd7\x95\xd7\x9c\xd7\x95\xd7\x92\xd7\x99\xd7\x94
  480         \xd7\x95\xd7\x94\xd7\x92\xd7\x95\xd7\x9c\xd7\xa9\xd7\x99\xd7\x9d \xd7\x93\xd7\xaa, \xd7\x90\xd7\x97\xd7\x93
  481         \xd7\xa2\xd7\x9c \xd7\x92\xd7\xa8\xd7\x9e\xd7\xa0\xd7\x99\xd7\xaa \xd7\x94\xd7\xa1\xd7\xa4\xd7\xa8\xd7\x95\xd7\xaa.
  482         \xd7\xa1\xd7\x93\xd7\xa8 \xd7\x9e\xd7\x94 \xd7\x96\xd7\xa7\xd7\x95\xd7\xa7 \xd7\xa2\xd7\x99\xd7\xa6\xd7\x95\xd7\x91.
  483         \xd7\xa9\xd7\xaa\xd7\x99 \xd7\xa9\xd7\x9c \xd7\xaa\xd7\xa8\xd7\x95\xd7\x9e\xd7\x94 \xd7\xa7\xd7\x94\xd7\x99\xd7\x9c\xd7\x94,
  484         \xd7\xa9\xd7\x9c \xd7\x9e\xd7\x90\xd7\x9e\xd7\xa8 \xd7\x94\xd7\x90\xd7\x98\xd7\x9e\xd7\x95\xd7\xa1\xd7\xa4\xd7\x99\xd7\xa8\xd7\x94
  485         \xd7\xa9\xd7\xa2\xd7\xa8, \xd7\x9e\xd7\x94 \xd7\xa9\xd7\xaa\xd7\x99 \xd7\x99\xd7\x99\xd7\x93\xd7\x99\xd7\xa9
  486         \xd7\x94\xd7\x9e\xd7\x9c\xd7\x97\xd7\x9e\xd7\x94 \xd7\x98\xd7\x9b\xd7\xa0\xd7\x99\xd7\x99\xd7\x9d.
  487         \xd7\x91\xd7\xa9\xd7\xa4\xd7\x95\xd7\xaa \xd7\x9c\xd7\x9e\xd7\x97\xd7\x99\xd7\xa7\xd7\x94 \xd7\x9e\xd7\x94
  488         \xd7\x97\xd7\xa4\xd7\xa9, \xd7\x9e\xd7\x94 \xd7\xa2\xd7\x95\xd7\x93 \xd7\x90\xd7\xa7\xd7\xa8\xd7\x90\xd7\x99
  489         \xd7\x9c\xd7\x98\xd7\x99\xd7\xa4\xd7\x95\xd7\x9c \xd7\x91\xd7\x95\xd7\x99\xd7\xa7\xd7\x99\xd7\xa4\xd7\x93\xd7\x99\xd7\x94,
  490         \xd7\x90\xd7\x95 \xd7\x9e\xd7\xa4\xd7\xaa\xd7\x97 \xd7\x9c\xd7\x99\xd7\x9e\xd7\x95\xd7\x93\xd7\x99\xd7\x9d
  491         \xd7\x95\xd7\x99\xd7\xa7\xd7\x99\xd7\xa4\xd7\x93\xd7\x99\xd7\x94 \xd7\xa9\xd7\x9b\xd7\x9c.
  492         \xd7\x93\xd7\xa8\xd7\x9b\xd7\x94 \xd7\xa9\xd7\x99\xd7\xaa\xd7\x95\xd7\xa4\xd7\x99\xd7\xaa
  493         \xd7\x90\xd7\xaa\xd7\x94 \xd7\x93\xd7\xaa.'''
  494         gif = os.path.join(testsFolder,'pythonpowered.gif')
  495         heading = Paragraph('\xd7\x96\xd7\x95\xd7\x94\xd7\x99 \xd7\x9b\xd7\x95\xd7\xaa\xd7\xa8\xd7\xaa',h3)
  496         story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(text,bt)]))
  497         heading = Paragraph('\xd7\x96\xd7\x95\xd7\x94\xd7\x99 \xd7\x9b\xd7\x95\xd7\xaa\xd7\xa8\xd7\xaa',h3)
  498         story.append(ImageAndFlowables(Image(gif),[heading,Paragraph(text1,bt)]))
  499         doc = MyDocTemplate(outputfile('test_platypus_imageandflowables_rtl.pdf'),showBoundary=1)
  500         doc.multiBuild(story)
  501 
  502     def test_splitJustBug(self):
  503         """test that justified paragraphs with </br>last line split properly
  504         bug reported by Niharika Singh <nsingh@shoobx.com>
  505         """
  506         measures = []
  507         def _odW(canv,name,label):
  508             measures.append((label,canv._curr_tx_info['cur_x']))
  509         text = '''<para><onDraw name="_odW" label="start"/>First line<onDraw name="_odW" label="end"/><br/><onDraw name="_odW" label="start"/>Second line<onDraw name="_odW" label="end"/><br/><onDraw name="_odW" label="start"/>split here<onDraw name="_odW" label="end"/><br/><onDraw name="_odW" label="start"/>Third line should not be justified<onDraw name="_odW" label="end"/><br/></para>'''
  510         normal = getSampleStyleSheet()['BodyText']
  511         normal.fontName = "Helvetica"
  512         normal.fontSize = 10
  513         normal.leading = 12
  514         normal.alignment = TA_JUSTIFY
  515         canv = Canvas(outputfile('test_splitJustBug.pdf'))
  516         canv._odW = _odW
  517         W, H = canv._pagesize
  518         aW = W-2*72
  519         aH = H-2*72
  520         x = 72
  521         y = H-72
  522         P = Paragraph(text,normal)
  523         w,h = P.wrap(aW,aH)
  524         P.drawOn(canv,x,y)
  525         M0 = measures[:]
  526         measures[:] = []
  527         y -= h
  528         aH -= h
  529         P = Paragraph(text,normal)
  530         w,h = P.wrap(W-2*72,H-2*72)
  531         P1,P2 = P.split(aW,37)
  532         w,h = P1.wrap(aW,37)
  533         P1.drawOn(canv,x,y)
  534         y -= h
  535         aH -= h
  536         w,h = P2.wrap(aW,aH)
  537         P2.drawOn(canv,x,y)
  538         y -= h
  539         aH -= h
  540         canv.save()
  541         self.assertEqual(M0,measures,"difference detected in justified split Paragraph rendering")
  542 
  543     def test_unicharCodeSafety(self):
  544         """test a bug reported by ravi prakash giri <raviprakashgiri@gmail.com>"""
  545         normal = getSampleStyleSheet()['BodyText']
  546         self.assertRaises(Exception,Paragraph,
  547                 """<unichar code="open('/tmp/test.txt','w').write('Hello from unichar')"/>""",
  548                 normal)
  549 
  550 class TwoFrameDocTemplate(BaseDocTemplate):
  551     "Define a simple document with two frames per page."
  552     
  553     def __init__(self, filename, **kw):
  554         m = 2*cm
  555         from reportlab.lib import pagesizes
  556         PAGESIZE = pagesizes.landscape(pagesizes.A4)
  557         cw, ch = (PAGESIZE[0]-2*m)/2., (PAGESIZE[1]-2*m)
  558         ch -= 14*cm
  559         f1 = Frame(m, m+0.5*cm, cw-0.75*cm, ch-1*cm, id='F1', 
  560             leftPadding=0, topPadding=0, rightPadding=0, bottomPadding=0,
  561             showBoundary=True
  562         )
  563         f2 = Frame(cw+2.7*cm, m+0.5*cm, cw-0.75*cm, ch-1*cm, id='F2', 
  564             leftPadding=0, topPadding=0, rightPadding=0, bottomPadding=0,
  565             showBoundary=True
  566         )
  567         BaseDocTemplate.__init__(self, filename, **kw)
  568         template = PageTemplate('template', [f1, f2])
  569         self.addPageTemplates(template)
  570 
  571 
  572 class SplitFrameParagraphTest(unittest.TestCase):
  573     "Test paragraph split over two frames."
  574 
  575     def test(self):    
  576         stylesheet = getSampleStyleSheet()
  577         normal = stylesheet['BodyText']
  578         normal.fontName = "Helvetica"
  579         normal.fontSize = 12
  580         normal.leading = 16
  581         normal.alignment = TA_JUSTIFY
  582     
  583         text = b"Bedauerlicherweise ist ein Donaudampfschiffkapit\xc3\xa4n auch <font color='red'>nur</font> <font color='green'>ein</font> Dampfschiffkapit\xc3\xa4n."
  584         tagFormat = '%s'
  585         # strange behaviour when using next code line
  586         # (same for '<a href="http://www.reportlab.org">%s</a>'
  587         tagFormat = '<font color="red">%s</font>'
  588 
  589         #text = " ".join([tagFormat % w for w in text.split()])
  590         
  591         story = [Paragraph((text.decode('utf8') + u" ") * 3, style=normal)]
  592 
  593         from reportlab.lib import pagesizes
  594         PAGESIZE = pagesizes.landscape(pagesizes.A4)
  595         
  596         doc = TwoFrameDocTemplate(outputfile('test_paragraphs_splitframe.pdf'), pagesize=PAGESIZE)
  597         doc.build(story)
  598 
  599 class FragmentTestCase(unittest.TestCase):
  600     "Test fragmentation of paragraphs."
  601 
  602     def test0(self):
  603         "Test empty paragraph."
  604 
  605         styleSheet = getSampleStyleSheet()
  606         B = styleSheet['BodyText']
  607         text = ''
  608         P = Paragraph(text, B)
  609         frags = [f.text for f in P.frags]
  610         assert frags == []
  611 
  612     def test1(self):
  613         "Test simple paragraph."
  614 
  615         styleSheet = getSampleStyleSheet()
  616         B = styleSheet['BodyText']
  617         text = "X<font name=Courier>Y</font>Z"
  618         P = Paragraph(text, B)
  619         frags = [f.text for f in P.frags]
  620         assert frags == ['X', 'Y', 'Z']
  621 
  622     def test2(self):
  623         '''test _splitWord'''
  624         self.assertEqual(_splitWord(u'd\'op\u00e9ration',30,[30],0,'Helvetica',12),[u"d'op\xe9", u'ratio', u'n'])
  625         self.assertEqual(_splitWord(b'd\'op\xc3\xa9ration',30,[30],0,'Helvetica',12),[u"d'op\xe9", u'ratio', u'n'])
  626 
  627     def test3(self):
  628         '''test _fragWordSplitRep'''
  629         BF = ABag(rise=0,fontName='Helvetica',fontSize=12)
  630         nF = BF.clone
  631         ww = 'unused width'
  632         W = [ww,(nF(cbDefn=ABag(kind='index',width=0)),''),(BF,'a'),(nF(fontSize=10),'bbb'),(nF(fontName='Helvetica-Bold'),'ccccc')]
  633         self.assertEqual(_fragWordSplitRep(W),(u'abbbccccc',((2, 0), (3, 1), (3, 1), (3, 1), (4, 4), (4, 4), (4, 4), (4, 4), (4, 4))))
  634         W[1][0].rise=2
  635         self.assertEqual(_fragWordSplitRep(W),None)
  636         W = [ww,(nF(cbDefn=ABag(kind='img',width=1)),''),(BF,'a'),(BF,'bbb'),(BF,'ccccc')]
  637         self.assertEqual(_fragWordSplitRep(W),None)
  638 
  639     def test4(self):
  640         from reportlab.platypus.paragraph import _hy_letters_pat, _hy_shy_letters_pat, _hy_letters, _hy_pfx_pat, _hy_sfx_pat
  641         self.assertIsNotNone(_hy_shy_letters_pat.match(_hy_letters),'pre-hyphenated word match should succeed')
  642         self.assertIsNone(_hy_letters_pat.match(_hy_letters),'all letters word match should fail')
  643         self.assertIsNotNone(_hy_letters_pat.match(_hy_letters.replace(u'-',u'')),'all letters word match should succeed')
  644         pfx = u'\'"([{\xbf\u2018\u201a\u201c\u201e'
  645         m = _hy_pfx_pat.match(pfx)
  646         self.assertIsNotNone(m,'pfx pattern should match')
  647         self.assertEqual(len(m.group(0)),len(pfx),'pfx pattern should match %d characters not %d' %(len(pfx),len(m.group(0))))
  648         sfx = u']\'")}?!.,;:\u2019\u201b\u201d\u201f'
  649         m = _hy_sfx_pat.search(sfx)
  650         self.assertIsNotNone(m,'sfx pattern should match')
  651         self.assertEqual(len(m.group(0)),len(sfx),'sfx pattern should match %d characters not %d' %(len(sfx),len(m.group(0))))
  652 
  653     def test5(self):
  654         from reportlab.platypus.paragraph import _hyphenateWord, _hyphenateFragWord, _rebuildFragWord, stringWidth, ABag
  655         w = 'https://www.reportlab.com/pypi/packages'
  656         fontName = 'Helvetica'
  657         fontSize = 12
  658         AF = ABag(rise=0,fontName=fontName,fontSize=fontSize)
  659         BF = AF.clone(fontName='Helvetica-Bold')
  660 
  661         def applyTest(w, uriWasteReduce, embeddedHyphenation, ex, split=None):
  662             if not split:
  663                 ww = stringWidth(w,fontName,fontSize)
  664                 r = _hyphenateWord(None,fontName,fontSize,w,ww,ww+10,ww+5, uriWasteReduce, embeddedHyphenation)
  665             elif split:
  666                 i = int(len(w)*split)
  667                 fw = _rebuildFragWord([(AF,w[:i]),(BF,w[i:])])
  668                 #print('%s %s %r %r' % (split,fw[0],fw[1][1],fw[2][1]))
  669                 ww = fw[0]
  670                 r = _hyphenateFragWord(None,fw,ww+10,ww+5, uriWasteReduce, embeddedHyphenation)
  671                 if r is not None:
  672                     _r = r
  673                     r = [u''.join((_[1] for _ in _fw[1:])) for _fw in _r]  
  674             self.assertEqual(r,ex,'hyphenation of w=%r u=%r e=%r ex=%r split=%r failed'%(w,uriWasteReduce,embeddedHyphenation,ex,split))
  675         for split in (None,0.001,0.1,0.5,0.8,0.9,1.0):
  676             applyTest('https://www.reportlab.com/pypi/packages', 0.3, True, [u'https://www.reportlab.com/pypi/', u'packages'],split=split)
  677             applyTest('https://www.reportlab.com/pypi/packages', False, True, None,split=split)
  678             applyTest('https://www.repor-tlab.com/pypi/packages', 0.3, True, [u'https://www.repor-tlab.com/pypi/', u'packages'],split=split)
  679             applyTest('https//www.repor-tlab.com/pypi/packages', 0.3, True, None,split=split) #not a uri (no :) and contains - and non letters
  680             applyTest('httpsSSwwwDrepor-tlabDcomSpypiSpackages', 0.3, True, [u'httpsSSwwwDrepor-', u'tlabDcomSpypiSpackages'],split=split) #should succeed because '-' with no non-letters
  681             applyTest('httpsSSwwwDrepor-tlabDcomSpypiSpackages', 0.3, False, None, split=split) #fails because embeddedHyphenation=False
  682 
  683     @unittest.skipUnless(pyphen,'s')
  684     def test6(self):
  685         bt = getSampleStyleSheet()['BodyText']
  686         bt.fontName = 'Helvetica'
  687         bt.fontSize = 10
  688         bt.leading = 12
  689         bt.alignment = TA_JUSTIFY
  690         canv = Canvas(outputfile('test_platypus_paragraphs_hyphenations.pdf'))
  691         x = 72
  692         y = canv._pagesize[1] - 72
  693 
  694         def _t(p,x,y,aW,aH=0x7fffffff,dy=5):
  695             w, h = p.wrap(aW,aH)
  696             y0 = y
  697             y -= h
  698             canv.saveState()
  699             canv.setLineWidth(0.5)
  700             if aH!=0x7fffffff:
  701                 canv.setLineWidth(1)
  702                 canv.setStrokeColor((1,0,0))
  703                 canv.rect(x,y0-aH,aW,aH)
  704                 ny = y0 - max(aH,h)
  705             else:
  706                 ny = y
  707             canv.setLineWidth(0.5)
  708             canv.setStrokeColor((0.5,0.5,0.5))
  709             canv.rect(x,y,w,h)
  710             p.drawOn(canv,x,y)
  711             canv.restoreState()
  712             return ny-dy
  713         def t(x,y,aW,aH=0x7fffffff,style=bt):
  714             p = Paragraph(text,style=style)
  715             return _t(p,x,y,aW,aH=aH)
  716 
  717         raw = """This is a splittable word 'disestablishment'!"""
  718         for text in ("""This is a splittable word '<span color="red">dis</span><span color="blue">estab</span><span color="green">lish</span><span color="magenta">ment</span>'!""",
  719                      """This is a splittable word 'd<span color="red">ise</span><span color="blue">stabl</span><span color="green">ishm</span><span color="magenta">ent</span>'!""",
  720                      """This is a splittable word 'di<span color="red">ses</span><span color="blue">tabli</span><span color="green">shme</span><span color="magenta">ent</span>'!""",
  721                     """This is a splittable word 'disestablishment'!""",
  722                      ):
  723             aW = stringWidth("This is a splittable word 'dis",bt.fontName,bt.fontSize)
  724             y = t(x,y,aW)
  725             aW = stringWidth("This is a splittable word 'dise",bt.fontName,bt.fontSize)
  726             y = t(x,y,aW)
  727             aW = stringWidth("This is a splittable word 'disestabl",bt.fontName,bt.fontSize)
  728             y = t(x,y,aW)
  729             aW = stringWidth("This is a splittable word 'disestabli",bt.fontName,bt.fontSize)
  730             y = t(x,y,aW)
  731             aW = stringWidth("This is a splittable word 'disestablishm",bt.fontName,bt.fontSize)
  732             y = t(x,y,aW)
  733 
  734         canv.showPage()
  735         y = canv._pagesize[1] - 72
  736         nt = bt.clone('nt',fontName='Helvetica', fontSize = 12,leading = 16, alignment = TA_JUSTIFY)
  737         naW, naH = 342.992125984252, 56.69291338582681
  738         for ntext in (  b"Bedauerlicherweise ist ein Donaudampfschiffkapit\xc3\xa4n auch <font color='red'>nur</font> <font color='green'>ein</font> Dampfschiffkapit\xc3\xa4n.",
  739                         b"Bedauerlicherweise ist ein Donaudampfschiffkapit\xc3\xa4n auch nur ein Dampfschiffkapit\xc3\xa4n.",
  740                         ):
  741             ntext = (ntext.decode('utf8') + u" ") * 3
  742             p = Paragraph(ntext,style=nt)
  743             y = _t(p,x,y,naW,aH=naH)
  744 
  745             S = p.split(naW,naH)
  746             self.assertEqual(len(S),2)
  747             y = _t(S[0],x,y,naW,aH=naH)
  748             y = _t(S[1],x,y,naW,aH=naH)
  749         canv.save()
  750 
  751     @unittest.skipUnless(pyphen,'s')
  752     def test7(self):
  753         """test various ways to adjust the hypenationMinWordLength"""
  754         registerFont(TTFont("Vera", "Vera.ttf"))
  755         aW = 51.0236220472
  756         text  = u'\u0440\u044b\u0431\u0430 \u043f\u0438\u043b\u0430 \u0438 \u0431\u0430\u0431\u0443 \u0434\u0430\u0436\u0435 \u0432\u0435\u043b\u0430 \u043d\u0430 \u043c\u0430\u044f\u043a'
  757         text1 = u'\u0440\u044b\u0431\u0430 <span color="blue">\u043f\u0438\u043b\u0430</span> \u0438 \u0431\u0430\u0431\u0443 \u0434\u0430\u0436\u0435 \u0432\u0435\u043b\u0430 \u043d\u0430 \u043c\u0430\u044f\u043a'
  758         tmpls = [
  759                 u'%(text)s',
  760                 u'<para hyphenationMinWordLength="%(hymwl)d">%(text)s</para>',
  761                 u'<para>%(text)s</para>',
  762                 u'%(text1)s',
  763                 u'<para hyphenationMinWordLength="%(hymwl)d">%(text1)s</para>',
  764                 u'<para>%(text1)s</para>',
  765                 ]
  766         for ex,x,hymwl in [
  767                 (72,0,None),    #default is 5
  768                 (72,0,5),
  769                 (60,0,4),
  770                 (72,2,None),    #default is 5
  771                 (72,1,5),
  772                 (60,1,4),
  773                 (72,3,None),    #default is 5
  774                 (72,4,5),
  775                 (60,5,4),
  776                 ]:
  777             kwds = dict(hyphenationMinWordLength=hymwl) if hymwl!=None else {}
  778             template = tmpls[x]
  779             t = template % locals()
  780             p = Paragraph(
  781                     template % locals(),
  782                     style = ParagraphStyle('P10H5', fontSize=10, fontName="Vera", hyphenationLang="ru_RU",**kwds),
  783                     )
  784             w,h = p.wrap(aW,0x7fffffff)
  785             self.assertEqual(h,ex,'Russion hyphenation test failed for ex=%(ex)s template=%(template)r hymwl=%(hymwl)r h=%(h)s\ntext=%(t)r' % locals())
  786 
  787 class ULTestCase(unittest.TestCase):
  788     "Test underlining and overstriking of paragraphs."
  789     def testUl(self):
  790         from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin
  791         from reportlab.lib.units import inch
  792         from reportlab.platypus.flowables import AnchorFlowable
  793         class MyDocTemplate(BaseDocTemplate):
  794             _invalidInitArgs = ('pageTemplates',)
  795 
  796             def __init__(self, filename, **kw):
  797                 self.allowSplitting = 0
  798                 kw['showBoundary']=1
  799                 BaseDocTemplate.__init__(self, filename, **kw)
  800                 self.addPageTemplates(
  801                         [
  802                         PageTemplate('normal',
  803                                 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))],
  804                                 ),
  805                         ])
  806 
  807         styleSheet = getSampleStyleSheet()
  808         normal = ParagraphStyle(name='normal',fontName='Times-Roman',fontSize=12,leading=1.2*12,parent=styleSheet['Normal'])
  809         normal_sp = ParagraphStyle(name='normal_sp',parent=normal,alignment=TA_JUSTIFY,spaceBefore=12)
  810         normal_just = ParagraphStyle(name='normal_just',parent=normal,alignment=TA_JUSTIFY)
  811         normal_right = ParagraphStyle(name='normal_right',parent=normal,alignment=TA_RIGHT)
  812         normal_center = ParagraphStyle(name='normal_center',parent=normal,alignment=TA_CENTER)
  813         normal_indent = ParagraphStyle(name='normal_indent',firstLineIndent=0.5*inch,parent=normal)
  814         normal_indent_lv_2 = ParagraphStyle(name='normal_indent_lv_2',firstLineIndent=1.0*inch,parent=normal)
  815         texts = ['''Furthermore, a subset of <font size="14">English sentences</font> interesting on quite
  816 independent grounds is not quite equivalent to a stipulation to place
  817 the constructions into these various categories.''',
  818         '''We will bring evidence in favor of
  819 The following thesis:  most of the methodological work in modern
  820 linguistics can be defined in such a way as to impose problems of
  821 phonemic and morphological analysis.''']
  822         story =[]
  823         a = story.append
  824         a(Paragraph("This should &lt;a href=\"#theEnd\" color=\"blue\"&gt;<a href=\"#theEnd\" color=\"blue\">jump</a>&lt;/a&gt; jump to the end!",style=normal))
  825         a(XPreformatted("This should &lt;a href=\"#theEnd\" color=\"blue\"&gt;<a href=\"#theEnd\" color=\"blue\">jump</a>&lt;/a&gt; jump to the end!",style=normal))
  826         a(Paragraph("<a href=\"#theEnd\"><u><font color=\"blue\">ditto</font></u></a>",style=normal))
  827         a(XPreformatted("<a href=\"#theEnd\"><u><font color=\"blue\">ditto</font></u></a>",style=normal))
  828         a(Paragraph("This <font color='CMYKColor(0,0.6,0.94,0)'>should</font> &lt;a href=\"#thePenultimate\" color=\"blue\"&gt;<a href=\"#thePenultimate\" color=\"blue\">jump</a>&lt;/a&gt; jump to the penultimate page!",style=normal))
  829         a(Paragraph("This should &lt;a href=\"#theThird\" color=\"blue\"&gt;<a href=\"#theThird\" color=\"blue\">jump</a>&lt;/a&gt; jump to a justified para!",style=normal))
  830         a(Paragraph("This should &lt;a href=\"#theFourth\" color=\"blue\"&gt;<a href=\"#theFourth\" color=\"blue\">jump</a>&lt;/a&gt; jump to an indented para!",style=normal))
  831         for mode in (0,1):
  832             text0 = texts[0]
  833             text1 = texts[1]
  834             if mode:
  835                 text0 = text0.replace('English sentences','<b>English sentences</b>').replace('quite equivalent','<i>quite equivalent</i>')
  836                 text1 = text1.replace('the methodological work','<b>the methodological work</b>').replace('to impose problems','<i>to impose problems</i>')
  837             for t in ('u','strike'):
  838                 for n in range(6):
  839                     for s in (normal,normal_center,normal_right,normal_just,normal_indent, normal_indent_lv_2):
  840                         for autoLeading in ('','min','max'):
  841                             if n==4 and s==normal_center and t=='strike' and mode==1:
  842                                 a(Paragraph("<font color=green>The second jump at the beginning should come here &lt;a name=\"thePenultimate\"/&gt;<a name=\"thePenultimate\"/>!</font>",style=normal))
  843                             elif n==4 and s==normal_just and t=='strike' and mode==1:
  844                                 a(Paragraph("<font color=green>The third jump at the beginning should come just below here to a paragraph with just an a tag in it!</font>",style=normal))
  845                                 a(Paragraph("<a name=\"theThird\"/>",style=normal))
  846                             elif n==4 and s==normal_indent and t=='strike' and mode==1:
  847                                 a(Paragraph("<font color=green>The fourth jump at the beginning should come just below here!</font>",style=normal))
  848                                 a(AnchorFlowable('theFourth'))
  849                             a(Paragraph('n=%d style=%s(autoLeading=%s) tag=%s'%(n,s.name,autoLeading,t),style=normal_sp))
  850                             a(Paragraph('<para autoleading="%s">%s<%s>%s</%s>. %s <%s>%s</%s>. %s</para>' % (
  851                             autoLeading,
  852                             (s==normal_indent_lv_2 and '<seq id="document" inc="no"/>.<seq id="document_lv_2"/>' or ''),
  853                             t,' '.join((n+1)*['A']),t,text0,t,' '.join((n+1)*['A']),t,text1),
  854                             style=s))
  855         a(Paragraph("The jump at the beginning should come here &lt;a name=\"theEnd\"/&gt;<a name=\"theEnd\"/>!",style=normal))
  856         a(Paragraph('Underlining <span fontSize="11"><u color="red">A<u color="green">B</u><u color="blue">C</u>D<sup><strike width="0.5" color="magenta">2</strike><sup><u color="darkgreen" width="0.2">3</u></sup></sup></u></span>',normal))
  857         a(Paragraph('<para autoLeading="max" spaceAfter="10">this is in 12 <font size=30>this is in 30</font> <u offset="-0.5" width="0.5" color="red"><u offset="-1.5" width="0.5" color="blue">and</u></u> <link underline="1" ucolor="blue" href="http://google.com/">the link box<sup><a color="red" ucolor="green" underline="1" href="https://www.reportlab.com">2</a></sup> is right (twice).</link></para>''',normal))
  858         a(Paragraph('<para autoLeading="max" spaceAfter="10">this is in 12 <font size=30>this is in 30</font> and <link underline="1" ucolor="blue" href="http://google.com/">the link box is right.</link></para>''',normal))
  859         a(Paragraph('Underlining <u><span color="red">underlined in red? <span color="blue"><u>or blue</u></span> or red again?</span></u>',normal))
  860         a(Paragraph('Link <a href="#theEnd" color="blue">jump</a> to end.<br/>Underlined link <a href="#theEnd" underline="1" ucolor="red" color="blue">jump</a> to end!',style=normal))
  861         a(Paragraph('<para autoleading=""><u>A</u>. Furthermore, a subset of <font size="14">English sentences</font> interesting on quite\nindependent grounds is not quite equivalent to a stipulation to place\nthe constructions into these various categories. <u>A</u>. We will bring evidence in favor of\nThe following thesis: most of the methodological work in modern\nlinguistics can be defined in such a way as to impose problems of\nphonemic and morphological analysis.</para>',normal))
  862         a(Paragraph('<para autoleading=""><u>A</u>. Furthermore, a subset of <font size="14">English sentences</font> interesting on quite<br/><u>A</u>.</para>',normal))
  863         a(Paragraph(u"<para>This is a <sup rise=5><span color='red'>sup</span></sup>rise=5.</para>",normal))
  864         a(Paragraph('<span fontSize="11"><u color="green"><strike color="blue">AAAAAA</strike></u></span>',normal))
  865         a(Paragraph("Underlining &amp; width proportional to first use font size ('f' suffix) <u offset='-0.125*f' width='0.05*f'>underlined <span size=14>underlined</span></u>!",style=normal))
  866         a(Paragraph("Underlining &amp; width proportional to first use font size ('F' suffix) <u offset='-0.125*F' width='0.05*F'>underlined <span size=14>underlined</span></u>!",style=normal))
  867         a(Paragraph('''<para spaceBefore="10">This is underlined &lt;sup&gt;: a<sup><u><span color="red">sup</span></u></sup></para>''',style=normal))
  868         a(Paragraph('''<para spaceBefore="10">This is <u>underlined</u></para>''',style=normal))
  869         a(Paragraph('''<para spaceBefore="10">This is <u kind="double">underlined double</u></para>''',style=normal))
  870         a(Paragraph('''<para spaceBefore="10">This is <strike>striken</strike></para>''',style=normal))
  871         a(Paragraph('''<para spaceBefore="10">This is <strike><u>both</u></strike></para>''',style=normal))
  872         a(Paragraph('''<para spaceBefore="10">This is <u width="0.5" offset="-1" kind="double">underlined kind="double"</u></para>''',style=normal))
  873         a(Paragraph('''<para spaceBefore="10">This is <u width="0.25" offset="-1" kind="double">double underlined with thinner lines</u></para>''',style=normal))
  874         a(Paragraph('''<para spaceBefore="10">This is <u width="0.5" offset="-0.5" color="red">underlined in red</u></para>''',style=normal))
  875         a(Paragraph('''<para spaceBefore="10">This is <strike width="0.5" color="red">overstruck in red</strike></para>''',style=normal))
  876         a(Paragraph('''<para spaceBefore="10">This is <strike width="0.5" color="red" kind="double">doubly overstruck in red</strike></para>''',style=normal))
  877         a(Paragraph('''<para spaceBefore="10">This is <strike width="0.5" offset="0.125*F" color="red" kind="triple" gap="0.5">triply overstruck in red</strike></para>''',style=normal))
  878         a(Paragraph('''<para autoLeading="max" spaceAfter="10" spaceBefore="30">this is in 12 <font size="30">this is in 30</font> <u offset="-0.5" width="0.5" color="red"><u offset="-1.5" width="0.5" color="blue">and</u></u> <link underline="1" ucolor="blue" href="http://google.com/">the link box<sup><a color="red" ucolor="green" underline="1" href="https://www.reportlab.com">2</a></sup> is right (twice).</link></para>''',style=normal))
  879         a(Paragraph("",style=normal))
  880         # 3.5.x had a bug with leftIndent and underlines, check that
  881         left_indent = ParagraphStyle(name='left_indent',leftIndent=80,parent=styleSheet['Normal'])
  882         a(Paragraph("<u>Replicating a left indent underline bug.</u>",style=left_indent))
  883 
  884         #testing PR 49
  885         a(Paragraph("This paragraph contains <strike>really</strike> large <u>spaces</u> <strike color='blue' offset='1' width='0.5'><u color='red' offset='-1' width='0.5'>between words</u></strike>. ThisLongWordDoesntFitIntoPreviousLineCausingWordsSpread",style=normal_just))
  886 
  887         doc = MyDocTemplate(outputfile('test_platypus_paragraphs_ul.pdf'))
  888         doc.build(story)
  889 
  890 class AutoLeadingTestCase(unittest.TestCase):
  891     "Test underlining and overstriking of paragraphs."
  892     def testAutoLeading(self):
  893         from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin
  894         from reportlab.lib.units import inch
  895         from reportlab.platypus.flowables import AnchorFlowable
  896         class MyDocTemplate(BaseDocTemplate):
  897             _invalidInitArgs = ('pageTemplates',)
  898 
  899             def __init__(self, filename, **kw):
  900                 self.allowSplitting = 0
  901                 kw['showBoundary']=1
  902                 BaseDocTemplate.__init__(self, filename, **kw)
  903                 self.addPageTemplates(
  904                         [
  905                         PageTemplate('normal',
  906                                 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))],
  907                                 ),
  908                         ])
  909 
  910         from reportlab.lib.testutils import testsFolder
  911         styleSheet = getSampleStyleSheet()
  912         normal = ParagraphStyle(name='normal',fontName='Times-Roman',fontSize=12,leading=1.2*12,parent=styleSheet['Normal'])
  913         normal_sp = ParagraphStyle(name='normal_sp',parent=normal,alignment=TA_JUSTIFY,spaceBefore=12)
  914         texts = ['''Furthermore, a subset of <font size="14">English sentences</font> interesting on quite
  915 independent grounds is not quite equivalent to a stipulation to place
  916 <font color="blue">the constructions <img src="%(testsFolder)s/../docs/images/testimg.gif"/> into these various categories.</font>'''%dict(testsFolder=testsFolder),
  917         '''We will bring <font size="18">Ugly Things</font> in favor of
  918 The following thesis:  most of the methodological work in Modern
  919 Linguistics can be <img src="%(testsFolder)s/../docs/images/testimg.gif" valign="baseline" /> defined in such <img src="%(testsFolder)s/../docs/images/testimg.gif" valign="10" /> a way as to impose problems of
  920 phonemic and <u>morphological <img src="%(testsFolder)s/../docs/images/testimg.gif" valign="top"/> </u> analysis.'''%dict(testsFolder=testsFolder)]
  921         story =[]
  922         a = story.append
  923         t = 'u'
  924         n = 1
  925         for s in (normal,normal_sp):
  926             for autoLeading in ('','min','max'):
  927                 a(Paragraph('style=%s(autoLeading=%s)'%(s.name,autoLeading),style=normal_sp))
  928                 a(Paragraph('<para autoleading="%s"><%s>%s</%s>. %s <%s>%s</%s>. %s</para>' % (
  929                             autoLeading,
  930                             t,' '.join((n+1)*['A']),t,texts[0],t,' '.join((n+1)*['A']),t,texts[1]),
  931                             style=s))
  932         a(Paragraph('''<img src="%(testsFolder)s/../docs/images/testimg.gif" valign="top"/> image is very first thing in the line.'''%dict(testsFolder=testsFolder), style=normal))
  933         a(Paragraph('some text.... some more.... some text.... some more....', normal))
  934         a(Paragraph('<img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="0.19in" /> some text <br /> '%dict(testsFolder=testsFolder), normal))
  935         a(Paragraph('some text.... some more.... some text.... some more....', normal))
  936         a(Paragraph('<img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="0.19in" /> <br /> '%dict(testsFolder=testsFolder), normal))
  937         a(Paragraph('some text.... some more.... some text.... some more....', normal))
  938 
  939         #Volker Haas' valign tests
  940         fmt = '''<font color="red">%(valign)s</font>: Furthermore, a <u>subset</u> <strike>of</strike> <font size="14">English sentences</font> interesting on quite
  941 independent grounds is not quite equivalent to a stipulation to place <img src="%(testsFolder)s/../docs/images/redsquare.png" width="0.5in" height="0.5in" valign="%(valign)s"/>
  942 the constructions into these <u>various</u> categories. We will bring <font size="18">Ugly Things</font> in favor of
  943 The following thesis:  most of the methodological work in Modern
  944 Linguistics can be defined in such a way as to impose problems of
  945 phonemic and <u>morphological</u> <strike>analysis</strike>.'''
  946 
  947         p_style= ParagraphStyle('Normal')
  948         p_style.autoLeading = 'max'
  949         for valign in (
  950                 'baseline',
  951                 'sub',
  952                 'super',
  953                 'top',
  954                 'text-top',
  955                 'middle',
  956                 'bottom',
  957                 'text-bottom',
  958                 '0%',
  959                 '2in',
  960                 ):
  961             a(Paragraph(fmt % dict(valign=valign,testsFolder=testsFolder),p_style))
  962             a(XPreformatted(fmt % dict(valign=valign,testsFolder=testsFolder),p_style))
  963 
  964         a(Paragraph('<br/><b>Some Paragraph tests of &lt;sup rise="pts" size="pts"</b>...', normal))
  965         a(Paragraph("<br/>This is a <sup><span color='red'>sup</span></sup>.",p_style))
  966         a(XPreformatted("This is a <sup><span color='red'>sup</span></sup>.",p_style))
  967         a(Paragraph("This is a <sup rise=5><span color='red'>sup</span></sup>rise=5.",p_style))
  968         a(XPreformatted("This is a <sup rise=5><span color='red'>sup</span></sup>rise=5.",p_style))
  969         a(Paragraph("This is a <sup rise=6><span color='red'>sup</span></sup>rise=6.",p_style))
  970         a(XPreformatted("This is a <sup rise=6><span color='red'>sup</span></sup>rise=6.",p_style))
  971         a(Paragraph("This is a <sup rise=7><span color='red'>sup</span></sup>rise=7.",p_style))
  972         a(XPreformatted("This is a <sup rise=7><span color='red'>sup</span></sup>rise=7.",p_style))
  973         a(Paragraph("This is a <sup rise=8><span color='red'>sup</span></sup>rise=8.",p_style))
  974         a(XPreformatted("This is a <sup rise=8><span color='red'>sup</span></sup>rise=8.",p_style))
  975         a(Paragraph("This is a <sup rise=9><span color='red'>sup</span></sup>rise=9.",p_style))
  976         a(XPreformatted("This is a <sup rise=9><span color='red'>sup</span></sup>rise=9.",p_style))
  977         a(Paragraph("This is a <sup size=7><span color='red'>sup</span></sup>size=7.",p_style))
  978         a(XPreformatted("This is a <sup size=7><span color='red'>sup</span></sup>size=7.",p_style))
  979         a(Paragraph("This is a <sup rise=5 size=7><span color='red'>sup</span></sup>rise=5 size=7.",p_style))
  980         a(XPreformatted("This is a <sup rise=5 size=7><span color='red'>sup</span></sup>rise=5 size=7.",p_style))
  981         a(Paragraph("This is a <sup rise=6 size=7><span color='red'>sup</span></sup>rise=6 size=7.",p_style))
  982         a(XPreformatted("This is a <sup rise=6 size=7><span color='red'>sup</span></sup>rise=6 size=7.",p_style))
  983         a(Paragraph("This is a <sup rise=7 size=7><span color='red'>sup</span></sup>rise=7 size=7.",p_style))
  984         a(XPreformatted("This is a <sup rise=7 size=7><span color='red'>sup</span></sup>rise=7 size=7.",p_style))
  985         a(Paragraph("This is a <sup rise=8 size=7><span color='red'>sup</span></sup>rise=8 size=7.",p_style))
  986         a(XPreformatted("This is a <sup rise=8 size=7><span color='red'>sup</span></sup>rise=8 size=7.",p_style))
  987         a(Paragraph("This is a <sup rise=9 size=7><span color='red'>sup</span></sup>rise=9 size=7.",p_style))
  988         a(XPreformatted("This is a <sup rise=9 size=7><span color='red'>sup</span></sup>rise=9 size=7.",p_style))
  989         a(Paragraph("This is a <sup rise=90% size=70%><span color='red'>sup</span></sup>rise=90% size=70%.",p_style))
  990         a(Paragraph("This is a <sup rise=-2 size=-2><span color='red'>sup</span></sup>rise=-2 size=-2.",p_style))
  991         a(Paragraph("This is a <sup rise=-4 size=-3><span color='red'>sup</span></sup>rise=-4 size=-3.",p_style))
  992         a(PageBreak())
  993 
  994         a(Paragraph('<br/><b>Some Paragraph tests of &lt;img width="x%" height="x%"</b>...', normal))
  995         a(Paragraph('H=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="10%%" />'%dict(testsFolder=testsFolder), normal))
  996         a(Paragraph('H=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="50%%" />'%dict(testsFolder=testsFolder), normal))
  997         a(Paragraph('H=100%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="100%%" />'%dict(testsFolder=testsFolder), normal))
  998         a(Paragraph('H=100%% W=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="10%%" height="100%%" />'%dict(testsFolder=testsFolder), normal))
  999         a(Paragraph('H=100%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="100%%" />'%dict(testsFolder=testsFolder), normal))
 1000         a(Paragraph('H=50%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="50%%" />'%dict(testsFolder=testsFolder), normal))
 1001         a(Paragraph('<br/><b>Some XPreformatted tests of &lt;img width="x%" height="x%"</b>...', normal))
 1002         a(XPreformatted('H=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="10%%" />'%dict(testsFolder=testsFolder), normal))
 1003         a(XPreformatted('H=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="50%%" />'%dict(testsFolder=testsFolder), normal))
 1004         a(XPreformatted('H=100%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="100%%" />'%dict(testsFolder=testsFolder), normal))
 1005         a(XPreformatted('H=100%% W=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="10%%" height="100%%" />'%dict(testsFolder=testsFolder), normal))
 1006         a(XPreformatted('H=100%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="100%%" />'%dict(testsFolder=testsFolder), normal))
 1007         a(XPreformatted('H=50%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="50%%" />'%dict(testsFolder=testsFolder), normal))
 1008         a(Paragraph('<br/><b>Some CJK Paragraph tests of &lt;img width="x%" height="x%"</b>...', normal))
 1009         normalCJK = ParagraphStyle('normalCJK', parent=normal, wordWrap = 'CJK')
 1010         a(Paragraph('H=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="10%%" />'%dict(testsFolder=testsFolder), normalCJK))
 1011         a(Paragraph('H=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="50%%" />'%dict(testsFolder=testsFolder), normalCJK))
 1012         a(Paragraph('H=100%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="0.57in" height="100%%" />'%dict(testsFolder=testsFolder), normalCJK))
 1013         a(Paragraph('H=100%% W=10%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="10%%" height="100%%" />'%dict(testsFolder=testsFolder), normalCJK))
 1014         a(Paragraph('H=100%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="100%%" />'%dict(testsFolder=testsFolder), normalCJK))
 1015         a(Paragraph('H=50%% W=50%% <img src="%(testsFolder)s/../docs/images/testimg.gif" width="50%%" height="50%%" />'%dict(testsFolder=testsFolder), normalCJK))
 1016         doc = MyDocTemplate(outputfile('test_platypus_paragraphs_autoleading.pdf'))
 1017         doc.build(story)
 1018 
 1019 DEJAVUSANS = ('DejaVuSans','DejaVuSans-Bold','DejaVuSans-Oblique','DejaVuSans-BoldOblique')
 1020 def haveDejaVu():
 1021     from reportlab.pdfbase.ttfonts import TTFont
 1022     for x in DEJAVUSANS:
 1023         try:
 1024             TTFont(x,x+'.ttf')
 1025         except:
 1026             return False
 1027     return True
 1028 
 1029 DEJAVUSANS = ('DejaVuSans','DejaVuSans-Bold','DejaVuSans-Oblique','DejaVuSans-BoldOblique')
 1030 def alphaSortedItems(d):
 1031     return (i[1] for i in sorted((j[0].lower(),j) for j in d.items()))
 1032 
 1033 def tentities(title, b, fn):
 1034     from reportlab.platypus.paraparser import greeks
 1035     from reportlab.platypus.doctemplate import SimpleDocTemplate
 1036     from reportlab.pdfbase.pdfmetrics import stringWidth, registerFont, registerFontFamily
 1037     from reportlab.pdfbase.ttfonts import TTFont
 1038     from reportlab.platypus.tables import TableStyle, Table
 1039     from reportlab.platypus.paragraph import Paragraph
 1040     from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
 1041     from reportlab import ascii
 1042 
 1043     for v in DEJAVUSANS:
 1044         registerFont(TTFont(v,v+'.ttf'))
 1045     registerFontFamily(*(DEJAVUSANS[:1]+DEJAVUSANS))
 1046 
 1047     def bu(s):
 1048         return asUnicode(s) if not b else asBytes(s)
 1049 
 1050     bt = getSampleStyleSheet()['BodyText']
 1051     bt.fontName = 'DejaVuSans'
 1052     doc = SimpleDocTemplate(fn)
 1053     story = [Paragraph('<b>%s</b>' % title,bt)]
 1054     story.extend([Paragraph(bu('&amp;%s; = <span color="red">&%s;</span>' % (k,k)), bt) for k, v in alphaSortedItems(greeks)])
 1055     doc.build(story)
 1056 
 1057 class JustifyTestCase(unittest.TestCase):
 1058     "Test justification of paragraphs."
 1059     def testUl(self):
 1060         from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin
 1061         from reportlab.lib.units import inch
 1062         class MyDocTemplate(BaseDocTemplate):
 1063             _invalidInitArgs = ('pageTemplates',)
 1064 
 1065             def __init__(self, filename, **kw):
 1066                 self.allowSplitting = 0
 1067                 BaseDocTemplate.__init__(self, filename, **kw)
 1068                 self.addPageTemplates(
 1069                         [
 1070                         PageTemplate('normal',
 1071                                 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))],
 1072                                 ),
 1073                         ])
 1074 
 1075         styleSheet = getSampleStyleSheet()
 1076         normal = ParagraphStyle(name='normal',fontName='Times-Roman',fontSize=12,leading=1.2*12,parent=styleSheet['Normal'])
 1077         normal_just = ParagraphStyle(name='normal_just',parent=normal,alignment=TA_JUSTIFY,spaceAfter=12)
 1078         text0 = '''Furthermore, a subset of English sentences interesting on quite
 1079 independent grounds is not quite equivalent to a stipulation to place
 1080 the constructions into these various categories. We will bring evidence in favor of
 1081 The following thesis:  most of the methodological work in modern
 1082 linguistics can be defined in such a way as to impose problems of
 1083 phonemic and morphological analysis.'''
 1084         story =[]
 1085         a = story.append
 1086         for mode in (0,1,2,3,4,5,6,7):
 1087             text = text0
 1088             paraStyle = normal_just
 1089             if mode==1:
 1090                 text = text.replace('English sentences','<b>English sentences</b>').replace('quite equivalent','<i>quite equivalent</i>')
 1091                 text = text.replace('the methodological work','<b>the methodological work</b>').replace('to impose problems','<i>to impose problems</i>')
 1092                 a(Paragraph('Justified paragraph in normal/bold/italic font',style=normal))
 1093             elif mode==2:
 1094                 text = '<b>%s</b>' % text
 1095                 a(Paragraph('Justified paragraph in bold font',style=normal))
 1096             elif mode==3:
 1097                 text = '<i>%s</i>' % text
 1098                 a(Paragraph('Justified paragraph in italic font',style=normal))
 1099             elif mode==4:
 1100                 text = text.replace('English ','English&nbsp;').replace('quite ','quite&nbsp;')
 1101                 text = text.replace(' methodological','&nbsp;methodological').replace(' impose','&nbsp;impose')
 1102                 a(Paragraph('Justified paragraph in normal font &amp; some hard spaces',style=normal))
 1103             elif mode in (5,6,7):
 1104                 text = text.replace('as to impose','<br/>as to impose').replace(' most of the','<br/>most of the')
 1105                 text = text.replace(' grounds','<br/>grounds').replace(' various','<br/>various')
 1106                 if mode in (6,7):
 1107                     msg = []
 1108                     msg.append('justifyBreaks=1')
 1109                     paraStyle = paraStyle.clone('paraStyle6',paraStyle,justifyBreaks=1)
 1110                     if mode==7:
 1111                         msg.append('justifyLastLine=3')
 1112                         paraStyle = paraStyle.clone('paraStyle7',paraStyle,justifyLastLine=3)
 1113                     msg = '(%s) ' % (' '.join(msg))
 1114                 else:
 1115                     a(PageBreak())
 1116                     msg = ' '
 1117 
 1118                 a(Paragraph('Justified%swith some &lt;br/&gt; tags' % msg,style=normal))
 1119             else:
 1120                 a(Paragraph('Justified paragraph in normal font',style=normal))
 1121 
 1122             a(Paragraph(text,style=paraStyle))
 1123         doc = MyDocTemplate(outputfile('test_platypus_paragraphs_just.pdf'))
 1124         doc.build(story)
 1125 
 1126     def testAutoPageTemplate(self):
 1127         from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin
 1128         from reportlab.lib.units import inch
 1129         class onPage:
 1130             def __init__(self,label):
 1131                 self.label = label
 1132             def __call__(self,canv,doc):
 1133                 canv.drawString(72,72,'This is pageTemplate(%s)' % (self.label,))
 1134         class MyDocTemplate(BaseDocTemplate):
 1135             _invalidInitArgs = ('pageTemplates',)
 1136 
 1137             def __init__(self, filename, **kw):
 1138                 self.allowSplitting = 0
 1139                 BaseDocTemplate.__init__(self, filename, **kw)
 1140                 self.addPageTemplates(
 1141                         [
 1142                         PageTemplate('normal',
 1143                                 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))],
 1144                                 onPage = onPage('normal'),
 1145                                 ),
 1146                         PageTemplate('auto',
 1147                                 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))],
 1148                                 onPage = onPage('auto'),
 1149                                 autoNextPageTemplate = 'autoFollow',
 1150                                 ),
 1151                         PageTemplate('autoFollow',
 1152                                 [Frame(inch, inch, 6.27*inch, 9.69*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))],
 1153                                 onPage = onPage('autoFollow'),
 1154                                 ),
 1155                         ])
 1156         styleSheet = getSampleStyleSheet()
 1157         normal = ParagraphStyle(name='normal',fontName='Times-Roman',fontSize=12,leading=1.2*12,parent=styleSheet['Normal'])
 1158         story =[]
 1159         a = story.append
 1160         a(Paragraph('should be on page template normal', normal))
 1161         a(NextPageTemplate('auto'))
 1162         a(PageBreak())
 1163         a(Paragraph('should be on page template auto', normal))
 1164         a(PageBreak())
 1165         a(DocAssert('doc.pageTemplate.id=="autoFollow"','expected doc.pageTemplate.id=="autoFollow"'))
 1166         a(Paragraph('should be on page template autoFollow 1', normal))
 1167         a(PageBreak())
 1168         a(Paragraph('should be on page template autoFollow 2', normal))
 1169         doc = MyDocTemplate(outputfile('test_platypus_paragraphs_AutoNextPageTemplate.pdf'))
 1170         doc.build(story)
 1171 
 1172     def testParaBrFlowing(self):
 1173         from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin
 1174         from reportlab.lib.units import inch
 1175         class MyDocTemplate(BaseDocTemplate):
 1176             _invalidInitArgs = ('pageTemplates',)
 1177 
 1178             def __init__(self, filename, **kw):
 1179                 self.allowSplitting = 0
 1180                 BaseDocTemplate.__init__(self, filename, **kw)
 1181                 self.addPageTemplates(
 1182                         [
 1183                         PageTemplate('normal',
 1184                                 [
 1185                                 Frame(inch, 4.845*inch, 3*inch, 3.645*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")),
 1186                                 Frame(4.27*inch, 4.845*inch, 3*inch, 3.645*inch, id='second',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")),
 1187                                 Frame(inch, inch, 3*inch, 3.645*inch, id='third',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")),
 1188                                 Frame(4.27*inch, inch, 3*inch, 3.645*inch, id='fourth',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))
 1189                                 ],
 1190                                 ),
 1191                         ])
 1192         styleSheet = getSampleStyleSheet()
 1193         normal = ParagraphStyle(name='normal',fontName='Helvetica',fontSize=10,leading=12,parent=styleSheet['Normal'])
 1194         bold = ParagraphStyle(name='bold',fontName='Helvetica-Bold',fontSize=12,leading=14.4,parent=normal)
 1195         brText=u"""
 1196 Clearly, the natural general principle that will subsume this case is
 1197 not subject to a parasitic gap construction.  Presumably, most of the
 1198 methodological work in modern linguistics can be defined in such a way
 1199 as to impose the system of base rules exclusive of the lexicon.  In the
 1200 discussion of resumptive pronouns following (81), the fundamental error
 1201 of regarding functional notions as categorial is to be regarded as a
 1202 descriptive <span color="red">fact</span>.<br/>So far, the earlier discussion of deviance is not
 1203 quite equivalent to a parasitic gap construction.  To characterize a
 1204 linguistic level L, a case of semigrammaticalness of a different sort
 1205 may remedy and, at the same time, eliminate irrelevant intervening
 1206 contexts in selectional <span color="red">rules</span>.<br/>
 1207 Summarizing, then, we assume that the descriptive power of the base
 1208 component can be defined in such a way as to impose nondistinctness in
 1209 the sense of distinctive feature theory.  A lot of sophistication has
 1210 been developed about the utilization of machines for complex purposes,
 1211 the notion of level of grammaticalness delimits an abstract underlying
 1212 <span color="red">order</span>.<br/>To provide a constituent structure for T(Z,K), a subset of
 1213 English sentences interesting on quite independent grounds appears to
 1214 correlate rather closely with problems of phonemic and morphological
 1215 analysis.  For one thing, this analysis of a formative as a pair of sets
 1216 of features is rather different from a general convention regarding the
 1217 forms of the grammar.  A lot of sophistication has been developed about
 1218 the utilization of machines for complex purposes, a case of
 1219 semigrammaticalness of a different sort is not to be considered in
 1220 determining an important distinction in language <span color="red">use</span>.<br/>
 1221 We will bring evidence in favor of the following thesis:  a subset of
 1222 English sentences interesting on quite independent grounds delimits a
 1223 descriptive <span color="red">fact</span>.<br/>To characterize a linguistic level L, the notion of
 1224 level of grammaticalness is not to be considered in determining a
 1225 parasitic gap construction.  It must be emphasized, once again, that the
 1226 speaker-hearer's linguistic intuition can be defined in such a way as to
 1227 impose a stipulation to place the constructions into these various
 1228 categories.  On our assumptions, the appearance of parasitic gaps in
 1229 domains relatively inaccessible to ordinary extraction raises serious
 1230 doubts about problems of phonemic and morphological analysis.  For one
 1231 thing, the fundamental error of regarding functional notions as
 1232 categorial is not quite equivalent to a stipulation to place the
 1233 constructions into these various <span color="red">categories</span>.<br/>
 1234 Thus the descriptive power of the base component is unspecified with
 1235 respect to the strong generative capacity of the theory.  Presumably,
 1236 the theory of syntactic features developed earlier appears to correlate
 1237 rather closely with a corpus of utterance tokens upon which conformity
 1238 has been defined by the paired utterance test.  To provide a constituent
 1239 structure for T(Z,K), a case of semigrammaticalness of a different sort
 1240 is not to be considered in determining the ultimate standard that
 1241 determines the accuracy of any proposed grammar.  For any transformation
 1242 which is sufficiently diversified in application to be of any interest,
 1243 a subset of English sentences interesting on quite independent grounds
 1244 raises serious doubts about the requirement that branching is not
 1245 tolerated within the dominance scope of a complex symbol.  We will bring
 1246 evidence in favor of the following thesis:  an important property of
 1247 these three types of EC is not to be considered in determining the
 1248 system of base rules exclusive of the <span color="red">lexicon</span>.<br/>
 1249 With this clarification, the descriptive power of the base component is
 1250 not subject to the requirement that branching is not tolerated within
 1251 the dominance scope of a complex <span color="red">symbol</span>.<br/>In the discussion of
 1252 resumptive pronouns following (81), this selectionally introduced
 1253 contextual feature does not readily tolerate a parasitic gap
 1254 construction.  Another superficial similarity is the interest in
 1255 simulation of behavior, a descriptively adequate grammar does not affect
 1256 the structure of a corpus of utterance tokens upon which conformity has
 1257 been defined by the paired utterance <span color="red">test</span>.<br/>From C1, it follows that the
 1258 speaker-hearer's linguistic intuition is not to be considered in
 1259 determining the traditional practice of grammarians.  Let us continue to
 1260 suppose that the notion of level of grammaticalness is necessary to
 1261 impose an interpretation on the system of base rules exclusive of the
 1262 <span color="red">lexicon</span>.<br/>
 1263 """
 1264         story =[]
 1265         a = story.append
 1266         a(Paragraph('Paragraph Flowing', bold))
 1267         a(Paragraph(brText, normal))
 1268         doc = MyDocTemplate(outputfile('test_platypus_paragraphs_para_br_flowing.pdf'))
 1269         doc.build(story)
 1270 
 1271     def testParaNBSP(self):
 1272         from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, PageBegin
 1273         from reportlab.lib.units import inch
 1274         class MyDocTemplate(BaseDocTemplate):
 1275             _invalidInitArgs = ('pageTemplates',)
 1276 
 1277             def __init__(self, filename, **kw):
 1278                 self.allowSplitting = 0
 1279                 BaseDocTemplate.__init__(self, filename, **kw)
 1280                 self.addPageTemplates(
 1281                         [
 1282                         PageTemplate('normal',
 1283                                 [
 1284                                 Frame(inch, 4.845*inch, 3*inch, 3.645*inch, id='first',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")),
 1285                                 Frame(4.27*inch, 4.845*inch, 3*inch, 3.645*inch, id='second',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")),
 1286                                 Frame(inch, inch, 3*inch, 3.645*inch, id='third',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red")),
 1287                                 Frame(4.27*inch, inch, 3*inch, 3.645*inch, id='fourth',topPadding=0,rightPadding=0,leftPadding=0,bottomPadding=0,showBoundary=ShowBoundaryValue(color="red"))
 1288                                 ],
 1289                                 ),
 1290                         ])
 1291         styleSheet = getSampleStyleSheet()
 1292         normal = ParagraphStyle(name='normal',fontName='Helvetica',fontSize=10,leading=12,parent=styleSheet['Normal'])
 1293         bold = ParagraphStyle(name='normal',fontName='Helvetica-Bold',fontSize=10,leading=12,parent=styleSheet['Normal'])
 1294         registerFontFamily('Helvetica','Helvetica','Helvetica-Bold','Helvetica-Oblique','Helvetica-BoldOblique')
 1295         story =[]
 1296         a = story.append
 1297         a(Paragraph('Paragraph Hard Space Handling', bold))
 1298         a(Paragraph(''' <span backcolor="pink">ABCDEFGHI</span> ''', normal))
 1299         a(Paragraph(''' <span backcolor="palegreen">&nbsp;ABCDEFGHI&nbsp;</span> ''', normal))
 1300         a(Paragraph('''<span backcolor="lightblue">&nbsp;</span>''', normal))
 1301         a(Paragraph('''<span backcolor="lightblue">&nbsp;</span><span backcolor="palegreen">&nbsp;</span> ''', normal))
 1302         a(Paragraph('''<span backcolor="pink"><b>A</b></span><span backcolor="lightblue"> </span><span backcolor="pink"><b>B</b></span>''', normal))
 1303         a(Paragraph('''<span backcolor="pink"><b>A</b></span> <span backcolor="lightblue"> </span><span backcolor="pink"><b>B</b></span>''', normal))
 1304         a(Paragraph('''<span backcolor="pink"><b>A</b></span><span backcolor="lightblue">&nbsp;</span><span backcolor="pink"><b>B</b></span>''', normal))
 1305         a(Paragraph('''<span backcolor="pink"><b>A</b></span> <span backcolor="lightblue">&nbsp;</span><span backcolor="pink"><b>B</b></span>''', normal))
 1306         doc = MyDocTemplate(outputfile('test_platypus_paragraphs_nbsp.pdf'))
 1307         doc.build(story)
 1308 
 1309     @unittest.skipUnless(haveDejaVu(),'s')
 1310     def testParaEntities(self):
 1311         tentities(b'unicode formatted paragraphs',False,outputfile('test_platypus_unicode_paragraph_entities.pdf'))
 1312         tentities(b'byte formatted paragraphs',True,outputfile('test_platypus_bytes_paragraph_entities.pdf'))
 1313 
 1314     def testXPreUnderlining(self):
 1315         styleSheet = getSampleStyleSheet()
 1316         bt = styleSheet['BodyText']
 1317         story = [
 1318                 XPreformatted("xpre<u><font size='1' color='red'>SS</font>        </u>",bt),
 1319                 XPreformatted("xpre<u><font size='1' color='red'>SS</font>        </u>|",bt),
 1320                 XPreformatted("<u><font size='1' color='red'>SS</font>        </u>",bt),
 1321                 XPreformatted("<u><font size='1' color='red'>SS</font>        </u>|",bt),
 1322                 ]
 1323         doc = MyDocTemplate(outputfile('test_platypus_XPreUnderlining.pdf'))
 1324         doc.build(story)
 1325 
 1326 #noruntests
 1327 def makeSuite():
 1328     return makeSuiteForClasses(ParagraphCorners,SplitFrameParagraphTest,FragmentTestCase, ParagraphSplitTestCase, ULTestCase, JustifyTestCase,
 1329             AutoLeadingTestCase)
 1330 
 1331 #noruntests
 1332 if __name__ == "__main__":
 1333     unittest.TextTestRunner().run(makeSuite())
 1334     printLocation()