33 from reportlab.platypus.paragraph import Paragraph |
33 from reportlab.platypus.paragraph import Paragraph |
34 from reportlab.platypus.frames import Frame |
34 from reportlab.platypus.frames import Frame |
35 from reportlab.rl_config import defaultPageSize, verbose |
35 from reportlab.rl_config import defaultPageSize, verbose |
36 import reportlab.lib.sequencer |
36 import reportlab.lib.sequencer |
37 from reportlab.pdfgen import canvas |
37 from reportlab.pdfgen import canvas |
|
38 import tokenize |
38 |
39 |
39 from types import * |
40 from types import * |
40 import sys |
41 import sys |
41 import logging |
42 import logging |
42 logger = logging.getLogger("reportlab.platypus") |
43 logger = logging.getLogger("reportlab.platypus") |
336 _firstPageTemplateIndex = 0 |
337 _firstPageTemplateIndex = 0 |
337 |
338 |
338 def __init__(self, filename, **kw): |
339 def __init__(self, filename, **kw): |
339 """create a document template bound to a filename (see class documentation for keyword arguments)""" |
340 """create a document template bound to a filename (see class documentation for keyword arguments)""" |
340 self.filename = filename |
341 self.filename = filename |
|
342 self._nameSpace = dict(doc=self) |
|
343 self._lifetimes = {} |
341 |
344 |
342 for k in self._initArgs.keys(): |
345 for k in self._initArgs.keys(): |
343 if not kw.has_key(k): |
346 if not kw.has_key(k): |
344 v = self._initArgs[k] |
347 v = self._initArgs[k] |
345 else: |
348 else: |
432 def handle_pageEnd(self): |
435 def handle_pageEnd(self): |
433 ''' show the current page |
436 ''' show the current page |
434 check the next page template |
437 check the next page template |
435 hang a page begin |
438 hang a page begin |
436 ''' |
439 ''' |
|
440 self._removeVars('page') |
437 #detect infinite loops... |
441 #detect infinite loops... |
438 if self._curPageFlowableCount == 0: |
442 if self._curPageFlowableCount == 0: |
439 self._emptyPages += 1 |
443 self._emptyPages += 1 |
440 else: |
444 else: |
441 self._emptyPages = 0 |
445 self._emptyPages = 0 |
486 |
490 |
487 def handle_frameEnd(self,resume=0): |
491 def handle_frameEnd(self,resume=0): |
488 ''' Handles the semantics of the end of a frame. This includes the selection of |
492 ''' Handles the semantics of the end of a frame. This includes the selection of |
489 the next frame or if this is the last frame then invoke pageEnd. |
493 the next frame or if this is the last frame then invoke pageEnd. |
490 ''' |
494 ''' |
|
495 self._removeVars('frame') |
491 self._leftExtraIndent = self.frame._leftExtraIndent |
496 self._leftExtraIndent = self.frame._leftExtraIndent |
492 self._rightExtraIndent = self.frame._rightExtraIndent |
497 self._rightExtraIndent = self.frame._rightExtraIndent |
493 |
498 |
494 f = self.frame |
499 f = self.frame |
495 if hasattr(self,'_nextFrameIndex'): |
500 if hasattr(self,'_nextFrameIndex'): |
555 else: |
560 else: |
556 raise TypeError, "argument fx should be string or integer" |
561 raise TypeError, "argument fx should be string or integer" |
557 |
562 |
558 def handle_currentFrame(self,fx,resume=0): |
563 def handle_currentFrame(self,fx,resume=0): |
559 '''change to the frame with name or index fx''' |
564 '''change to the frame with name or index fx''' |
560 |
|
561 self.handle_nextFrame(fx,resume) |
565 self.handle_nextFrame(fx,resume) |
562 self.handle_frameEnd(resume) |
566 self.handle_frameEnd(resume) |
563 |
567 |
564 def handle_breakBefore(self, flowables): |
568 def handle_breakBefore(self, flowables): |
565 '''preprocessing step to allow pageBreakBefore and frameBreakBefore attributes''' |
569 '''preprocessing step to allow pageBreakBefore and frameBreakBefore attributes''' |
692 def _startBuild(self, filename=None, canvasmaker=canvas.Canvas): |
696 def _startBuild(self, filename=None, canvasmaker=canvas.Canvas): |
693 self._calc() |
697 self._calc() |
694 |
698 |
695 #each distinct pass gets a sequencer |
699 #each distinct pass gets a sequencer |
696 self.seq = reportlab.lib.sequencer.Sequencer() |
700 self.seq = reportlab.lib.sequencer.Sequencer() |
697 |
701 |
698 self.canv = canvasmaker(filename or self.filename, |
702 self.canv = canvasmaker(filename or self.filename, |
699 pagesize=self.pagesize, |
703 pagesize=self.pagesize, |
700 invariant=self.invariant, |
704 invariant=self.invariant, |
701 pageCompression=self.pageCompression) |
705 pageCompression=self.pageCompression) |
702 |
706 |
883 |
888 |
884 def afterFlowable(self, flowable): |
889 def afterFlowable(self, flowable): |
885 '''called after a flowable has been rendered''' |
890 '''called after a flowable has been rendered''' |
886 pass |
891 pass |
887 |
892 |
|
893 _allowedLifetimes = 'page','frame','build','forever' |
|
894 def docAssign(self,var,expr,lifetime): |
|
895 var=var.strip()+'\n' |
|
896 expr=expr.strip() |
|
897 T=tokenize.generate_tokens(lambda :var) |
|
898 tokens=[] |
|
899 while 1: |
|
900 t=T.next() |
|
901 if t[0]==tokenize.NEWLINE: break |
|
902 tokens.append(t) |
|
903 simple = len(tokens)==1 |
|
904 del T |
|
905 var=var.strip() |
|
906 try: |
|
907 if lifetime not in self._allowedLifetimes: |
|
908 raise ValueError('bad lifetime %r not in %r'%(lifetime,self._allowedLifetimes)) |
|
909 exec '%s=(%s)' % (var,expr) in {},self._nameSpace |
|
910 except: |
|
911 exc = sys.exc_info()[1] |
|
912 args = list(exc.args) |
|
913 args[-1] += '\ndocAssign %s=(%s) lifetime=%r failed!' % (var,expr,lifetime) |
|
914 exc.args = tuple(args) |
|
915 raise |
|
916 if simple: |
|
917 for v in self._lifetimes.itervalues(): |
|
918 if var in v: |
|
919 v.remove(var) |
|
920 self._lifetimes.setdefault(lifetime,set([])).add(var) |
|
921 |
|
922 def docExec(self,stmt): |
|
923 stmt=stmt.strip() |
|
924 try: |
|
925 exec stmt in {},self._nameSpace |
|
926 except: |
|
927 exc = sys.exc_info()[1] |
|
928 args = list(exc.args) |
|
929 args[-1] += '\ndocExec %s failed!' % stmt |
|
930 exc.args = tuple(args) |
|
931 raise |
|
932 |
|
933 def _removeVars(self,lifetime): |
|
934 for k in self._lifetimes.setdefault(lifetime,[]): |
|
935 try: |
|
936 del self._nameSpace[k] |
|
937 except KeyError: |
|
938 pass |
|
939 del self._lifetimes[lifetime] |
|
940 |
|
941 def docEval(self,expr): |
|
942 try: |
|
943 return eval(expr.strip(),{},self._nameSpace) |
|
944 except: |
|
945 exc = sys.exc_info()[1] |
|
946 args = list(exc.args) |
|
947 args[-1] += '\ndocEval %s failed!' % expr |
|
948 exc.args = tuple(args) |
|
949 raise |
|
950 |
888 class SimpleDocTemplate(BaseDocTemplate): |
951 class SimpleDocTemplate(BaseDocTemplate): |
889 """A special case document template that will handle many simple documents. |
952 """A special case document template that will handle many simple documents. |
890 See documentation for BaseDocTemplate. No pageTemplates are required |
953 See documentation for BaseDocTemplate. No pageTemplates are required |
891 for this special case. A page templates are inferred from the |
954 for this special case. A page templates are inferred from the |
892 margin information and the onFirstPage, onLaterPages arguments to the build method. |
955 margin information and the onFirstPage, onLaterPages arguments to the build method. |