html.extract_annotations: Allow multiple footnote qualifiers. Use only ones accepted...
authorRadek Czajka <radekczajka@nowoczesnapolska.org.pl>
Thu, 23 Oct 2014 11:51:06 +0000 (13:51 +0200)
committerRadek Czajka <radekczajka@nowoczesnapolska.org.pl>
Thu, 23 Oct 2014 11:51:06 +0000 (13:51 +0200)
librarian/fn_qualifiers.py [new file with mode: 0644]
librarian/html.py
scripts/fn_qualifiers_list_from_redmine.py [new file with mode: 0644]
tests/test_html_annotations.py

diff --git a/librarian/fn_qualifiers.py b/librarian/fn_qualifiers.py
new file mode 100644 (file)
index 0000000..51168e4
--- /dev/null
@@ -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',
+    }
index 85b9003..6115b31 100644 (file)
@@ -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 (file)
index 0000000..020b119
--- /dev/null
@@ -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')
index f269042..4956b7d 100644 (file)
@@ -23,7 +23,7 @@ def test_annotations():
 
         ('<pe/>', (
             'pe',
-            None
+            []
             '',
             '<p></p>'
             ),
@@ -32,7 +32,7 @@ def test_annotations():
         (
          '<pr>Definiendum --- definiens.</pr>', (
             'pr',
-            None
+            []
             'Definiendum \u2014 definiens.', 
             '<p>Definiendum \u2014 definiens.</p>'
             ),
@@ -40,7 +40,7 @@ def test_annotations():
 
         ('<pt><slowo_obce>Definiendum</slowo_obce> --- definiens.</pt>', (
             'pt',
-            None
+            []
             'Definiendum \u2014 definiens.', 
             '<p><em class="foreign-word">Definiendum</em> \u2014 definiens.</p>'
             ),
@@ -48,7 +48,7 @@ def test_annotations():
 
         ('<pr>Definiendum (łac.) --- definiens.</pr>', (
             'pr',
-            'łac.'
+            ['łac.']
             'Definiendum (łac.) \u2014 definiens.', 
             '<p>Definiendum (łac.) \u2014 definiens.</p>'
             ),
@@ -56,7 +56,7 @@ def test_annotations():
 
         ('<pe><slowo_obce>Definiendum</slowo_obce> (łac.) --- definiens.</pe>', (
             'pe',
-            'łac.'
+            ['łac.']
             'Definiendum (łac.) \u2014 definiens.', 
             '<p><em class="foreign-word">Definiendum</em> (łac.) \u2014 definiens.</p>'
             ),
@@ -64,7 +64,7 @@ def test_annotations():
 
         ('<pt> <slowo_obce>Definiendum</slowo_obce> (daw.) --- definiens.</pt>', (
             'pt',
-            'daw.'
+            ['daw.']
             'Definiendum (daw.) \u2014 definiens.', 
             '<p> <em class="foreign-word">Definiendum</em> (daw.) \u2014 definiens.</p>'
             ),
@@ -72,7 +72,7 @@ def test_annotations():
 
         ('<pr>Definiendum (łac.) --- <slowo_obce>definiens</slowo_obce>.</pr>', (
             'pr',
-            'łac.'
+            ['łac.']
             'Definiendum (łac.) \u2014 definiens.', 
             '<p>Definiendum (łac.) \u2014 <em class="foreign-word">definiens</em>.</p>'
             ),
@@ -80,7 +80,7 @@ def test_annotations():
 
         ('<pe><slowo_obce>Definiendum</slowo_obce> (łac.) --- <slowo_obce>definiens</slowo_obce>.</pe>', (
             'pe',
-            'łac.',
+            ['łac.'],
             'Definiendum (łac.) \u2014 definiens.',
             '<p><em class="foreign-word">Definiendum</em> (łac.) \u2014 <em class="foreign-word">definiens</em>.</p>'
             ),
@@ -88,12 +88,20 @@ def test_annotations():
 
         ('<pe>Definiendum (łac.) --- definiens (some) --- more text.</pe>', (
             'pe',
-            'łac.',
+            ['łac.'],
             'Definiendum (łac.) \u2014 definiens (some) \u2014 more text.',
             '<p>Definiendum (łac.) \u2014 definiens (some) \u2014 more text.</p>',
             ),
             'Footnote with a second parentheses and mdash.'),
 
+        ('<pe><slowo_obce>gemajna</slowo_obce> (daw., z niem. <slowo_obce>gemein</slowo_obce>: zwykły) --- częściej: gemajn, szeregowiec w wojsku polskim cudzoziemskiego autoramentu.</pe>', (
+            'pe',
+            ['daw.', 'niem.'],
+            'gemajna (daw., z niem. gemein: zwykły) \u2014 częściej: gemajn, szeregowiec w wojsku polskim cudzoziemskiego autoramentu.',
+            '<p><em class="foreign-word">gemajna</em> (daw., z niem. <em class="foreign-word">gemein</em>: zwykły) \u2014 częściej: gemajn, szeregowiec w wojsku polskim cudzoziemskiego autoramentu.</p>'
+            ),
+            'Footnote with multiple and qualifiers and emphasis.'),
+
     )
 
     xml_src = '''<utwor><akap> %s </akap></utwor>''' % "".join(