[reportlab-users] question about keepWithNext and multibuild
    adam hyde 
    adam at flossmanuals.net
       
    Tue Sep 23 13:47:03 EDT 2008
    
    
  
goodness...it appears to work :)
I patched reportlab 2.1 and it looks good. I will run some more tests
today and tomorrow and let confirm the situation, but from what I see
now it is holding the keepWithNext while building the TOC. Fantastic!
Many thanks for all your help!
adam
On Tue, 2008-09-23 at 18:03 +0100, Robin Becker wrote:
> adam hyde wrote:
> >........
> > So we are really needing to build a TOC without multipass. We just pick
> > up on h1 headings using Pisa as this is the only depth required in a
> > book TOC for our purposes. If anyone has a nice snippet for producing a
> > TOC without multipass we would very much appreciate it.
> > 
> > adam
> .........
> 
> At the moment the keepTogether style is handled thusly;
> 
> in the main loop of the doctemplate build process at the start of the flowable 
> handling the head of the list is examined for flowables with keepWithNext style. 
> If any are found these are bundled together and replaced by a single 
> KeepTogether flowable; to avoid doing this recursively we force the keepWithNext 
> value for each flowable to be zero.
> 
> KeepTogether has just enough intelligence to try and ensure its contents stay on 
> a single page and when wrapped it always fails first time inorder to allow the 
> split method a chance to force a frame throw.
> 
> Even though we've messed about with the current passed story quite a bit the 
> main problem is that we changed the keepWithNext attribute on each flowable we 
> bundled together. The multiBuild method is careful to keep the original story 
> list intact, but we have forgotten that flowables are mutable (in this case a 
> structural property of the flowable was changed).
> 
> It should be possible to just remember the flowables which have been modified by 
> the handle_keepWithNext method and restore them at the end of the loop. After 
> checking I see that we are already attempting to eliminate some side effects of 
> the main loop.
> 
> 
> I have run all tests with this patch in place. It attempts to fix the 
> keepWithNext values back to their original state. Can you give it a whirl? It is 
> against current head, but the coding is not that hard so should apply to recent 
> sources.
> 
> C:\code\reportlab\platypus>svn diff doctemplate.py
> Index: doctemplate.py
> ===================================================================
> --- doctemplate.py      (revision 3298)
> +++ doctemplate.py      (working copy)
> @@ -600,8 +600,17 @@
>           if i:
>               if i<n and not getattr(flowables[i],'locChanger',None): i += 1
>               K = KeepTogether(flowables[:i])
> -            for f in K._content[:-1]:
> -                f.__dict__['keepWithNext'] = 0
> +            mbe = getattr(self,'_multiBuildEdits',None)
> +            if mbe:
> +                for f in K._content[:-1]:
> +                    if hasattr(f,'keepWithNext'):
> +                        mbe((setattr,f,'keepWithNext',f.keepWithNext))
> +                    else:
> +                        mbe((delattr,f,'keepWithNext')) #must get it from a style
> +                    f.__dict__['keepWithNext'] = 0
> +            else:
> +                for f in K._content[:-1]:
> +                    f.__dict__['keepWithNext'] = 0
>               del flowables[:i]
>               flowables.insert(0,K)
> 
> @@ -818,6 +827,8 @@
>           #better fix for filename is a 'file' problem
>           self._doSave = 0
>           passes = 0
> +        mbe = []
> +        self._multiBuildEdits = mbe.append
>           while 1:
>               passes += 1
>               if self._onProgress:
> @@ -832,12 +843,6 @@
>               self.build(tempStory, filename, canvasmaker)
>               #self.notify('debug',None)
> 
> -            #clean up so multi-build does not go wrong - the frame
> -            #packer might have tacked an attribute onto some flowables
> -            for elem in story:
> -                if hasattr(elem, '_postponed'):
> -                    del elem._postponed
> -
>               for fl in self._indexingFlowables:
>                   fl.afterBuild()
> 
> @@ -850,6 +855,18 @@
>               if passes > maxPasses:
>                   raise IndexError, "Index entries not resolved after %d passes" 
> % maxPasses
> 
> +            #clean up so multi-build does not go wrong - the frame
> +            #packer might have tacked an attribute onto some flowables
> +            for elem in story:
> +                if hasattr(elem, '_postponed'):
> +                    del elem._postponed
> +
> +            #work through any edits
> +            while mbe:
> +                e = mbe.pop(0)
> +                e[0](*e[1:])
> +
> +        del self._multiBuildEdits
>           if verbose: print 'saved'
> 
>       #these are pure virtuals override in derived classes
> 
> plain text document attachment (mbe.patch)
> Index: doctemplate.py
> ===================================================================
> --- doctemplate.py	(revision 3298)
> +++ doctemplate.py	(working copy)
> @@ -600,8 +600,17 @@
>          if i:
>              if i<n and not getattr(flowables[i],'locChanger',None): i += 1
>              K = KeepTogether(flowables[:i])
> -            for f in K._content[:-1]:
> -                f.__dict__['keepWithNext'] = 0
> +            mbe = getattr(self,'_multiBuildEdits',None)
> +            if mbe:
> +                for f in K._content[:-1]:
> +                    if hasattr(f,'keepWithNext'):
> +                        mbe((setattr,f,'keepWithNext',f.keepWithNext))
> +                    else:
> +                        mbe((delattr,f,'keepWithNext')) #must get it from a style
> +                    f.__dict__['keepWithNext'] = 0
> +            else:
> +                for f in K._content[:-1]:
> +                    f.__dict__['keepWithNext'] = 0
>              del flowables[:i]
>              flowables.insert(0,K)
>  
> @@ -818,6 +827,8 @@
>          #better fix for filename is a 'file' problem
>          self._doSave = 0
>          passes = 0
> +        mbe = []
> +        self._multiBuildEdits = mbe.append
>          while 1:
>              passes += 1
>              if self._onProgress:
> @@ -832,12 +843,6 @@
>              self.build(tempStory, filename, canvasmaker)
>              #self.notify('debug',None)
>  
> -            #clean up so multi-build does not go wrong - the frame
> -            #packer might have tacked an attribute onto some flowables
> -            for elem in story:
> -                if hasattr(elem, '_postponed'):
> -                    del elem._postponed
> -
>              for fl in self._indexingFlowables:
>                  fl.afterBuild()
>  
> @@ -850,6 +855,18 @@
>              if passes > maxPasses:
>                  raise IndexError, "Index entries not resolved after %d passes" % maxPasses
>  
> +            #clean up so multi-build does not go wrong - the frame
> +            #packer might have tacked an attribute onto some flowables
> +            for elem in story:
> +                if hasattr(elem, '_postponed'):
> +                    del elem._postponed
> +
> +            #work through any edits
> +            while mbe:
> +                e = mbe.pop(0)
> +                e[0](*e[1:])
> +
> +        del self._multiBuildEdits
>          if verbose: print 'saved'
>  
>      #these are pure virtuals override in derived classes
> _______________________________________________
> reportlab-users mailing list
> reportlab-users at reportlab.com
> http://two.pairlist.net/mailman/listinfo/reportlab-users
-- 
Adam Hyde
Founder FLOSS Manuals
http://www.flossmanuals.net
    
    
More information about the reportlab-users
mailing list