reportlab: added DocIf & DocWhile flowables
authorrgbecker
Fri, 22 Aug 2008 10:31:32 +0000
changeset 2956 5c17941635bd
parent 2955 cc16265295fb
child 2957 137b1d6cdca4
reportlab: added DocIf & DocWhile flowables
reportlab/platypus/doctemplate.py
reportlab/platypus/flowables.py
reportlab/test/test_platypus_general.py
--- a/reportlab/platypus/doctemplate.py	Thu Aug 21 16:50:11 2008 +0000
+++ b/reportlab/platypus/doctemplate.py	Fri Aug 22 10:31:32 2008 +0000
@@ -893,6 +893,7 @@
     _allowedLifetimes = 'page','frame','build','forever'
     def docAssign(self,var,expr,lifetime):
         var=var.strip()+'\n'
+        if not isinstance(expr,(str,unicode)): expr=str(expr)
         expr=expr.strip()
         T=tokenize.generate_tokens(lambda :var)
         tokens=[]
--- a/reportlab/platypus/flowables.py	Thu Aug 21 16:50:11 2008 +0000
+++ b/reportlab/platypus/flowables.py	Fri Aug 22 10:31:32 2008 +0000
@@ -1167,17 +1167,24 @@
     def __init__(self,var,expr,life='frame'):
         Flowable.__init__(self)
         self.args = var,expr,life
-    def wrap(self,aW,aH):
+
+    def funcWrap(self,aW,aH):
         NS=self._doctemplateAttr('_nameSpace')
         NS.update(dict(availableWidth=aW,availableHeight=aH))
         try:
-            self._doctemplateAttr('d'+self.__class__.__name__[1:])(*self.args)
+            return self.func()
         finally:
             for k in 'availableWidth','availableHeight':
                 try:
                     del NS[k]
                 except:
                     pass
+
+    def func(self):
+        return self._doctemplateAttr('d'+self.__class__.__name__[1:])(*self.args)
+
+    def wrap(self,aW,aH):
+        self.funcWrap(aW,aH)
         return 0,0
 
 class DocExec(DocAssign):
@@ -1188,20 +1195,33 @@
 
 class DocPara(DocAssign):
     '''at wrap time create a paragraph with the value of expr as text
-    if paraTemplate is specified it should use %(value)s for string interpolation
+    if format is specified it should use %(__expr__)s for string interpolation
+    of the expression expr (if any). It may also use %(name)s interpolations
+    for other variables in the namespace.
     suitable defaults will be used if style and klass are None
     '''
-    def __init__(self,expr,paraTemplate=None,style=None,klass=None):
+    def __init__(self,expr,format=None,style=None,klass=None):
         Flowable.__init__(self)
         self.expr=expr
-        self.paraTemplate=paraTemplate
+        self.format=format
         self.style=style
         self.klass=klass
 
+    def func(self):
+        expr = self.expr
+        if expr:
+            if not isinstance(expr,(str,unicode)): expr = str(expr)
+            return self._doctemplateAttr('docEval')(expr)
+
+    def add_content(self,*args):
+        self._doctemplateAttr('frame').add_generated_content(*args)
+
     def wrap(self,aW,aH):
-        value=self._doctemplateAttr('docEval')(self.expr)
-        if self.paraTemplate:
-            value = self.paraTemplate % dict(value=value)
+        value = self.funcWrap(aW,aH)
+        if self.format:
+            NS=self._doctemplateAttr('_nameSpace').copy()
+            NS['__expr__'] = value
+            value = self.format % NS
         else:
             value = str(value)
         P = self.klass
@@ -1211,5 +1231,31 @@
         if not style:
             from reportlab.lib.styles import getSampleStyleSheet
             style=getSampleStyleSheet()['Code']
-        self._doctemplateAttr('frame').add_generated_content(P(value,style=style))
+        self.add_content(P(value,style=style))
         return 0,0
+
+class DocIf(DocPara):
+    def __init__(self,cond,thenBlock,elseBlock=[]):
+        Flowable.__init__(self)
+        self.expr = cond
+        self.blocks = elseBlock,thenBlock
+
+    def checkBlock(self,block):
+        if not isinstance(block,(list,tuple)):
+            block = (block,)
+        return block
+
+    def wrap(self,aW,aH):
+        self.add_content(*self.checkBlock(self.blocks[int(bool(self.funcWrap(aW,aH)))]))
+        return 0,0
+
+class DocWhile(DocIf):
+    def __init__(self,cond,whileBlock):
+        Flowable.__init__(self)
+        self.expr = cond
+        self.block = self.checkBlock(whileBlock)
+
+    def wrap(self,aW,aH):
+        if bool(self.funcWrap(aW,aH)):
+            self.add_content(*(list(self.block)+[self]))
+        return 0,0
--- a/reportlab/test/test_platypus_general.py	Thu Aug 21 16:50:11 2008 +0000
+++ b/reportlab/test/test_platypus_general.py	Fri Aug 22 10:31:32 2008 +0000
@@ -574,7 +574,6 @@
         from reportlab.lib.styles import ParagraphStyle
         from reportlab.graphics.shapes import Drawing, Rect
         from reportlab.platypus import SimpleDocTemplate
-        from reportlab.platypus.flowables import DocAssign, DocExec, DocPara
         normal = ParagraphStyle(name='Normal', fontName='Helvetica', fontSize=8.5, leading=11)
         header = ParagraphStyle(name='Heading1', parent=normal, fontSize=14, leading=19,
                     spaceAfter=6, keepWithNext=1)
@@ -582,14 +581,36 @@
         d.add(Rect(50, 50, 300, 100))
 
         story = [Paragraph("The section header", header), d,
+                ]
+        doc = SimpleDocTemplate('test_drawing_keepwithnext.pdf')
+        doc.build(story)
+
+    def test2(self):
+        #test from Wietse Jacobs
+        from reportlab.lib.styles import ParagraphStyle
+        from reportlab.graphics.shapes import Drawing, Rect
+        from reportlab.platypus import SimpleDocTemplate
+        from reportlab.platypus.flowables import DocAssign, DocExec, DocPara, DocIf, DocWhile
+        normal = ParagraphStyle(name='Normal', fontName='Helvetica', fontSize=8.5, leading=11)
+        header = ParagraphStyle(name='Heading1', parent=normal, fontSize=14, leading=19,
+                    spaceAfter=6, keepWithNext=1)
+        d = Drawing(400, 200)
+        d.add(Rect(50, 50, 300, 100))
+
+        story = [
                 DocAssign('currentFrame','doc.frame.id'),
                 DocAssign('currentPageTemplate','doc.pageTemplate.id'),
                 DocAssign('aW','availableWidth'),
                 DocAssign('aH','availableHeight'),
                 DocAssign('aWH','availableWidth,availableHeight'),
+                DocAssign('i',3),
+                DocIf('i>3',Paragraph('The value of i is larger than 3',normal),Paragraph('The value of i is not larger than 3',normal)),
+                DocIf('i==3',Paragraph('The value of i is equal to 3',normal),Paragraph('The value of i is not equal to 3',normal)),
+                DocIf('i<3',Paragraph('The value of i is less than 3',normal),Paragraph('The value of i is not less than 3',normal)),
+                DocWhile('i',[DocPara('i',format='The value of i is %(__expr__)d',style=normal),DocExec('i-=1')]),
                 DocPara('repr(doc._nameSpace)'),
                 ]
-        doc = SimpleDocTemplate('test_drawing_keepwithnext.pdf')
+        doc = SimpleDocTemplate('test_doc_programming.pdf')
         doc.build(story)
 
 def makeSuite():