Python-Skript Update.
[wortliste.git] / skripte / python / edit_tools / abgleich_endungen.py
blob479cef1376525129028f6018de290adbf6b1b3f1
1 #!/usr/bin/env python
2 # -*- coding: utf8 -*-
3 # :Copyright: © 2014 Günter Milde.
4 # Released without warranty under the terms of the
5 # GNU General Public License (v. 2 or later)
6 # :Id: $Id: $
8 # Abgleich der Trennstellen zwischen Woertern mit gleichem Stamm
9 # ==============================================================
11 # Übertragen von kategorisierten Trennstellen von Wörtern auf
12 # Wörter anderer Endung und unkategorisierten Trennstellen.
14 # ::
16 import re, sys, codecs, copy
17 from wortliste import (WordFile, WordEntry, join_word, udiff,
18 uebertrage, TransferError,
19 sprachabgleich, toggle_case)
20 from analyse import read_teilwoerter, teilwoerter
21 from abgleich_teilwoerter import wortliste_to_teilwoerter
23 # Konfiguration
24 # -------------
26 # Sprachvarianten
27 # ~~~~~~~~~~~~~~~
28 # Sprach-Tag nach [BCP47]_::
30 # sprachvariante = 'de-1901' # "traditionell"
31 sprachvariante = 'de-1996' # Reformschreibung
32 # sprachvariante = 'de-1901-x-GROSS' # ohne ß (Schweiz oder GROSS)
33 # sprachvariante = 'de-1996-x-GROSS' # ohne ß (Schweiz oder GROSS)
34 # sprachvariante = 'de-CH-1901' # ohne ß (Schweiz) ("süssauer")
36 # Großschreibung
37 # ~~~~~~~~~~~~~~
38 # Vergleiche Wörter mit unterschiedlicher Großschreibung
39 # (z.T. reiben <-> Reibung)::
41 grossklein = False
42 # grossklein = True
44 # Vergleichsbasis
45 # ~~~~~~~~~~~~~~~
46 # Verwende die Wortliste oder die mit ``analyse.py`` generierte Teilwortliste
47 # als Quelle der kategorisierten Trennungen::
49 use_teilwoerter = False
50 # use_teilwoerter = True
52 # Grundwort
53 # ~~~~~~~~~
54 # Bei Composita, verwende nur das Grundwort für den Abgleich
55 # (besonders sinnvoll bei Teilwörtern als Vergleichsbasis)::
57 use_grundwort = use_teilwoerter
58 # use_grundwort = False
61 # Funktionen
62 # -----------
64 # Übertrag kategorisierter Trennungen auf Wörter mit anderer Endung::
66 def endungsabgleich(wort, endung, vergleichsendung=u'',
67 use_grundwort=False, grossklein=False):
69 if not wort.endswith(endung):
70 return wort
71 if use_grundwort:
72 teile = wort.split('=')
73 else:
74 teile = [wort]
75 grundwort = teile[-1]
76 stamm = grundwort[:-len(endung)] + vergleichsendung
77 key = join_word(stamm)
78 if grossklein:
79 key = toggle_case(key)
81 if key in words.trennvarianten:
82 # print u'fundum', key
83 for altstamm in words.trennvarianten[key]:
84 if u'·' in altstamm:
85 continue
86 if grossklein:
87 altstamm = toggle_case(altstamm)
88 try:
89 neustamm = uebertrage(altstamm, stamm)
90 # Vergleichsendung abtrennen
91 if vergleichsendung:
92 neustamm = neustamm[:-len(vergleichsendung)]
93 # Mit Originalendung einsetzen
94 teile[-1] = neustamm + endung.replace(u'·', u'-')
95 break
96 except TransferError, e:
97 print unicode(e), u"(%s -> %s)" % (vergleichsendung, endung)
99 return u'='.join(teile)
101 # Endungen
102 # --------
103 # ``(<alt>, <neu>)`` Paare von Endungen
105 # Achtung: die Auswahl zu testender Wörter erfolgt anhand der "neu"-Endung.
106 # Daher darf diese nicht leer sein!
107 # ::
109 endungen = [
110 (u'', u'·chen'),
111 (u'', u'd'),
112 # (u'', u'·de'),
113 # (u'', u'e·rin'),
114 # (u'', u'e'),
115 # (u'', u'er'),
116 (u'', u'·en'),
117 (u'', u'·er'),
118 (u'', u'is·mus'),
119 (u'', u'·is·mus'),
120 (u'', u'·ität'),
121 (u'', u'·lein'),
122 (u'', u'm'),
123 (u'', u'n'),
124 # (u'', u'ner'),
125 (u'', u'·ne'),
126 # (u'', u'·ner'),
127 (u'', u'·nen'),
128 # (u'', u'·nem'),
129 (u'', u'r'),
130 (u'', u's'),
131 (u'', u'·sche'),
132 (u'', u'st'),
133 # (u'', u's·te'),
134 (u'', u't'),
135 (u'', u'·tum'),
136 # (u'', u't·te'),
137 # (u'', u'·schaft'),
138 (u'', u's·te'),
140 (u'-al', u'a·le'),
141 (u'-an', u'a·ne'),
142 (u'-at', u'a·te'),
143 (u'-ben', u'b·ne'),
144 (u'-che', u'ch'),
145 (u'-de', u'd'),
146 # (u'-en', u'e'),
147 (u'-en', u'e·ne'),
148 (u'-er', u'e·rin'),
149 (u'-er', u'e·rei'),
150 (u'-ern', u'e·re'),
151 (u'-ge', u'g'),
152 (u'-gen', u'g'),
153 (u'-on', u'o·nen'),
154 (u'-re', u'r'),
155 (u'-re', u'rt'),
156 (u'-ren', u'rt'),
157 (u'-ren', u'r·ne'),
158 (u'-sche', u'sch'),
159 (u'-sen', u's·ne'),
160 (u'-sten', u's·mus'),
161 (u'-te',u't'),
162 (u'-tern', u't·re'),
163 (u'-ös', u'ö·se'),
165 (u'a', u'·ar'),
166 (u'a', u'·as'),
167 (u'b', u'·be'),
168 (u'b', u'·ber'),
169 (u'bt', u'b·te'),
170 (u'bar', u't'),
171 (u'ce', u'-cen'),
172 (u'ch', u'·che'),
173 # (u'ch', u'-che'), # Test "if u'·' not in wort" auskommentieren!
174 (u'ch', u'·cher'),
175 (u'ck', u'·cke'),
176 (u'ck', u'·cker'),
177 (u'd', u'·de'),
178 # (u'd', u'·dem'),
179 # (u'd', u'·den'),
180 (u'd', u'·der'),
181 # (u'd', u'·des'),
182 # (u'de', u'd'),
183 (u'e', u'·en'),
184 # (u'e-ren', u'sch'),
185 (u'el', u'le'),
186 (u'en', u'e'),
187 # (u'en', u'em'),
188 # (u'en', u'en-de'),
189 # (u'en', u'end'),
190 # (u'en', u'er'),
191 # (u'en', u'es'),
192 # (u'en', u'est'),
193 # (u'en', u't'),
194 # (u'en', u'te'),
195 (u'en', u'us'),
196 # (u'end',u'en' ),
197 (u'er', u'e'),
198 # (u'er', u'ens'),
199 (u'er', u'in'),
200 # (u'er', u'e·rei'),
201 # (u'er', u'ung'),
202 (u'es', u'est'),
203 (u'es', u's·te'),
204 (u'f', u'·fe'),
205 (u'f', u'·fer'),
206 (u'g', u'·ge'),
207 (u'g', u'·gen'),
208 (u'g', u'·ger'),
209 # (u'g', u'·ges'),
210 # (u'g', u'·gung'),
211 # (u'g', u'·ger'),
212 # (u'in', u'en'),
213 (u'ie', u'e'),
214 (u'-in', u'i·ne'),
215 (u'isch', u'i·sche'),
216 (u'k', u'·ke'),
217 # (u'k', u'·ken'),
218 (u'k', u'·ker'),
219 (u'l', u'·le'),
220 (u'l', u'·ler'),
221 # (u'l', u'·len'),
222 # (u'le', u'·ler'),
223 (u'l', u'·lis·mus'),
224 # (u'li-che', u'tem'),
225 # (u'li-che', u'ten'),
226 (u'ln', u'·le'),
227 (u'lt', u'·le'),
228 (u'm', u'·me'),
229 (u'm', u'·mer'),
230 (u'mus', u'men'),
231 (u'mus', u'tik'),
232 (u'mus', u'ten'),
233 # (u'me', u'·men'),
234 # (u'n', u'·at'),
235 # (u'n', u'·er'),
236 (u'n', u'·ne'),
237 # (u'n', u'·nen'),
238 (u'n',u'·ner'),
239 (u'n', u'·nis·mus'),
240 (u'n', u'r'),
241 (u'n', u't'),
242 (u'n', u'st'),
243 # (u'nd',u'n'),
244 # (u'ne',u'n'),
245 # (u'ne',u'·ner'),
246 # (u'o',u'·on'),
247 # (u'o',u'en'),
248 (u'o',u'·os'),
249 (u'on',u'o·nen'),
250 (u'p', u'·pe'),
251 (u'p', u'·pen'),
252 (u'p', u'·per'),
253 # (u'ph', u'·phen'),
254 (u'ph', u'·phis·mus'),
255 (u'r', u'·re'),
256 # (u'r', u'·rei'),
257 (u'r', u'·ren'),
258 (u'r', u'·rin'),
259 (u'r', u'·ris·mus'),
260 # (u'r', u'·rung'),
261 (u're', u'ste'),
262 # (u'ren', u'rst'),
263 # (u'ren', u'rt'),
264 (u'ren', u'r·te'),
265 (u'rn', u'·re'),
266 (u'rn', u'·rung'),
267 (u'rt', u'r·te'),
268 (u'rt', u'·re'),
269 (u's', u''),
270 # (u's', u's-ses'),
271 # (u's', u's·se'),
272 (u's', u'·se'),
273 (u's', u'·ser'),
274 (u's', u'·se·re'),
275 (u's', u'·se·res'),
276 (u'sch', u'·sche'),
277 # (u'sch', u'·schen'),
278 (u'sch', u'·scher'),
279 # (u'st', u'n'),
280 (u'st', u'·ste'),
281 # (u'st', u'·sten'),
282 # (u't', u'e'),
283 (u't', u'n'),
284 (u't', u'st'),
285 (u't', u'·bar'),
286 (u't', u'·ba·re'),
287 (u't', u'·te'),
288 # (u't', u'-te'),
289 (u't', u'·ten'),
290 (u't', u'·ter'),
291 (u't', u'·tes'),
292 (u't', u'·tin'),
293 (u't', u'·tis·mus'),
294 (u'te', u't'),
295 (u'te', u'·le'),
296 (u'te', u'·ten'),
297 (u'ten', u'mus'),
298 (u'ten', u'ren'),
299 (u'ten', u'tung'),
300 (u'ter', u'te·ren'),
301 (u'ti-on', u'tor'),
302 (u'um', u'a'),
303 (u'us', u'en'),
304 (u'v', u'·ve'),
305 (u'v', u'·ver'),
306 (u'v', u'·vis·mus'),
307 # (u've', u'v'),
308 # (u'z', u'·ten'),
309 (u'z', u'·ze'),
310 # (u'z', u'·zen'),
311 (u'z', u'·zer'),
312 (u'ß', u's·se'),
313 (u'ß', u'·ße'),
314 (u'ös', u'ö·se'),
317 if grossklein:
318 endungen.extend([
319 (u'', u'·ar·tig'),
320 (u'', u's·los'),
321 (u'', u'·keit'),
322 (u'', u'·heit'),
323 (u'', u'·schaft'),
324 (u'd', u'·heit'),
325 (u'', u'·weise'),
326 (u'e-ren', u'·ti·on'),
327 (u'-en', u'·bar·keit'),
328 (u'rn', u'·rung'),
331 if __name__ == '__main__':
333 # sys.stdout mit UTF8 encoding.
334 sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)
336 # `Wortliste` einlesen::
338 wordfile = WordFile('../../../wortliste') # ≅ 400 000 Einträge/Zeilen
339 wortliste = list(wordfile)
340 wortliste_neu = []
342 # Vergleichswörter einlesen::
344 if use_teilwoerter:
345 words = read_teilwoerter(path='teilwoerter-%s.txt'%sprachvariante)
346 else: # Gesamtwörter als "Teilwörter":
347 words = wortliste_to_teilwoerter(wortliste, sprachvariante)
349 # Erstellen der neuen wortliste::
351 for entry in wortliste:
353 # Wort mit Trennungen in Sprachvariante
354 wort = entry.get(sprachvariante)
355 if (wort is None # Wort existiert nicht in der Sprachvariante
356 or u'·' not in wort): # Alle Trennstellen kategorisiert
357 wortliste_neu.append(entry)
358 continue
360 # Endungsabgleich::
362 for alt, neu in endungen:
363 wort2 = endungsabgleich(wort, endung=neu, vergleichsendung=alt,
364 use_grundwort=use_grundwort,
365 grossklein=grossklein
367 if wort != wort2:
368 break
370 # Eintrag ändern::
372 if (wort != wort2): #and (u'·' not in wort2):
373 entry = copy.copy(entry)
374 entry.set(wort2, sprachvariante)
375 print u'%s -> %s' % (wort, wort2)
376 if len(entry) > 2:
377 sprachabgleich(entry)
379 wortliste_neu.append(entry)
382 # Patch erstellen::
384 patch = udiff(wortliste, wortliste_neu, 'wortliste', 'wortliste-neu')
385 if patch:
386 # print patch
387 patchfile = open('wortliste.patch', 'w')
388 patchfile.write(patch + '\n')
389 else:
390 print u'empty patch'