X-Git-Url: https://git.mdrn.pl/librarian.git/blobdiff_plain/8550d172b829f29b2fcd4723789fb2a5d9fff6eb..23d025c8875cca1404f274aca7170c9db5e980e7:/src/librarian/parser.py?ds=sidebyside diff --git a/src/librarian/parser.py b/src/librarian/parser.py index 2bb9509..6e0a9c9 100644 --- a/src/librarian/parser.py +++ b/src/librarian/parser.py @@ -1,25 +1,41 @@ -# -*- 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. +# Copyright © Fundacja Wolne Lektury. See NOTICE for more information. # -from __future__ import unicode_literals - +from collections import Counter +import io +import os +import re +from xml.parsers.expat import ExpatError +from lxml import etree +from lxml.etree import XMLSyntaxError, XSLTApplyError from librarian import ValidationError, NoDublinCore, ParseError, NoProvider from librarian import RDFNS from librarian.cover import make_cover from librarian import dcparser +from .elements import WL_ELEMENTS -from xml.parsers.expat import ExpatError -from lxml import etree -from lxml.etree import XMLSyntaxError, XSLTApplyError -import os -import re -import six +class WLElementLookup(etree.CustomElementClassLookup): + def lookup(self, node_type, document, namespace, name): + if node_type != 'element': + return + if namespace: + return + try: + return WL_ELEMENTS[name] + except KeyError: + return + + +parser = etree.XMLParser() +parser.set_element_class_lookup( + WLElementLookup() +) -class WLDocument(object): + +class WLDocument: + """Legacy class, to be replaced with documents.WLDocument.""" LINE_SWAP_EXPR = re.compile(r'/\s', re.MULTILINE | re.UNICODE) provider = None @@ -53,13 +69,13 @@ class WLDocument(object): @classmethod def from_bytes(cls, xml, *args, **kwargs): - return cls.from_file(six.BytesIO(xml), *args, **kwargs) + return cls.from_file(io.BytesIO(xml), *args, **kwargs) @classmethod def from_file(cls, xmlfile, *args, **kwargs): # first, prepare for parsing - if isinstance(xmlfile, six.text_type): + if isinstance(xmlfile, str): file = open(xmlfile, 'rb') try: data = file.read() @@ -68,14 +84,14 @@ class WLDocument(object): else: data = xmlfile.read() - if not isinstance(data, six.text_type): + if not isinstance(data, str): data = data.decode('utf-8') - data = data.replace(u'\ufeff', '') + data = data.replace('\ufeff', '') try: parser = etree.XMLParser(remove_blank_text=False) - tree = etree.parse(six.BytesIO(data.encode('utf-8')), parser) + tree = etree.parse(io.BytesIO(data.encode('utf-8')), parser) return cls(tree, *args, **kwargs) except (ExpatError, XMLSyntaxError, XSLTApplyError) as e: @@ -102,15 +118,20 @@ class WLDocument(object): elem.insert(0, ins) elem.text = chunks.pop(0) - def parts(self): + def parts(self, pass_part_errors=False): if self.provider is None: raise NoProvider('No document provider supplied.') if self.book_info is None: raise NoDublinCore('No Dublin Core in document.') for part_uri in self.book_info.parts: - yield self.from_file( - self.provider.by_uri(part_uri), provider=self.provider - ) + try: + with self.provider.by_slug(part_uri.slug) as f: + yield self.from_file(f, provider=self.provider) + except Exception as e: + if pass_part_errors: + yield e + else: + raise def chunk(self, path): # convert the path to XPath @@ -177,6 +198,13 @@ class WLDocument(object): node.tag = 'span' node.tail = tail + def fix_pa_akap(self): + for pa in ('pa','pe','pr','pt'): + for akap in self.edoc.findall(f'//{pa}/akap'): + akap.getparent().set('blocks', 'true') + if not akap.getparent().index(akap): + akap.set('inline', 'true') + def editors(self): """Returns a set of all editors for book and its children. @@ -194,26 +222,10 @@ class WLDocument(object): # Converters - def as_html(self, *args, **kwargs): - from librarian import html - return html.transform(self, *args, **kwargs) - - def as_text(self, *args, **kwargs): - from librarian import text - return text.transform(self, *args, **kwargs) - - def as_epub(self, *args, **kwargs): - from librarian import epub - return epub.transform(self, *args, **kwargs) - def as_pdf(self, *args, **kwargs): from librarian import pdf return pdf.transform(self, *args, **kwargs) - def as_mobi(self, *args, **kwargs): - from librarian import mobi - return mobi.transform(self, *args, **kwargs) - def as_fb2(self, *args, **kwargs): from librarian import fb2 return fb2.transform(self, *args, **kwargs) @@ -237,7 +249,7 @@ class WLDocument(object): if make_author_dir: save_path = os.path.join( save_path, - six.text_type(self.book_info.author).encode('utf-8') + str(self.book_info.author).encode('utf-8') ) save_path = os.path.join(save_path, self.book_info.url.slug) if ext: