"Fossies" - the Fresh Open Source Software Archive

Member "xhtml2pdf-0.2.5/xhtml2pdf/document.py" (8 Oct 2020, 7404 Bytes) of package /linux/www/xhtml2pdf-0.2.5.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. For more information about "document.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.2.4_vs_0.2.5.

    1 # -*- coding: utf-8 -*-
    2 import io
    3 
    4 from xhtml2pdf.context import pisaContext
    5 from xhtml2pdf.default import DEFAULT_CSS
    6 from xhtml2pdf.parser import pisaParser
    7 from reportlab.platypus.flowables import Spacer
    8 from reportlab.platypus.frames import Frame
    9 from xhtml2pdf.xhtml2pdf_reportlab import PmlBaseDoc, PmlPageTemplate
   10 from xhtml2pdf.util import pisaTempFile, getBox, PyPDF2
   11 import logging
   12 import six
   13 
   14 
   15 if not six.PY2:
   16     from html import escape as html_escape
   17 else:
   18     from cgi import escape as html_escape
   19 
   20 # Copyright 2010 Dirk Holtwick, holtwick.it
   21 #
   22 # Licensed under the Apache License, Version 2.0 (the "License");
   23 # you may not use this file except in compliance with the License.
   24 # You may obtain a copy of the License at
   25 #
   26 #     http://www.apache.org/licenses/LICENSE-2.0
   27 #
   28 # Unless required by applicable law or agreed to in writing, software
   29 # distributed under the License is distributed on an "AS IS" BASIS,
   30 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   31 # See the License for the specific language governing permissions and
   32 # limitations under the License.
   33 
   34 log = logging.getLogger("xhtml2pdf")
   35 
   36 
   37 def pisaErrorDocument(dest, c):
   38     out = pisaTempFile(capacity=c.capacity)
   39     out.write("<p style='background-color:red;'><strong>%d error(s) occured:</strong><p>" % c.err)
   40     for mode, line, msg, _ in c.log:
   41         if mode == "error":
   42             out.write("<pre>%s in line %d: %s</pre>" %
   43                       (mode, line, html_escape(msg)))
   44 
   45     out.write("<p><strong>%d warning(s) occured:</strong><p>" % c.warn)
   46     for mode, line, msg, _ in c.log:
   47         if mode == "warning":
   48             out.write("<p>%s in line %d: %s</p>" %
   49                       (mode, line, html_escape(msg)))
   50 
   51     return pisaDocument(out.getvalue(), dest, raise_exception=False)
   52 
   53 
   54 def pisaStory(src, path=None, link_callback=None, debug=0, default_css=None,
   55               xhtml=False, encoding=None, context=None, xml_output=None,
   56               **kw):
   57     # Prepare Context
   58     if not context:
   59         context = pisaContext(path, debug=debug)
   60         context.pathCallback = link_callback
   61 
   62     # Use a default set of CSS definitions to get an expected output
   63     if default_css is None:
   64         default_css = DEFAULT_CSS
   65 
   66     # Parse and fill the story
   67     pisaParser(src, context, default_css, xhtml, encoding, xml_output)
   68 
   69     # Avoid empty documents
   70     if not context.story:
   71         context.story = [Spacer(1, 1)]
   72 
   73     if context.indexing_story:
   74         context.story.append(context.indexing_story)
   75 
   76     # Remove anchors if they do not exist (because of a bug in Reportlab)
   77     for frag, anchor in context.anchorFrag:
   78         if anchor not in context.anchorName:
   79             frag.link = None
   80     return context
   81 
   82 
   83 def pisaDocument(src, dest=None, path=None, link_callback=None, debug=0,
   84                  default_css=None, xhtml=False, encoding=None, xml_output=None,
   85                  raise_exception=True, capacity=100 * 1024, context_meta=None,
   86                  **kw):
   87     log.debug("pisaDocument options:\n  src = %r\n  dest = %r\n  path = %r\n  link_callback = %r\n  xhtml = %r\n  context_meta = %r",
   88               src,
   89               dest,
   90               path,
   91               link_callback,
   92               xhtml,
   93               context_meta)
   94 
   95     # Prepare simple context
   96     context = pisaContext(path, debug=debug, capacity=capacity)
   97 
   98     if context_meta is not None:
   99         context.meta.update(context_meta)
  100 
  101     context.pathCallback = link_callback
  102 
  103     # Build story
  104     context = pisaStory(src, path, link_callback, debug, default_css, xhtml,
  105                         encoding, context=context, xml_output=xml_output)
  106 
  107     # Buffer PDF into memory
  108     out = io.BytesIO()
  109 
  110     doc = PmlBaseDoc(
  111         out,
  112         pagesize=context.pageSize,
  113         author=context.meta["author"].strip(),
  114         subject=context.meta["subject"].strip(),
  115         keywords=[x.strip() for x in
  116                   context.meta["keywords"].strip().split(",") if x],
  117         title=context.meta["title"].strip(),
  118         showBoundary=0,
  119         allowSplitting=1)
  120 
  121     # Prepare templates and their frames
  122     if "body" in context.templateList:
  123         body = context.templateList["body"]
  124         del context.templateList["body"]
  125     else:
  126         x, y, w, h = getBox("1cm 1cm -1cm -1cm", context.pageSize)
  127         body = PmlPageTemplate(
  128             id="body",
  129             frames=[
  130                 Frame(x, y, w, h,
  131                       id="body",
  132                       leftPadding=0,
  133                       rightPadding=0,
  134                       bottomPadding=0,
  135                       topPadding=0)],
  136             pagesize=context.pageSize)
  137 
  138     doc.addPageTemplates([body] + list(context.templateList.values()))
  139 
  140     # Use multibuild e.g. if a TOC has to be created
  141     if context.multiBuild:
  142         doc.multiBuild(context.story)
  143     else:
  144         doc.build(context.story)
  145 
  146     # Add watermarks
  147     if PyPDF2:
  148         for bgouter in context.pisaBackgroundList:
  149             # If we have at least one background, then lets do it
  150             if bgouter:
  151                 istream = out
  152 
  153                 output = PyPDF2.PdfFileWriter()
  154                 input1 = PyPDF2.PdfFileReader(istream)
  155                 ctr = 0
  156                 # TODO: Why do we loop over the same list again?
  157                 # see bgouter at line 137
  158                 for bg in context.pisaBackgroundList:
  159                     page = input1.getPage(ctr)
  160                     if (
  161                             bg and not bg.notFound() and
  162                             (bg.mimetype == "application/pdf")
  163                     ):
  164                         bginput = PyPDF2.PdfFileReader(bg.getFile())
  165                         pagebg = bginput.getPage(0)
  166                         pagebg.mergePage(page)
  167                         page = pagebg
  168                     # Todo: the else-statement doesn't make a lot of sense to me; it's just throwing warnings
  169                     #  on unittesting \tests. Probably we have to rewrite the whole "background-image" stuff
  170                     #  to deal with cases like:
  171                     #  Page1 .jpg background
  172                     #  Page1 .pdf background
  173                     #  Page1 .jpg background, Page2 no background
  174                     #  Page1 .pdf background, Page2 no background
  175                     #  Page1 .jpg background, Page2 .pdf background
  176                     #  Page1 .pdf background, Page2 .jpg background
  177                     #  etc.
  178                     #  Right now it's kind of confusing. (fbernhart)
  179                     # else:
  180                     #     log.warning(context.warning(
  181                     #         "Background PDF %s doesn't exist.", bg))
  182                     output.addPage(page)
  183                     ctr += 1
  184                 out = pisaTempFile(capacity=context.capacity)
  185                 output.write(out)
  186                 # data = sout.getvalue()
  187                 # Found a background? So leave loop after first occurence
  188                 break
  189     else:
  190         log.warning(context.warning("PyPDF2 not installed!"))
  191 
  192     # Get the resulting PDF and write it to the file object
  193     # passed from the caller
  194 
  195     if dest is None:
  196         # No output file was passed - Let's use a pisaTempFile
  197         dest = io.BytesIO()
  198     context.dest = dest
  199 
  200     data = out.getvalue()
  201     context.dest.write(data)  # TODO: context.dest is a tempfile as well...
  202 
  203     return context