1 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
9 from .parser import parser
10 from . import dcparser, DCNS, DirDocProvider
11 from .functions import lang_code_3to2
15 def __init__(self, filename=None, url=None, provider=None):
16 source = filename or urllib.request.urlopen(url)
17 tree = etree.parse(source, parser=parser)
19 tree.getroot().document = self
20 self.base_meta = dcparser.BookInfo({}, {
21 DCNS('language'): ["pol"],
22 }, validate_required=False)
24 self.provider = provider if provider is not None else DirDocProvider('.')
26 self.tree.getroot().validate()
30 # Allow metadata of the master element as document meta.
31 #master = self.tree.getroot()[-1]
32 return self.tree.getroot().meta
37 for part_uri in self.meta.parts or []:
38 with self.provider.by_slug(part_uri.slug) as f:
39 yield type(self)(filename=f, provider=self.provider)
41 def build(self, builder, base_url=None, **kwargs):
42 return builder(base_url=base_url).build(self, **kwargs)
44 def assign_ids(self, existing=None):
45 # Find all existing IDs.
46 existing = existing or set()
47 que = [self.tree.getroot()]
51 item.normalize_insides()
52 except AttributeError:
54 existing.add(item.attrib.get('id'))
58 que = [self.tree.getroot()]
62 if item.attrib.get('id'):
64 if not getattr(item, 'SHOULD_HAVE_ID', False):
66 while f'e{i}' in existing:
68 item.attrib['id'] = f'e{i}'
71 def _compat_assign_ordered_ids(self):
73 Compatibility: ids in document order, to be roughly compatible with legacy
74 footnote ids. Just for testing consistency, change to some sane identifiers
77 EXPR = re.compile(r'/\s', re.MULTILINE | re.UNICODE)
78 def _compat_assign_ordered_ids_in_elem(elem, i):
79 elem.attrib['_compat_ordered_id'] = str(i)
81 if getattr(elem, 'HTML_CLASS', None) == 'stanza':
83 i += len(EXPR.split(elem.text)) - 1
85 i = _compat_assign_ordered_ids_in_elem(sub, i)
87 i += len(EXPR.split(sub.tail)) - 1
89 if elem.tag in ('uwaga', 'extra'):
92 i = _compat_assign_ordered_ids_in_elem(sub, i)
95 _compat_assign_ordered_ids_in_elem(self.tree.getroot(), 4)
97 def _compat_assign_section_ids(self):
99 Ids in master-section order. These need to be compatible with the
100 #secN anchors used by WL search results page to link to fragments.
102 def _compat_assigns_section_ids_in_elem(elem, prefix='sec'):
103 for i, child in enumerate(elem):
104 idfier = '{}{}'.format(prefix, i + 1)
106 child.attrib['_compat_section_id'] = idfier
109 _compat_assigns_section_ids_in_elem(child, idfier + '-')
110 _compat_assigns_section_ids_in_elem(self.tree.getroot().master)
114 persons = set(self.meta.editors
115 + self.meta.technical_editors)
116 for child in self.children:
117 persons.update(child.editors())
122 def references(self):
123 return self.tree.findall('.//ref')