Prettier authors on covers.
[librarian.git] / librarian / pdf.py
index 246fd0c..e6d897d 100644 (file)
@@ -9,25 +9,27 @@ Creates one big XML from the book and its children, converts it to LaTeX
 with TeXML, then runs it by XeLaTeX.
 
 """
 with TeXML, then runs it by XeLaTeX.
 
 """
-from __future__ import with_statement
+from __future__ import print_function, unicode_literals
+
 import os
 import os.path
 import shutil
 import os
 import os.path
 import shutil
-from StringIO import StringIO
 from tempfile import mkdtemp, NamedTemporaryFile
 import re
 from copy import deepcopy
 from subprocess import call, PIPE
 from tempfile import mkdtemp, NamedTemporaryFile
 import re
 from copy import deepcopy
 from subprocess import call, PIPE
+from itertools import chain
 
 from Texml.processor import process
 from lxml import etree
 from lxml.etree import XMLSyntaxError, XSLTApplyError
 
 from Texml.processor import process
 from lxml import etree
 from lxml.etree import XMLSyntaxError, XSLTApplyError
+import six
 
 from librarian.dcparser import Person
 from librarian.parser import WLDocument
 
 from librarian.dcparser import Person
 from librarian.parser import WLDocument
-from librarian import ParseError, DCNS, get_resource, OutputFile
+from librarian import ParseError, DCNS, get_resource, OutputFile, RDFNS
 from librarian import functions
 from librarian import functions
-from librarian.cover import DefaultEbookCover
+from librarian.cover import make_cover
 from .sponsor import sponsor_logo
 
 
 from .sponsor import sponsor_logo
 
 
@@ -56,7 +58,7 @@ def insert_tags(doc, split_re, tagname, exclude=None):
 
     >>> t = etree.fromstring('<a><b>A-B-C</b>X-Y-Z</a>')
     >>> insert_tags(t, re.compile('-'), 'd')
 
     >>> t = etree.fromstring('<a><b>A-B-C</b>X-Y-Z</a>')
     >>> insert_tags(t, re.compile('-'), 'd')
-    >>> print etree.tostring(t)
+    >>> print(etree.tostring(t, encoding='unicode'))
     <a><b>A<d/>B<d/>C</b>X<d/>Y<d/>Z</a>
     """
 
     <a><b>A<d/>B<d/>C</b>X<d/>Y<d/>Z</a>
     """
 
@@ -85,7 +87,7 @@ def substitute_hyphens(doc):
     insert_tags(doc,
                 re.compile("(?<=[^-\s])-(?=[^-\s])"),
                 "dywiz",
     insert_tags(doc,
                 re.compile("(?<=[^-\s])-(?=[^-\s])"),
                 "dywiz",
-                exclude=[DCNS("identifier.url"), DCNS("rights.license")]
+                exclude=[DCNS("identifier.url"), DCNS("rights.license"), "meta"]
                 )
 
 
                 )
 
 
@@ -102,13 +104,25 @@ def fix_tables(doc):
         if kol.tail is not None:
             if not kol.tail.strip():
                 kol.tail = None
         if kol.tail is not None:
             if not kol.tail.strip():
                 kol.tail = None
-    for table in doc.iter(tag='tabela'):
+    for table in chain(doc.iter(tag='tabela'), doc.iter(tag='tabelka')):
         if table.get('ramka') == '1' or table.get('ramki') == '1':
             table.set('_format', '|' + 'X|' * len(table[0]))
         else:
             table.set('_format', 'X' * len(table[0]))
 
 
         if table.get('ramka') == '1' or table.get('ramki') == '1':
             table.set('_format', '|' + 'X|' * len(table[0]))
         else:
             table.set('_format', 'X' * len(table[0]))
 
 
+def mark_subauthors(doc):
+    root_author = ', '.join(elem.text for elem in doc.findall('./' + RDFNS('RDF') + '//' + DCNS('creator_parsed')))
+    last_author = None
+    # jeśli autor jest inny niż autor całości i niż poprzedni autor
+    # to wstawiamy jakiś znacznik w rdf?
+    for subutwor in doc.xpath('/utwor/utwor'):
+        author = ', '.join(elem.text for elem in subutwor.findall('.//' + DCNS('creator_parsed')))
+        if author not in (last_author, root_author):
+            subutwor.find('.//' + RDFNS('RDF')).append(etree.Element('use_subauthor'))
+        last_author = author
+
+
 def move_motifs_inside(doc):
     """ moves motifs to be into block elements """
     for master in doc.xpath('//powiesc|//opowiadanie|//liryka_l|//liryka_lp|'
 def move_motifs_inside(doc):
     """ moves motifs to be into block elements """
     for master in doc.xpath('//powiesc|//opowiadanie|//liryka_l|//liryka_lp|'
@@ -183,11 +197,11 @@ def package_available(package, args='', verbose=False):
     tempdir = mkdtemp('-wl2pdf-test')
     fpath = os.path.join(tempdir, 'test.tex')
     f = open(fpath, 'w')
     tempdir = mkdtemp('-wl2pdf-test')
     fpath = os.path.join(tempdir, 'test.tex')
     f = open(fpath, 'w')
-    f.write(r"""
-        \documentclass{wl}
-        \usepackage[%s]{%s}
-        \begin{document}
-        \end{document}
+    f.write("""
+        \\documentclass{wl}
+        \\usepackage[%s]{%s}
+        \\begin{document}
+        \\end{document}
         """ % (args, package))
     f.close()
     if verbose:
         """ % (args, package))
     f.close()
     if verbose:
@@ -199,7 +213,7 @@ def package_available(package, args='', verbose=False):
 
 
 def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
 
 
 def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
-              cover=None, flags=None, customizations=None, ilustr_path=''):
+              cover=None, flags=None, customizations=None, ilustr_path='', latex_dir=False):
     """ produces a PDF file with XeLaTeX
 
     wldoc: a WLDocument
     """ produces a PDF file with XeLaTeX
 
     wldoc: a WLDocument
@@ -219,7 +233,7 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
 
         if cover:
             if cover is True:
 
         if cover:
             if cover is True:
-                cover = DefaultEbookCover
+                cover = make_cover
             bound_cover = cover(book_info, width=1200)
             root.set('data-cover-width', str(bound_cover.width))
             root.set('data-cover-height', str(bound_cover.height))
             bound_cover = cover(book_info, width=1200)
             root.set('data-cover-width', str(bound_cover.width))
             root.set('data-cover-height', str(bound_cover.height))
@@ -259,6 +273,7 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
         substitute_hyphens(document.edoc)
         fix_hanging(document.edoc)
         fix_tables(document.edoc)
         substitute_hyphens(document.edoc)
         fix_hanging(document.edoc)
         fix_tables(document.edoc)
+        mark_subauthors(document.edoc)
 
         # wl -> TeXML
         style_filename = get_stylesheet("wl2tex")
 
         # wl -> TeXML
         style_filename = get_stylesheet("wl2tex")
@@ -292,8 +307,8 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
         del document  # no longer needed large object :)
 
         tex_path = os.path.join(temp, 'doc.tex')
         del document  # no longer needed large object :)
 
         tex_path = os.path.join(temp, 'doc.tex')
-        fout = open(tex_path, 'w')
-        process(StringIO(texml), fout, 'utf-8')
+        fout = open(tex_path, 'wb')
+        process(six.BytesIO(texml), fout, 'utf-8')
         fout.close()
         del texml
 
         fout.close()
         del texml
 
@@ -304,18 +319,24 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
         shutil.copy(get_resource('pdf/wl.cls'), temp)
         shutil.copy(get_resource('res/wl-logo.png'), temp)
 
         shutil.copy(get_resource('pdf/wl.cls'), temp)
         shutil.copy(get_resource('res/wl-logo.png'), temp)
 
+        if latex_dir:
+            return temp
+
         try:
             cwd = os.getcwd()
         except OSError:
             cwd = None
         os.chdir(temp)
 
         try:
             cwd = os.getcwd()
         except OSError:
             cwd = None
         os.chdir(temp)
 
-        if verbose:
-            p = call(['xelatex', tex_path])
-        else:
-            p = call(['xelatex', '-interaction=batchmode', tex_path], stdout=PIPE, stderr=PIPE)
-        if p:
-            raise ParseError("Error parsing .tex file")
+        # some things work better when compiled twice
+        # (table of contents, [line numbers - disabled])
+        for run in range(2):
+            if verbose:
+                p = call(['xelatex', tex_path])
+            else:
+                p = call(['xelatex', '-interaction=batchmode', tex_path], stdout=PIPE, stderr=PIPE)
+            if p:
+                raise ParseError("Error parsing .tex file")
 
         if cwd is not None:
             os.chdir(cwd)
 
         if cwd is not None:
             os.chdir(cwd)
@@ -326,7 +347,7 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
         shutil.rmtree(temp)
         return OutputFile.from_filename(output_file.name)
 
         shutil.rmtree(temp)
         return OutputFile.from_filename(output_file.name)
 
-    except (XMLSyntaxError, XSLTApplyError), e:
+    except (XMLSyntaxError, XSLTApplyError) as e:
         raise ParseError(e)
 
 
         raise ParseError(e)
 
 
@@ -341,14 +362,14 @@ def load_including_children(wldoc=None, provider=None, uri=None):
         text = f.read().decode('utf-8')
         f.close()
     elif wldoc is not None:
         text = f.read().decode('utf-8')
         f.close()
     elif wldoc is not None:
-        text = etree.tostring(wldoc.edoc, encoding=unicode)
+        text = etree.tostring(wldoc.edoc, encoding='unicode')
         provider = wldoc.provider
     else:
         raise ValueError('Neither a WLDocument, nor provider and URI were provided.')
 
         provider = wldoc.provider
     else:
         raise ValueError('Neither a WLDocument, nor provider and URI were provided.')
 
-    text = re.sub(ur"([\u0400-\u04ff]+)", ur"<alien>\1</alien>", text)
+    text = re.sub(r"([\u0400-\u04ff]+)", r"<alien>\1</alien>", text)
 
 
-    document = WLDocument.from_string(text, parse_dublincore=True, provider=provider)
+    document = WLDocument.from_bytes(text.encode('utf-8'), parse_dublincore=True, provider=provider)
     document.swap_endlines()
 
     for child_uri in document.book_info.parts:
     document.swap_endlines()
 
     for child_uri in document.book_info.parts: