Merge remote-tracking branch 'mgorny/fb2'
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Mon, 24 Sep 2012 12:43:39 +0000 (14:43 +0200)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Mon, 24 Sep 2012 12:43:39 +0000 (14:43 +0200)
21 files changed:
librarian/__init__.py
librarian/book2anything.py
librarian/cover.py
librarian/dcparser.py
librarian/epub.py
librarian/epub/xsltLast.xsl
librarian/parser.py
librarian/pdf.py
librarian/pdf/wl2tex.xslt
scripts/book2cover
setup.py
tests/files/picture/angelus-novus.jpeg [new file with mode: 0644]
tests/files/picture/angelus-novus.png [deleted file]
tests/files/picture/angelus-novus.xml
tests/files/text/asnyk_miedzy_nami_expected.txt
tests/files/text/asnyk_zbior.xml
tests/files/text/do-mlodych.xml [new file with mode: 0755]
tests/files/text/miedzy-nami-nic-nie-bylo.xml
tests/test_epub.py
tests/test_pdf.py [new file with mode: 0644]
tests/test_picture.py

index 8a69d00..c46d5d1 100644 (file)
@@ -8,15 +8,22 @@ from __future__ import with_statement
 import os
 import re
 import shutil
+import urllib
+
 
 class UnicodeException(Exception):
     def __str__(self):
         """ Dirty workaround for Python Unicode handling problems. """
-        return self.message
+        return unicode(self).encode('utf-8')
 
     def __unicode__(self):
         """ Dirty workaround for Python Unicode handling problems. """
-        return self.message
+        args = self.args[0] if len(self.args) == 1 else self.args
+        try:
+            message = unicode(args)
+        except UnicodeDecodeError:
+            message = unicode(args, encoding='utf-8', errors='ignore')
+        return message
 
 class ParseError(UnicodeException):
     pass
@@ -267,3 +274,8 @@ class OutputFile(object):
         if not os.path.isdir(dirname):
             os.makedirs(dirname)
         shutil.copy(self.get_filename(), path)
+
+
+class URLOpener(urllib.FancyURLopener):
+    version = 'FNP Librarian (http://github.com/fnp/librarian)'
+urllib._urlopener = URLOpener()
index 7660ec7..b8b8d27 100755 (executable)
@@ -99,7 +99,9 @@ class Book2Anything(object):
         # Add cover support, if any.
         if cls.uses_cover:
             if options.image_cache:
-                transform_args['cover'] = lambda x: WLCover(x, image_cache = options.image_cache)
+                def cover_class(*args, **kwargs):
+                    return WLCover(image_cache=options.image_cache, *args, **kwargs)
+                transform_args['cover'] = cover_class
             elif not cls.cover_optional or options.with_cover:
                 transform_args['cover'] = WLCover
 
index 02d76f9..be34e26 100644 (file)
@@ -5,7 +5,8 @@
 #
 import re
 import Image, ImageFont, ImageDraw, ImageFilter
-from librarian import get_resource
+from StringIO import StringIO
+from librarian import get_resource, OutputFile, URLOpener
 
 
 class TextBox(object):
@@ -119,9 +120,11 @@ class Cover(object):
         'PNG': 'image/png',
         }
 
-    def __init__(self, book_info):
+    def __init__(self, book_info, format=None):
         self.author = ", ".join(auth.readable() for auth in book_info.authors)
         self.title = book_info.title
+        if format is not None:
+            self.format = format
 
     def pretty_author(self):
         """Allows for decorating author's name."""
@@ -180,6 +183,11 @@ class Cover(object):
     def save(self, *args, **kwargs):
         return self.image().save(format=self.format, *args, **kwargs)
 
+    def output_file(self, *args, **kwargs):
+        imgstr = StringIO()
+        self.save(imgstr, *args, **kwargs)
+        return OutputFile.from_string(imgstr.getvalue())
+
 
 class WLCover(Cover):
     """Default Wolne Lektury cover generator."""
@@ -212,24 +220,21 @@ class WLCover(Cover):
         u'Współczesność': '#06393d',
     }
 
-    def __init__(self, book_info, image_cache=None):
-        super(WLCover, self).__init__(book_info)
+    def __init__(self, book_info, format=None, image_cache=None):
+        super(WLCover, self).__init__(book_info, format=format)
         self.kind = book_info.kind
         self.epoch = book_info.epoch
         if book_info.cover_url:
-            from urllib2 import urlopen
-            from StringIO import StringIO
-
             url = book_info.cover_url
             bg_src = None
             if image_cache:
                 from urllib import quote
                 try:
-                    bg_src = urlopen(image_cache + quote(url, safe=""))
+                    bg_src = URLOpener().open(image_cache + quote(url, safe=""))
                 except:
                     pass
             if bg_src is None:
-                bg_src = urlopen(url)
+                bg_src = URLOpener().open(url)
             self.background_img = StringIO(bg_src.read())
             bg_src.close()
         else:
index 5a571ec..eddd8e5 100644 (file)
@@ -115,10 +115,21 @@ class Field(object):
         except ValueError, e:
             raise ValidationError("Field '%s' - invald value: %s" % (self.uri, e.message))
 
-    def validate(self, fdict, strict=False):
+    def validate(self, fdict, fallbacks=None, strict=False):
+        if fallbacks is None:
+            fallbacks = {}
         if not fdict.has_key(self.uri):
             if not self.required:
-                f = self.default
+                # Accept single value for single fields and saliases.
+                if self.name in fallbacks:
+                    if self.multiple:
+                        f = fallbacks[self.name]
+                    else:
+                        f = [fallbacks[self.name]]
+                elif self.salias and self.salias in fallbacks:
+                    f = [fallbacks[self.salias]]
+                else:
+                    f = self.default
             else:
                 raise ValidationError("Required field %s not found" % self.uri)
         else:
@@ -224,7 +235,7 @@ class WorkInfo(object):
 
         return cls(desc.attrib, field_dict, *args, **kwargs)
 
-    def __init__(self, rdf_attrs, dc_fields, strict=False):
+    def __init__(self, rdf_attrs, dc_fields, fallbacks=None, strict=False):
         """rdf_attrs should be a dictionary-like object with any attributes of the RDF:Description.
         dc_fields - dictionary mapping DC fields (with namespace) to list of text values for the
         given field. """
@@ -233,7 +244,8 @@ class WorkInfo(object):
         self.fmap = {}
 
         for field in self.FIELDS:
-            value = field.validate(dc_fields, strict=strict)
+            value = field.validate(dc_fields, fallbacks=fallbacks,
+                            strict=strict)
             setattr(self, 'prop_' + field.name, value)
             self.fmap[field.name] = field
             if field.salias: self.fmap[field.salias] = field
index 469ff40..bbeb3d7 100644 (file)
@@ -368,6 +368,10 @@ def transform(wldoc, verbose=False,
         for flag in flags:
             document.edoc.getroot().set(flag, 'yes')
 
+    # add editors info
+    document.edoc.getroot().set('editors', u', '.join(sorted(
+        editor.readable() for editor in document.editors())))
+
     opf = xslt(document.book_info.to_etree(), get_resource('epub/xsltContent.xsl'))
     manifest = opf.find('.//' + OPFNS('manifest'))
     guide = opf.find('.//' + OPFNS('guide'))
index 751f97a..5288443 100644 (file)
   </xsl:template>
 
   <xsl:template name="editors">
-    <xsl:if test="//dc:contributor.editor[text()]|//dc:contributor.technical_editor[text()]">
+    <xsl:if test="@editors">
         <p class="info">
             <xsl:text>Opracowanie redakcyjne i przypisy: </xsl:text>
-            <xsl:for-each select="//dc:contributor.editor[text()]|//dc:contributor.technical_editor[text() and not(//dc:contributor.editor/text()=text())]">
-                <xsl:sort />
-                <xsl:if test="position() != 1">, </xsl:if>
-                <xsl:apply-templates mode="person" />
-            </xsl:for-each>.
-        </p>
+            <xsl:value-of select="@editors" />.</p>
     </xsl:if>
   </xsl:template>
 
-  <xsl:template match="dc:contributor.editor|dc:contributor.technical_editor">
-      <br /><xsl:apply-templates mode='person' />
-  </xsl:template>
-
   <xsl:template match="text()" mode="person">
     <xsl:value-of select="wl:person_name(.)" />
   </xsl:template>
index 6343d21..a9e8c65 100644 (file)
@@ -5,6 +5,7 @@
 #
 from librarian import ValidationError, NoDublinCore,  ParseError, NoProvider
 from librarian import RDFNS
+from librarian.cover import WLCover
 from librarian import dcparser
 
 from xml.parsers.expat import ExpatError
@@ -19,7 +20,8 @@ class WLDocument(object):
     LINE_SWAP_EXPR = re.compile(r'/\s', re.MULTILINE | re.UNICODE)
     provider = None
 
-    def __init__(self, edoc, parse_dublincore=True, provider=None, strict=False):
+    def __init__(self, edoc, parse_dublincore=True, provider=None, 
+                    strict=False, meta_fallbacks=None):
         self.edoc = edoc
         self.provider = provider
 
@@ -37,7 +39,7 @@ class WLDocument(object):
                 raise NoDublinCore('Document has no DublinCore - which is required.')
 
             self.book_info = dcparser.BookInfo.from_element(
-                    self.rdf_elem, strict=strict)
+                    self.rdf_elem, fallbacks=meta_fallbacks, strict=strict)
         else:
             self.book_info = None
 
@@ -46,7 +48,7 @@ class WLDocument(object):
         return cls.from_file(StringIO(xml), *args, **kwargs)
 
     @classmethod
-    def from_file(cls, xmlfile, parse_dublincore=True, provider=None):
+    def from_file(cls, xmlfile, *args, **kwargs):
 
         # first, prepare for parsing
         if isinstance(xmlfile, basestring):
@@ -67,7 +69,7 @@ class WLDocument(object):
             parser = etree.XMLParser(remove_blank_text=False)
             tree = etree.parse(StringIO(data.encode('utf-8')), parser)
 
-            return cls(tree, parse_dublincore=parse_dublincore, provider=provider)
+            return cls(tree, *args, **kwargs)
         except (ExpatError, XMLSyntaxError, XSLTApplyError), e:
             raise ParseError(e)
 
@@ -147,7 +149,7 @@ class WLDocument(object):
                 xpath = self.path_to_xpath(key)
                 node = self.edoc.xpath(xpath)[0]
                 repl = etree.fromstring(u"<%s>%s</%s>" %(node.tag, data, node.tag) )
-                node.getparent().replace(node, repl);
+                node.getparent().replace(node, repl)
             except Exception, e:
                 unmerged.append( repr( (key, xpath, e) ) )
 
@@ -163,6 +165,21 @@ class WLDocument(object):
             node.tag = 'span'
             node.tail = tail
 
+    def editors(self):
+        """Returns a set of all editors for book and its children.
+
+        :returns: set of dcparser.Person objects
+        """
+        if self.book_info is None:
+            raise NoDublinCore('No Dublin Core in document.')
+        persons = set(self.book_info.editors +
+                        self.book_info.technical_editors)
+        for child in self.parts():
+            persons.update(child.editors())
+        if None in persons:
+            persons.remove(None)
+        return persons
+
     # Converters
 
     def as_html(self, *args, **kwargs):
@@ -189,6 +206,11 @@ class WLDocument(object):
         from librarian import fb2
         return fb2.transform(self, *args, **kwargs)
 
+    def as_cover(self, cover_class=None, *args, **kwargs):
+        if cover_class is None:
+            cover_class = WLCover
+        return cover_class(self.book_info, *args, **kwargs).output_file()
+
     def save_output_file(self, output_file, output_path=None,
             output_dir_path=None, make_author_dir=False, ext=None):
         if output_dir_path:
index 3c83cad..9fb92b1 100644 (file)
@@ -3,6 +3,12 @@
 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
+"""PDF creation library.
+
+Creates one big XML from the book and its children, converts it to LaTeX
+with TeXML, then runs it by XeLaTeX.
+
+"""
 from __future__ import with_statement
 import os
 import os.path
@@ -135,9 +141,13 @@ def hack_motifs(doc):
 
 
 def parse_creator(doc):
-    """ find all dc:creator and dc.contributor tags and add *_parsed versions with forenames first """
+    """Generates readable versions of creator and translator tags.
+
+    Finds all dc:creator and dc.contributor.translator tags
+    and adds *_parsed versions with forenames first.
+    """
     for person in doc.xpath("|".join('//dc:'+(tag) for tag in (
-                    'creator', 'contributor.translator', 'contributor.editor', 'contributor.technical_editor')),
+                    'creator', 'contributor.translator')),
                     namespaces = {'dc': str(DCNS)})[::-1]:
         if not person.text:
             continue
@@ -188,32 +198,39 @@ def transform(wldoc, verbose=False, save_tex=None, morefloats=None,
 
     # Parse XSLT
     try:
+        book_info = wldoc.book_info
         document = load_including_children(wldoc)
+        root = document.edoc.getroot()
 
         if cover:
             if cover is True:
                 cover = WLCover
-            bound_cover = cover(document.book_info)
-            document.edoc.getroot().set('data-cover-width', str(bound_cover.width))
-            document.edoc.getroot().set('data-cover-height', str(bound_cover.height))
+            bound_cover = cover(book_info)
+            root.set('data-cover-width', str(bound_cover.width))
+            root.set('data-cover-height', str(bound_cover.height))
             if bound_cover.uses_dc_cover:
-                if document.book_info.cover_by:
-                    document.edoc.getroot().set('data-cover-by', document.book_info.cover_by)
-                if document.book_info.cover_source:
-                    document.edoc.getroot().set('data-cover-source', document.book_info.cover_source)
+                if book_info.cover_by:
+                    root.set('data-cover-by', book_info.cover_by)
+                if book_info.cover_source:
+                    root.set('data-cover-source',
+                            book_info.cover_source)
         if flags:
             for flag in flags:
-                document.edoc.getroot().set('flag-' + flag, 'yes')
+                root.set('flag-' + flag, 'yes')
 
         # check for LaTeX packages
         if morefloats:
-            document.edoc.getroot().set('morefloats', morefloats.lower())
+            root.set('morefloats', morefloats.lower())
         elif package_available('morefloats', 'maxfloats=19'):
-            document.edoc.getroot().set('morefloats', 'new')
+            root.set('morefloats', 'new')
 
         # add customizations
         if customizations is not None:
-            document.edoc.getroot().set('customizations', u','.join(customizations))
+            root.set('customizations', u','.join(customizations))
+
+        # add editors info
+        root.set('editors', u', '.join(sorted(
+            editor.readable() for editor in document.editors())))
 
         # hack the tree
         move_motifs_inside(document.edoc)
@@ -294,7 +311,8 @@ def load_including_children(wldoc=None, provider=None, uri=None):
 
     text = re.sub(ur"([\u0400-\u04ff]+)", ur"<alien>\1</alien>", text)
 
-    document = WLDocument.from_string(text, parse_dublincore=True)
+    document = WLDocument.from_string(text,
+                parse_dublincore=True, provider=provider)
     document.swap_endlines()
 
     for child_uri in document.book_info.parts:
index 1a675ba..909cf4b 100644 (file)
                     </xsl:choose>
                 </xsl:if>
                 }
+                \def\editors{<xsl:call-template name="editors" />}
             </TeXML>
 
             <cmd name="editorialsection" />
+
         </env>
     </TeXML>
 </xsl:template>
                 \vspace{.6em}
             </xsl:if>}
         \def\description{<xsl:apply-templates select=".//dc:description" mode="inline" />}
-        \def\editors{<xsl:call-template name="editors" />}
     </TeXML>
 </xsl:template>
 
 </xsl:template>
 
 <xsl:template name="editors">
-    <xsl:if test="//dc:contributor.editor_parsed|//dc:contributor.technical_editor_parsed">
+    <xsl:if test="@editors">
         <xsl:text>Opracowanie redakcyjne i przypisy: </xsl:text>
-        <xsl:for-each select="//dc:contributor.editor_parsed|//dc:contributor.technical_editor_parsed[not(//dc:contributor.editor_parsed/text()=text())]">
-            <xsl:sort select="@sortkey" />
-            <xsl:if test="position() != 1">, </xsl:if>
-            <xsl:apply-templates mode="inline" />
-        </xsl:for-each>.
+        <xsl:value-of select="@editors" />
+        <xsl:text>.</xsl:text>
     </xsl:if>
 </xsl:template>
 
index ae11e60..3cc0ed7 100755 (executable)
@@ -17,9 +17,7 @@ class Book2Cover(Book2Anything):
 
     @staticmethod
     def transform(wldoc, cover):
-        output = StringIO()
-        cover(wldoc.book_info).save(output)
-        return OutputFile.from_string(output.getvalue())
+        return wldoc.as_cover(cover_class=cover)
 
 
 if __name__ == '__main__':
index b6dbcb4..f88817e 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -21,7 +21,7 @@ def whole_tree(prefix, path):
 
 setup(
     name='librarian',
-    version='1.5',
+    version='1.5.1',
     description='Converter from WolneLektury.pl XML-based language to XHTML, TXT and other formats',
     author="Marek Stępniowski",
     author_email='marek@stepniowski.com',
diff --git a/tests/files/picture/angelus-novus.jpeg b/tests/files/picture/angelus-novus.jpeg
new file mode 100644 (file)
index 0000000..fd0394f
Binary files /dev/null and b/tests/files/picture/angelus-novus.jpeg differ
diff --git a/tests/files/picture/angelus-novus.png b/tests/files/picture/angelus-novus.png
deleted file mode 100644 (file)
index 9925dad..0000000
Binary files a/tests/files/picture/angelus-novus.png and /dev/null differ
index 0f26730..964faed 100644 (file)
@@ -18,9 +18,9 @@
       <dc:rights xml:lang="pl">Domena publiczna - Paul Klee zm. 1940</dc:rights>
       <dc:date.pd xml:lang="pl">1940</dc:date.pd>
       <dc:type>Image</dc:type>
-      <dc:format xml:lang="pl">image/png</dc:format>
-      <dc:format.dimensions xml:lang="pl">1645 x 2000 px</dc:format.dimensions>
-      <dc:format.checksum.sha1 xml:lang="pl">d9ead48f3442ac4e1add602aacdffa4638ae8e21</dc:format.checksum.sha1>
+      <dc:format xml:lang="pl">image/jpeg</dc:format>
+      <dc:format.dimensions xml:lang="pl">329 x 400 px</dc:format.dimensions>
+      <dc:format.checksum.sha1 xml:lang="pl">5ed8e8d24d92017c6341c0b8cfcc414dec55b8bf</dc:format.checksum.sha1>
       <dc:date xml:lang="pl">1920</dc:date>
       <dc:language xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">lat</dc:language>
     </rdf:Description>
     <div type="whole"/>
   </sem>
   <sem type="theme" theme="anioł historii">
-    <div type="area" x1="462" y1="212" x2="1283" y2="1730"/>
+    <div type="area" x1="92" y1="42" x2="257" y2="346"/>
   </sem>
   <sem type="theme" theme="spojrzenie">
-    <div type="area" x1="688" y1="500" x2="1054" y2="618"/>
+    <div type="area" x1="138" y1="100" x2="211" y2="124"/>
   </sem>
   <sem type="object" object="skrzydło">
-    <div type="area" x1="468" y1="741" x2="694" y2="1027"/>
-    <div type="area" x1="1044" y1="762" x2="1260" y2="1041"/>
+    <div type="area" x1="94" y1="148" x2="139" y2="205"/>
+    <div type="area" x1="209" y1="152" x2="252" y2="1041"/>
   </sem>
  
 </picture>
index 70c3185..d300b3e 100644 (file)
@@ -39,4 +39,4 @@ Tekst opracowany na podstawie: (Asnyk, Adam) El...y (1838-1897), Poezye, t. 3,
 
 Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN.
 
-Opracowanie redakcyjne i przypisy: Aleksandra Sekuła, Olga Sutkowska
+Opracowanie redakcyjne i przypisy: Adam Fikcyjny, Aleksandra Sekuła, Olga Sutkowska
index c585a8b..6a781f3 100755 (executable)
@@ -9,9 +9,11 @@
 <dc:subject.period xml:lang="pl">Pozytywizm</dc:subject.period>
 <dc:subject.type xml:lang="pl">Liryka</dc:subject.type>
 <dc:subject.genre xml:lang="pl">Wiersz</dc:subject.genre>
+<dc:contributor.technical_editor xml:lang="pl">Fikcyjny, Adam</dc:contributor.technical_editor>
 <dc:description xml:lang="pl">Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN.</dc:description>
 <dc:identifier.url xml:lang="pl">http://wolnelektury.pl/katalog/lektura/poezye</dc:identifier.url>
 <dc:relation.hasPart xml:lang="pl">http://wolnelektury.pl/katalog/lektura/miedzy-nami-nic-nie-bylo</dc:relation.hasPart>
+<dc:relation.hasPart xml:lang="pl">http://wolnelektury.pl/katalog/lektura/do-mlodych</dc:relation.hasPart>
 <dc:source.URL xml:lang="pl">http://www.polona.pl/Content/5164</dc:source.URL>
 <dc:source xml:lang="pl">(Asnyk, Adam) El...y (1838-1897), Poezye, t. 3,  Gebethner i Wolff, wyd. nowe poprzedzone słowem wstępnym St. Krzemińskiego, Warszawa, 1898</dc:source>
 <dc:rights xml:lang="pl">Domena publiczna - Adam Asnyk zm. 1897</dc:rights>
diff --git a/tests/files/text/do-mlodych.xml b/tests/files/text/do-mlodych.xml
new file mode 100755 (executable)
index 0000000..21fa522
--- /dev/null
@@ -0,0 +1,70 @@
+<utwor><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<rdf:Description rdf:about="http://redakcja.wolnelektury.pl/documents/book/do-mlodych/">
+<dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Asnyk, Adam</dc:creator>
+<dc:title xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Do młodych</dc:title>
+<dc:contributor.editor xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Sekuła, Aleksandra</dc:contributor.editor>
+<dc:contributor.technical_editor xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Sutkowska, Olga</dc:contributor.technical_editor>
+<dc:publisher xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Fundacja Nowoczesna Polska</dc:publisher>
+<dc:subject.period xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Pozytywizm</dc:subject.period>
+<dc:subject.type xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Liryka</dc:subject.type>
+<dc:subject.genre xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Wiersz</dc:subject.genre>
+<dc:description xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Publikacja zrealizowana w ramach projektu Wolne Lektury (http://wolnelektury.pl). Reprodukcja cyfrowa wykonana przez Bibliotekę Narodową z egzemplarza pochodzącego ze zbiorów BN.</dc:description>
+<dc:identifier.url xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">http://wolnelektury.pl/katalog/lektura/do-mlodych</dc:identifier.url>
+<dc:source.URL xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">http://www.polona.pl/Content/8616</dc:source.URL>
+<dc:source xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">El...y (Adam Asnyk), Poezye, t. 3,  Gebethner i Wolff, wyd. nowe poprzedzone słowem wstępnym St. Krzemińskiego, Warszawa 1898</dc:source>
+<dc:rights xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">Domena publiczna - Adam Asnyk zm. 1897</dc:rights>
+<dc:date.pd xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">1897</dc:date.pd>
+<dc:format xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">xml</dc:format>
+<dc:type xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">text</dc:type>
+<dc:type xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">text</dc:type>
+<dc:date xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">2009-04-07</dc:date>
+<dc:audience xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">L</dc:audience>
+<dc:language xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl">pol</dc:language>
+<dc:relation.coverImage.url xmlns:dc="http://purl.org/dc/elements/1.1/">http://redakcja.wolnelektury.pl/media/dynamic/cover/image/35.jpg</dc:relation.coverImage.url>
+<dc:relation.coverImage.attribution xmlns:dc="http://purl.org/dc/elements/1.1/">leboski@Flickr, CC BY 2.0</dc:relation.coverImage.attribution>
+<dc:relation.coverImage.source xmlns:dc="http://purl.org/dc/elements/1.1/">http://redakcja.wolnelektury.pl/cover/image/35</dc:relation.coverImage.source>
+</rdf:Description>
+</rdf:RDF><liryka_l>
+
+<autor_utworu>Adam Asnyk</autor_utworu>
+
+<nazwa_utworu>Do młodych</nazwa_utworu>
+
+
+
+
+<strofa>Szukajcie prawdy jasnego płomienia,/
+Szukajcie nowych, nieodkrytych dróg!/
+Za każdym krokiem w tajniki stworzenia/
+Coraz się dusza ludzka rozprzestrzenia/
+I większym staje się Bóg!</strofa>
+
+
+<strofa>Choć otrząśniecie kwiaty barwnych mitów,/
+Choć rozproszycie legendowy mrok,/
+Choć mgłę urojeń zedrzecie z błękitów, ---/
+Ludziom niebiańskich nie zbraknie zachwytów,/
+Lecz dalej sięgnie ich wzrok.</strofa>
+
+
+<strofa><begin id="b1238764684390"/><motyw id="m1238764684390">Czas, Kondycja ludzka, Przemijanie</motyw>Każda epoka ma swe własne cele/
+I zapomina o wczorajszych snach:/
+Nieście więc wiedzy pochodnię na czele/
+I nowy udział bierzcie w wieków dziele,---/
+Przyszłości podnoście gmach!</strofa>
+
+
+<strofa>Ale nie depczcie przeszłości ołtarzy,/
+Choć macie sami doskonalsze wznieść:/
+Na nich się jeszcze święty ogień żarzy,/
+I miłość ludzka stoi tam na straży,/
+I wy winniście im cześć!</strofa>
+
+
+<strofa>Ze światem, który w ciemność już zachodzi/
+Wraz z całą tęczą idealnych snów,/
+Prawdziwa mądrość niechaj was pogodzi:/
+I wasze gwiazdy, o zdobywcy młodzi,/
+W ciemnościach pogasną znów!<end id="e1238764684390"/></strofa>
+
+</liryka_l></utwor>
\ No newline at end of file
index 124940e..a94b8f0 100644 (file)
@@ -9,6 +9,8 @@
 <dc:contributor.editor xml:lang="pl" />
 <dc:contributor.editor xml:lang="pl">Sekuła, Aleksandra</dc:contributor.editor>
 <dc:contributor.technical_editor xml:lang="pl">Sutkowska, Olga</dc:contributor.technical_editor>
+<dc:contributor.editor xml:lang="pl">Fikcyjny, Adam</dc:contributor.editor>
+<dc:contributor.technical_editor xml:lang="pl">Fikcyjny, Adam</dc:contributor.technical_editor>
 <dc:publisher xml:lang="pl">Fundacja Nowoczesna Polska</dc:publisher>
 <dc:subject.period xml:lang="pl">Pozytywizm</dc:subject.period>
 <dc:subject.type xml:lang="pl">Liryka</dc:subject.type>
index 9fc5637..faa76e7 100644 (file)
@@ -3,14 +3,29 @@
 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
+from zipfile import ZipFile
+from lxml import html
+from nose.tools import *
 from librarian import DirDocProvider
 from librarian.parser import WLDocument
-from nose.tools import *
-from utils import get_fixture
+from tests.utils import get_fixture
 
 
 def test_transform():
-    WLDocument.from_file(
+    epub = WLDocument.from_file(
             get_fixture('text', 'asnyk_zbior.xml'),
             provider=DirDocProvider(get_fixture('text', ''))
-        ).as_epub(flags=['without_fonts'])
+        ).as_epub(flags=['without_fonts']).get_file()
+    zipf = ZipFile(epub)
+
+    # Check contributor list.
+    last = zipf.open('OPS/last.html')
+    tree = html.parse(last)
+    editors_attribution = False
+    for par in tree.findall("//p"):
+        if par.text.startswith(u'Opracowanie redakcyjne i przypisy:'):
+            editors_attribution = True
+            assert_equal(par.text.rstrip(),
+                u'Opracowanie redakcyjne i przypisy: '
+                u'Adam Fikcyjny, Aleksandra Sekuła, Olga Sutkowska.')
+    assert_true(editors_attribution)
diff --git a/tests/test_pdf.py b/tests/test_pdf.py
new file mode 100644 (file)
index 0000000..75b73bc
--- /dev/null
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+import re
+from tempfile import NamedTemporaryFile
+from nose.tools import *
+from librarian import DirDocProvider
+from librarian.parser import WLDocument
+from utils import get_fixture
+
+
+def test_transform():
+    temp = NamedTemporaryFile(delete=False)
+    temp.close()
+    WLDocument.from_file(
+            get_fixture('text', 'asnyk_zbior.xml'),
+            provider=DirDocProvider(get_fixture('text', ''))
+        ).as_pdf(save_tex=temp.name)
+    tex = open(temp.name).read().decode('utf-8')
+    print tex
+
+    # Check contributor list.
+    editors = re.search(ur'\\def\\editors\{'
+        ur'Opracowanie redakcyjne i przypisy: ([^}]*?)\.\s*\}', tex)
+    assert_equal(editors.group(1),
+        u"Adam Fikcyjny, Aleksandra Sekuła, Olga Sutkowska")
index 71a77dc..f64f624 100644 (file)
@@ -31,7 +31,7 @@ def test_wlpicture():
 
     #    from nose.tools import set_trace; set_trace()
     assert pi.type[0] == u"Image"
-    assert pi.mime_type == u'image/png' == wlp.mime_type
+    assert pi.mime_type == u'image/jpeg' == wlp.mime_type
     assert wlp.slug == 'angelus-novus'
 
     assert path.exists(wlp.image_path)