From a3be479506edf42dc58feb22b26e4f5da1e49edd Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Thu, 23 Oct 2014 13:51:06 +0200 Subject: [PATCH] html.extract_annotations: Allow multiple footnote qualifiers. Use only ones accepted by editors. --- librarian/fn_qualifiers.py | 198 +++++++++++++++++++++ librarian/html.py | 26 ++- scripts/fn_qualifiers_list_from_redmine.py | 35 ++++ tests/test_html_annotations.py | 26 ++- 4 files changed, 272 insertions(+), 13 deletions(-) create mode 100644 librarian/fn_qualifiers.py create mode 100644 scripts/fn_qualifiers_list_from_redmine.py diff --git a/librarian/fn_qualifiers.py b/librarian/fn_qualifiers.py new file mode 100644 index 0000000..51168e4 --- /dev/null +++ b/librarian/fn_qualifiers.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 +""" +List of standard footnote qualifiers. +This file is generated by scripts/fn_qualifiers_list_from_wiki.py, +do not edit it. +""" +from __future__ import unicode_literals + + +FN_QUALIFIERS = { + 'a.': 'albo', + 'alb.': 'albański', + 'amer.': 'amerykański, amerykańskie', + 'anat.': 'anatomiczne', + 'ang.': 'angielski, angielskie', + 'antr.': 'antropologia, antropologiczny', + 'ar.': 'arabski', + 'archeol.': 'archeologia, archeologiczny', + 'archit.': 'architektura', + 'astr.': 'astronomia', + 'austr.': 'austriacki', + 'austral.': 'australijski', + 'B.': 'biernik', + 'białorus.': 'białoruski', + 'biol.': 'biologia, biologiczny', + 'blm': 'bez liczby mnogiej', + 'blp': 'bez liczby pojedynczej', + 'bot.': 'botanika', + 'bułg.': 'bułgarski', + 'C.': 'celownik', + 'celt.': 'celtycki', + 'chem.': 'chemiczny', + 'chiń.': 'chiński', + 'chrześc.': 'chrześcijański, chrześcijaństwo', + 'cz.': 'czas (gramatyczny)', + 'cz.przesz.': 'czas przeszły', + 'cz.przysz.': 'czas przyszły', + 'cz.ter.': 'czas teraźniejszy', + 'czas.': 'czasownik', + 'czes.': 'czeski', + 'D.': 'dopełniacz', + 'daw.': 'dawne', + 'dk': 'dokonane', + 'druk.': 'drukarstwo, drukowany', + 'dziec.': 'dziecięcy', + 'egip.': 'egipski', + 'ekon.': 'ekonomiczny', + 'elektr.': 'elektryczny', + 'etn.': 'etnografia, etniczny', + 'euf.': 'eufemizm', + 'film.': 'filmowy', + 'filoz.': 'filozoficzny', + 'fiń.': 'fiński', + 'fiz.': 'fizyka', + 'fizjol.': 'fizjologia', + 'fot.': 'fotografia, fotograficzny', + 'fr.': 'francuski', + 'fraz.': 'frazeologia, frazeologiczny', + 'fragm.': 'fragment', + 'genet.': 'genetyka, genetyczny', + 'geogr.': 'geografia, geograficzny', + 'geol.': 'geologia', + 'geom.': 'geometria', + 'gr.': 'grecki', + 'gw.': 'gwara, gwarowe', + 'hand.': 'handel, handlowy', + 'hebr.': 'hebrajski', + 'hind.': 'hinduski', + 'hist.': 'historia, historyczny', + 'hiszp.': 'hiszpański', + 'hol.': 'holenderski', + 'im.': 'imienia', + 'imiesł.': 'imiesłów, imiesłowowy', + 'in.': 'inne, inny', + 'inf.': 'informacja', + 'inform.': 'informatyka', + 'irl.': 'irlandzki', + 'iron.': 'ironicznie', + 'isl.': 'islandzki', + 'itd.': 'i tak dalej', + 'itp.': 'i tym podobne', + 'jap.': 'japoński', + 'jęz.': 'język, językowy, językoznawstwo', + 'kg': 'kilogram', + 'km': 'kilometr', + 'lit.': 'literacki, literatura', + 'lm': 'liczba mnoga', + 'łac.': 'łacina, łacińskie', + 'M.': 'mianownik', + 'm.': 'męski', + 'mat.': 'matematyka', + 'med.': 'medyczne', + 'meteor.': 'meteorologia, meteorologiczny', + 'min.': 'minuta', + 'm.in.': 'między innymi', + 'miner.': 'mineralogia', + 'mit.': 'mitologia', + 'mit. germ.': 'mitologia germańska', + 'mit. gr.': 'mitologia grecka', + 'mit. rzym.': 'mitologia rzymska', + 'mors.': 'morskie', + 'm.-os.': 'męskoosobowy', + 'Ms.': 'miejscownik', + 'muz.': 'muzyczny', + 'N.': 'narzędnik', + 'n.': 'nijaki', + 'ndk': 'niedokonany', + 'ndm': 'nieodmienny', + 'n.e.': 'nasza era', + 'nieos.': 'nieosobowy', + 'niem.': 'niemiecki', + 'norw.': 'norweski', + 'np.': 'na przykład', + 'obelż.': 'obelżywie', + 'odm.': 'odmienny', + 'ok.': 'około', + 'os.': 'osoba, osobowy', + 'płd.': 'południowy', + 'płn.': 'północny', + 'p.n.e.': 'przed naszą erą', + 'pocz.': 'początek', + 'poet.': 'poetyckie', + 'pogard.': 'pogardliwe', + 'pol.': 'polski', + 'polit.': 'polityczny', + 'poł.': 'połowa', + 'popr.': 'poprawnie', + 'por.': 'porównaj', + 'port.': 'portugalski', + 'posp.': 'pospolity', + 'pot.': 'potocznie', + 'praw.': 'prawo, prawnicze', + 'przen.': 'przenośnie', + 'przestarz.': 'przestarzałe', + 'przesz.': 'przeszły', + 'przym.': 'przymiotnik', + 'przysł.': 'przysłowiowy', + 'przysłów.': 'przysłówek', + 'przysz.': 'przyszły', + 'psychol.': 'psychologia, psychologiczny', + 'r.': 'rok', + 'r.m.': 'rodzaj męski', + 'r.n.': 'rodzaj nijaki', + 'r.ż.': 'rodzaj żeński', + 'reg.': 'regionalne', + 'rel.': 'religijny, religioznawstwo', + 'rodz.': 'rodzaj', + 'roln.': 'rolnictwo, rolniczy', + 'ros.': 'rosyjski', + 'rub.': 'rubasznie', + 'rum.': 'rumuński', + 'rzad.': 'rzadki', + 'rzecz.': 'rzeczownik', + 'rzym.': 'rzymski', + 'skand.': 'skandynawski', + 'skrót.': 'skrótowiec', + 'słowac.': 'słowacki', + 'socjol.': 'socjologiczny', + 'sport.': 'sportowy', + 'st.': 'stopień', + 'starop.': 'staropolskie', + 'staroż.': 'starożytny', + 'szt.': 'sztuka', + 'szwedz.': 'szwedzki', + 'śr.': 'środek, środkowy', + 'środ.': 'środowiskowy', + 'teatr.': 'teatralny', + 'techn.': 'techniczny', + 'temp.': 'temperatura', + 'ter.': 'teraźniejszy', + 'tur.': 'turecki', + 'tur.-tat.': 'turecko-tatarski', + 'tys.': 'tysiąc', + 'tzn.': 'to znaczy', + 'uczn.': 'uczniowski', + 'ukr.': 'ukraiński', + 'urb.': 'urbanistyka', + 'W.': 'wołacz', + 'w.': 'wiek', + 'węg.': 'węgierski', + 'wg': 'według', + 'wł.': 'włoski', + 'wojsk.': 'wojskowy', + 'wsch.': 'wschodni', + 'współ.': 'współcześnie', + 'wulg.': 'wulgarne', + 'wym.': 'wymawiaj', + 'zach.': 'zachodnie', + 'zdr.': 'zdrobnienie', + 'zgr.': 'zgrubienie', + 'zn.': 'znaczy, znaczenie', + 'zob.': 'zobacz', + 'zool.': 'zoologia', + 'zwł.': 'zwłaszcza', + 'ż.': 'żeński', + 'żart.': 'żartobliwie', + 'żegl.': 'żeglarskie', + } diff --git a/librarian/html.py b/librarian/html.py index 85b9003..6115b31 100644 --- a/librarian/html.py +++ b/librarian/html.py @@ -294,7 +294,14 @@ def add_table_of_themes(root): def extract_annotations(html_path): - """For each annotation, yields a tuple: anchor, text, html.""" + """Extracts annotations from HTML for annotations dictionary. + + For each annotation, yields a tuple of: + anchor, footnote type, valid qualifiers, text, html. + + """ + from .fn_qualifiers import FN_QUALIFIERS + parser = etree.HTMLParser(encoding='utf-8') tree = etree.parse(html_path, parser) footnotes = tree.find('//*[@id="footnotes"]') @@ -309,10 +316,21 @@ def extract_annotations(html_path): footnote[-1].tail = None text_str = etree.tostring(footnote, method='text', encoding=unicode).strip() html_str = etree.tostring(footnote, method='html', encoding=unicode).strip() - qualifier = None + match = re_qualifier.match(text_str) if match: - qualifier = match.group(1) + qualifier_str = match.group(1) + qualifiers = [] + for candidate in re.split('[;,]', qualifier_str): + candidate = candidate.strip() + if candidate in FN_QUALIFIERS: + qualifiers.append(candidate) + elif candidate.startswith('z '): + subcandidate = candidate.split()[1] + if subcandidate in FN_QUALIFIERS: + qualifiers.append(subcandidate) + else: + qualifiers = [] - yield anchor, fn_type, qualifier, text_str, html_str + yield anchor, fn_type, qualifiers, text_str, html_str diff --git a/scripts/fn_qualifiers_list_from_redmine.py b/scripts/fn_qualifiers_list_from_redmine.py new file mode 100644 index 0000000..020b119 --- /dev/null +++ b/scripts/fn_qualifiers_list_from_redmine.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- coding: utf-8 + +""" +This scripts reads the table of footnote qualifiers from Redmine +and produces contents of fn_qualifiers.py – a list of valid qualifiers. +""" + +from lxml import etree +from urllib2 import urlopen + +url = 'http://redmine.nowoczesnapolska.org.pl/projects/wl-publikacje/wiki/Lista_skr%C3%B3t%C3%B3w' + +parser = etree.HTMLParser() +tree = etree.parse(urlopen(url), parser) + +print """\ +# -*- coding: utf-8 +\""" +List of standard footnote qualifiers. +This file is generated by scripts/fn_qualifiers_list_from_wiki.py, +do not edit it. +\""" +from __future__ import unicode_literals + + +FN_QUALIFIERS = {""".encode('utf-8') + +for td in tree.findall('//td'): + print (" '%s': '%s'," % ( + td[0].text.replace('\\', '\\\\').replace("'", "\\'"), + td[0].tail.strip(' -').replace('\\', '\\\\').replace("'", "\\'") + )).encode('utf-8') + +print """ }""".encode('utf-8') diff --git a/tests/test_html_annotations.py b/tests/test_html_annotations.py index f269042..4956b7d 100644 --- a/tests/test_html_annotations.py +++ b/tests/test_html_annotations.py @@ -23,7 +23,7 @@ def test_annotations(): ('', ( 'pe', - None, + [], '', '

' ), @@ -32,7 +32,7 @@ def test_annotations(): ( 'Definiendum --- definiens.', ( 'pr', - None, + [], 'Definiendum \u2014 definiens.', '

Definiendum \u2014 definiens.

' ), @@ -40,7 +40,7 @@ def test_annotations(): ('Definiendum --- definiens.', ( 'pt', - None, + [], 'Definiendum \u2014 definiens.', '

Definiendum \u2014 definiens.

' ), @@ -48,7 +48,7 @@ def test_annotations(): ('Definiendum (łac.) --- definiens.', ( 'pr', - 'łac.', + ['łac.'], 'Definiendum (łac.) \u2014 definiens.', '

Definiendum (łac.) \u2014 definiens.

' ), @@ -56,7 +56,7 @@ def test_annotations(): ('Definiendum (łac.) --- definiens.', ( 'pe', - 'łac.', + ['łac.'], 'Definiendum (łac.) \u2014 definiens.', '

Definiendum (łac.) \u2014 definiens.

' ), @@ -64,7 +64,7 @@ def test_annotations(): (' Definiendum (daw.) --- definiens.', ( 'pt', - 'daw.', + ['daw.'], 'Definiendum (daw.) \u2014 definiens.', '

Definiendum (daw.) \u2014 definiens.

' ), @@ -72,7 +72,7 @@ def test_annotations(): ('Definiendum (łac.) --- definiens.', ( 'pr', - 'łac.', + ['łac.'], 'Definiendum (łac.) \u2014 definiens.', '

Definiendum (łac.) \u2014 definiens.

' ), @@ -80,7 +80,7 @@ def test_annotations(): ('Definiendum (łac.) --- definiens.', ( 'pe', - 'łac.', + ['łac.'], 'Definiendum (łac.) \u2014 definiens.', '

Definiendum (łac.) \u2014 definiens.

' ), @@ -88,12 +88,20 @@ def test_annotations(): ('Definiendum (łac.) --- definiens (some) --- more text.', ( 'pe', - 'łac.', + ['łac.'], 'Definiendum (łac.) \u2014 definiens (some) \u2014 more text.', '

Definiendum (łac.) \u2014 definiens (some) \u2014 more text.

', ), 'Footnote with a second parentheses and mdash.'), + ('gemajna (daw., z niem. gemein: zwykły) --- częściej: gemajn, szeregowiec w wojsku polskim cudzoziemskiego autoramentu.', ( + 'pe', + ['daw.', 'niem.'], + 'gemajna (daw., z niem. gemein: zwykły) \u2014 częściej: gemajn, szeregowiec w wojsku polskim cudzoziemskiego autoramentu.', + '

gemajna (daw., z niem. gemein: zwykły) \u2014 częściej: gemajn, szeregowiec w wojsku polskim cudzoziemskiego autoramentu.

' + ), + 'Footnote with multiple and qualifiers and emphasis.'), + ) xml_src = ''' %s ''' % "".join( -- 2.20.1