<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
<meta charset="utf-8"/>
<meta name="generator" content="Docutils 0.15b.dev: http://docutils.sourceforge.net/" />
<title>wortliste.py</title>
<style type="text/css">
/* Minimal style sheet for the HTML output of Docutils. */
/* */
/* :Author: Günter Milde, based on html4css1.css by David Goodger */
/* :Id: $Id$ */
/* :Copyright: © 2015 Günter Milde. */
/* :License: Released under the terms of the `2-Clause BSD license`_, */
/* in short: */
/* */
/* Copying and distribution of this file, with or without modification, */
/* are permitted in any medium without royalty provided the copyright */
/* notice and this notice are preserved. */
/* */
/* This file is offered as-is, without any warranty. */
/* */
/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
/* This CSS2.1_ stylesheet defines rules for Docutils elements without */
/* HTML equivalent. It is required to make the document semantic visible. */
/* */
/* .. _CSS2.1: http://www.w3.org/TR/CSS2 */
/* .. _validates: http://jigsaw.w3.org/css-validator/validator$link */
/* alignment of text and inline objects inside block objects*/
.align-left { text-align: left; }
.align-right { text-align: right; }
.align-center { clear: both; text-align: center; }
.align-top { vertical-align: top; }
.align-middle { vertical-align: middle; }
.align-bottom { vertical-align: bottom; }
/* titles */
h1.title, p.subtitle {
text-align: center;
}
p.admonition-title,
p.topic-title,
p.sidebar-title,
p.rubric,
p.system-message-title {
font-weight: bold;
}
h1 + p.subtitle,
h1 + p.section-subtitle {
font-size: 1.6em;
}
h2 + p.section-subtitle { font-size: 1.28em; }
p.subtitle,
p.section-subtitle,
p.sidebar-subtitle {
font-weight: bold;
margin-top: -0.5em;
}
p.sidebar-title,
p.rubric {
font-size: larger;
}
p.rubric { color: maroon; }
a.toc-backref {
color: black;
text-decoration: none; }
/* Warnings, Errors */
div.caution p.admonition-title,
div.attention p.admonition-title,
div.danger p.admonition-title,
div.error p.admonition-title,
div.warning p.admonition-title,
div.system-messages h1,
div.error,
span.problematic,
p.system-message-title {
color: red;
}
/* inline literals */
span.docutils.literal {
font-family: monospace;
white-space: pre-wrap;
}
/* do not wraph at hyphens and similar: */
.literal > span.pre { white-space: nowrap; }
/* Lists */
/* compact and simple lists: no margin between items */
.simple li, .compact li,
.simple ul, .compact ul,
.simple ol, .compact ol,
.simple > li p, .compact > li p,
dl.simple > dd, dl.compact > dd {
margin-top: 0;
margin-bottom: 0;
}
/* Table of Contents */
div.topic.contents { margin: 0; }
ul.auto-toc {
list-style-type: none;
padding-left: 1.5em; }
/* Enumerated Lists */
ol.arabic { list-style: decimal }
ol.loweralpha { list-style: lower-alpha }
ol.upperalpha { list-style: upper-alpha }
ol.lowerroman { list-style: lower-roman }
ol.upperroman { list-style: upper-roman }
dt span.classifier { font-style: italic }
dt span.classifier:before {
font-style: normal;
margin: 0.5em;
content: ":";
}
/* Field Lists and drivatives */
/* bold field name, content starts on the same line */
dl.field-list > dt,
dl.option-list > dt,
dl.docinfo > dt,
dl.footnote > dt,
dl.citation > dt {
font-weight: bold;
clear: left;
float: left;
margin: 0;
padding: 0;
padding-right: 0.5em;
}
/* Offset for field content (corresponds to the --field-name-limit option) */
dl.field-list > dd,
dl.option-list > dd,
dl.docinfo > dd {
margin-left: 9em; /* ca. 14 chars in the test examples */
}
/* start field-body on a new line after long field names */
dl.field-list > dd > *:first-child,
dl.option-list > dd > *:first-child
{
display: inline-block;
width: 100%;
margin: 0;
}
/* field names followed by a colon */
dl.field-list > dt:after,
dl.docinfo > dt:after {
content: ":";
}
/* Bibliographic Fields (docinfo) */
pre.address { font: inherit; }
dd.authors > p { margin: 0; }
/* Option Lists */
dl.option-list { margin-left: 40px; }
dl.option-list > dt { font-weight: normal; }
span.option { white-space: nowrap; }
/* Footnotes and Citations */
dl.footnote.superscript > dd {margin-left: 1em; }
dl.footnote.brackets > dd {margin-left: 2em; }
dl > dt.label { font-weight: normal; }
a.footnote-reference.brackets:before,
dt.label > span.brackets:before { content: "["; }
a.footnote-reference.brackets:after,
dt.label > span.brackets:after { content: "]"; }
a.footnote-reference.superscript,
dl.footnote.superscript > dt.label {
vertical-align: super;
font-size: smaller;
}
dt.label > span.fn-backref { margin-left: 0.2em; }
dt.label > span.fn-backref > a { font-style: italic; }
/* Line Blocks */
div.line-block { display: block; }
div.line-block div.line-block {
margin-top: 0;
margin-bottom: 0;
margin-left: 40px;
}
/* Figures, Images, and Tables */
.figure.align-left,
img.align-left,
object.align-left,
table.align-left {
margin-right: auto;
}
.figure.align-center,
img.align-center,
object.align-center {
margin-left: auto;
margin-right: auto;
display: block;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.figure.align-right,
img.align-right,
object.align-right,
table.align-right {
margin-left: auto;
}
/* reset inner alignment in figures and tables */
/* div.align-left, div.align-center, div.align-right, */
table.align-left, table.align-center, table.align-right
{ text-align: inherit }
/* Admonitions and System Messages */
div.admonition,
div.system-message,
div.sidebar{
margin: 40px;
border: medium outset;
padding-right: 1em;
padding-left: 1em;
}
/* Sidebar */
div.sidebar {
width: 30%;
max-width: 26em;
float: right;
clear: right;
}
/* Text Blocks */
blockquote,
div.topic,
pre.literal-block,
pre.doctest-block,
pre.math,
pre.code {
margin-left: 1.5em;
margin-right: 1.5em
}
pre.code .ln { color: gray; } /* line numbers */
/* Tables */
table { border-collapse: collapse; }
td, th {
border-style: solid;
border-color: silver;
padding: 0 1ex;
border-width: thin;
}
td > p:first-child, th > p:first-child { margin-top: 0; }
td > p, th > p { margin-bottom: 0; }
table > caption {
text-align: left;
margin-bottom: 0.25em
}
table.borderless td, table.borderless th {
border: 0;
padding: 0;
padding-right: 0.5em /* separate table cells */
}
</style>
<style type="text/css">
/* CSS31_ style sheet for the output of Docutils HTML writers. */
/* Rules for easy reading and pre-defined style variants. */
/* */
/* :Author: Günter Milde, based on html4css1.css by David Goodger */
/* :Id: $Id$ */
/* :Copyright: © 2015 Günter Milde. */
/* :License: Released under the terms of the `2-Clause BSD license`_, */
/* in short: */
/* */
/* Copying and distribution of this file, with or without modification, */
/* are permitted in any medium without royalty provided the copyright */
/* notice and this notice are preserved. */
/* */
/* This file is offered as-is, without any warranty. */
/* */
/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
/* .. _CSS3: http://www.w3.org/TR/CSS3 */
/* Document Structure */
/* ****************** */
/* "page layout" */
body {
padding: 0 5%;
margin: 8px 0;
}
div.document {
line-height:1.3;
counter-reset: table;
/* counter-reset: figure; */
/* avoid long lines --> better reading */
/* OTOH: lines should not be too short because of missing hyphenation, */
max-width: 50em;
margin: auto;
}
/* Sections */
/* Transitions */
hr.docutils {
width: 80%;
margin-top: 1em;
margin-bottom: 1em;
clear: both;
}
/* Paragraphs */
/* ========== */
/* vertical space (parskip) */
p, ol, ul, dl,
div.line-block,
table{
margin-top: 0.5em;
margin-bottom: 0.5em;
}
h1, h2, h3, h4, h5, h6,
dl > dd {
margin-bottom: 0.5em;
}
/* Lists */
/* ========== */
/* Definition Lists */
dl > dd > p:first-child { margin-top: 0; }
/* :last-child is not part of CSS 2.1 (introduced in CSS 3) */
dl > dd > p:last-child { margin-bottom: 0; }
/* lists nested in definition lists */
/* :only-child is not part of CSS 2.1 (introduced in CSS 3) */
dd > ul:only-child, dd > ol:only-child { padding-left: 1em; }
/* Description Lists */
/* styled like in most dictionaries, encyclopedias etc. */
dl.description > dt {
font-weight: bold;
clear: left;
float: left;
margin: 0;
padding: 0;
padding-right: 0.5em;
}
/* Field Lists */
/* example for custom field-name width */
dl.field-list.narrow > dd {
margin-left: 5em;
}
/* run-in: start field-body on same line after long field names */
dl.field-list.run-in > dd p {
display: block;
}
/* Bibliographic Fields */
/* generally, bibliographic fields use special definition list dl.docinfo */
/* but dedication and abstract are placed into "topic" divs */
div.abstract p.topic-title {
text-align: center;
}
div.dedication {
margin: 2em 5em;
text-align: center;
font-style: italic;
}
div.dedication p.topic-title {
font-style: normal;
}
/* Citations */
dl.citation dt.label {
font-weight: bold;
}
span.fn-backref {
font-weight: normal;
}
/* Text Blocks */
/* ============ */
/* Literal Blocks */
/* Block Quotes */
blockquote > table,
div.topic > table {
margin-top: 0;
margin-bottom: 0;
}
blockquote p.attribution,
div.topic p.attribution {
text-align: right;
margin-left: 20%;
}
/* Tables */
/* ====== */
/* th { vertical-align: bottom; } */
table tr { text-align: left; }
/* "booktabs" style (no vertical lines) */
table.booktabs {
border: 0;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.booktabs * {
border: 0;
}
table.booktabs th {
border-bottom: thin solid;
}
/* numbered tables (counter defined in div.document) */
table.numbered > caption:before {
counter-increment: table;
content: "Table " counter(table) ": ";
font-weight: bold;
}
/* Explicit Markup Blocks */
/* ====================== */
/* Footnotes and Citations */
/* ----------------------- */
/* line on the left */
dl.footnote {
padding-left: 1ex;
border-left: solid;
border-left-width: thin;
}
/* Directives */
/* ---------- */
/* Body Elements */
/* ~~~~~~~~~~~~~ */
/* Images and Figures */
/* let content flow to the side of aligned images and figures */
.figure.align-left,
img.align-left,
object.align-left {
display: block;
clear: left;
float: left;
margin-right: 1em
}
.figure.align-right,
img.align-right,
object.align-right {
display: block;
clear: right;
float: right;
margin-left: 1em
}
/* Stop floating sidebars, images and figures at section level 1,2,3 */
h1, h2, h3 { clear: both; }
/* Sidebar */
/* Move into the margin. In a layout with fixed margins, */
/* it can be moved into the margin completely. */
div.sidebar {
width: 30%;
max-width: 26em;
margin-left: 1em;
margin-right: -5.5%;
background-color: #ffffee ;
}
/* Code */
pre.code { padding: 0.7ex }
pre.code, code { background-color: #eeeeee }
pre.code .ln { color: gray; } /* line numbers */
/* basic highlighting: for a complete scheme, see */
/* http://docutils.sourceforge.net/sandbox/stylesheets/ */
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
/* Math */
/* styled separately (see math.css for math-output=HTML) */
/* Epigraph */
/* Highlights */
/* Pull-Quote */
/* Compound Paragraph */
/* Container */
/* can be styled in a custom stylesheet */
/* Document Header and Footer */
div.footer, div.header {
clear: both;
font-size: smaller;
}
/* Inline Markup */
/* ============= */
/* Emphasis */
/* em */
/* Strong Emphasis */
/* strong */
/* Interpreted Text */
/* span.interpreted */
/* Title Reference */
/* cite */
/* Inline Literals */
/* possible values: normal, nowrap, pre, pre-wrap, pre-line */
/* span.docutils.literal { white-space: pre-wrap; } */
/* Hyperlink References */
a { text-decoration: none; }
/* External Targets */
/* span.target.external */
/* Internal Targets */
/* span.target.internal */
/* Footnote References */
/* a.footnote-reference */
/* Citation References */
/* a.citation-reference */
</style>
<style type="text/css">
/* inline literals */
span.docutils.literal { background-color: #eeeeee;
padding: 0.2ex}
pre.literal-block { background-color: #eeeeee;
padding: 0.7ex }
pre.doctest { background-color: #fff5e7 }
</style>
</head>
<body>
<div class="document" id="wortliste-py">
<h1 class="title">wortliste.py</h1>
<!-- #!/usr/bin/env python
# -*- coding: utf8 -*-
# :Copyright: © 2012 Günter Milde.
# :Licence: This work may be distributed and/or modified under
# the conditions of the `LaTeX Project Public License`,
# either version 1.3 of this license or (at your option)
# any later version.
# :Version: 0.1 (2012-02-07) -->
<pre class="literal-block">"""Hilfsmittel für die Arbeit mit der `Wortliste`"""</pre>
<div class="contents topic" id="inhalt">
<p class="topic-title first">Inhalt</p>
<ul class="simple">
<li><p><a class="reference internal" href="#abhangigkeiten" id="id13">Abhängigkeiten</a></p></li>
<li><p><a class="reference internal" href="#wordfile" id="id14">WordFile</a></p>
<ul>
<li><p><a class="reference internal" href="#initialisierung" id="id15">Initialisierung</a></p></li>
<li><p><a class="reference internal" href="#iteration" id="id16">Iteration</a></p></li>
<li><p><a class="reference internal" href="#asdict" id="id17">asdict()</a></p></li>
<li><p><a class="reference internal" href="#writelines" id="id18">writelines()</a></p></li>
<li><p><a class="reference internal" href="#write-entries" id="id19">write_entries()</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#wordentry" id="id20">WordEntry</a></p>
<ul>
<li><p><a class="reference internal" href="#argumente" id="id21">Argumente</a></p>
<ul>
<li><p><a class="reference internal" href="#feldnamen-feldindizes" id="id22">feldnamen, feldindizes</a></p></li>
<li><p><a class="reference internal" href="#ersatzfelder" id="id23">ersatzfelder</a></p></li>
<li><p><a class="reference internal" href="#comment" id="id24">comment</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#id2" id="id25">Initialisierung</a></p></li>
<li><p><a class="reference internal" href="#ruckverwandlung-in-string" id="id26">Rückverwandlung in String</a></p>
<ul>
<li><p><a class="reference internal" href="#unicode" id="id27">unicode()</a></p></li>
<li><p><a class="reference internal" href="#str" id="id28">__str__()</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#lang-index" id="id29">lang_index()</a></p></li>
<li><p><a class="reference internal" href="#key" id="id30">key()</a></p></li>
<li><p><a class="reference internal" href="#getitem" id="id31">getitem()</a></p></li>
<li><p><a class="reference internal" href="#get" id="id32">get()</a></p></li>
<li><p><a class="reference internal" href="#set" id="id33">set()</a></p></li>
<li><p><a class="reference internal" href="#setitem" id="id34">setitem()</a></p></li>
<li><p><a class="reference internal" href="#complete-completed" id="id35">complete(), completed()</a></p></li>
<li><p><a class="reference internal" href="#prune" id="id36">prune()</a></p></li>
<li><p><a class="reference internal" href="#merge" id="id37">merge()</a></p></li>
<li><p><a class="reference internal" href="#regelaenderungen" id="id38">regelaenderungen()</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#shortentry" id="id39">ShortEntry</a></p>
<ul>
<li><p><a class="reference internal" href="#id4" id="id40">Argumente</a></p>
<ul>
<li><p><a class="reference internal" href="#id5" id="id41">feldnamen, feldindizes</a></p></li>
<li><p><a class="reference internal" href="#id6" id="id42">ersatzfelder</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#id7" id="id43">Initialisierung</a></p></li>
<li><p><a class="reference internal" href="#id8" id="id44">key()</a></p></li>
<li><p><a class="reference internal" href="#getitem-get" id="id45">getitem, get()</a></p></li>
<li><p><a class="reference internal" href="#id9" id="id46">complete(), completed()</a></p></li>
<li><p><a class="reference internal" href="#id10" id="id47">prune()</a></p></li>
<li><p><a class="reference internal" href="#id11" id="id48">merge()</a></p></li>
<li><p><a class="reference internal" href="#wordentries" id="id49">wordentries()</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#funktionen" id="id50">Funktionen</a></p>
<ul>
<li><p><a class="reference internal" href="#transformationen" id="id51">Transformationen</a></p>
<ul>
<li><p><a class="reference internal" href="#ableitung1901" id="id52">ableitung1901()</a></p>
<ul>
<li><p><a class="reference internal" href="#trennregelanderungen" id="id53">Trennregeländerungen</a></p></li>
<li><p><a class="reference internal" href="#rechtschreibanderungen" id="id54">Rechtschreibänderungen</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#versalschreibung" id="id55">versalschreibung()</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#join-word" id="id56">join_word()</a></p></li>
<li><p><a class="reference internal" href="#zerlege" id="id57">zerlege()</a></p></li>
<li><p><a class="reference internal" href="#transfererror" id="id58">TransferError</a></p></li>
<li><p><a class="reference internal" href="#uebertrage" id="id59">uebertrage()</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#sortierschlussel" id="id60">Sortierschlüssel</a></p>
<ul>
<li><p><a class="reference internal" href="#sortkey-duden" id="id61">sortkey_duden()</a></p></li>
<li><p><a class="reference internal" href="#udiff" id="id62">udiff()</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#sprachtags" id="id63">Sprachtags</a></p></li>
<li><p><a class="reference internal" href="#tests" id="id64">Tests</a></p></li>
<li><p><a class="reference internal" href="#aufruf-von-der-kommandozeile" id="id65">Aufruf von der Kommandozeile</a></p></li>
<li><p><a class="reference internal" href="#quellen" id="id66">Quellen</a></p></li>
</ul>
</div>
<p>Die hier versammelten Funktionen und Klassen dienen der Arbeit an und
mit der freien <a class="reference external" href="../../../dokumente/README.wortliste">Wortliste der deutschsprachigen Trennmustermannschaft</a>
(<a class="reference external" href="../../../wortliste">wortliste</a>).</p>
<div class="section" id="abhangigkeiten">
<h1><a class="toc-backref" href="#id13">Abhängigkeiten</a></h1>
<p>Python 2.7 mit den Standardbibliotheken:</p>
<pre class="literal-block">import difflib
import re
import codecs
import unicodedata
import copy
import itertools</pre>
</div>
<div class="section" id="wordfile">
<h1><a class="toc-backref" href="#id14">WordFile</a></h1>
<p>Klasse zum Lesen und Schreiben der <cite>Wortliste</cite>:</p>
<pre class="literal-block">class WordFile(file):
encoding = 'utf8'</pre>
<div class="section" id="initialisierung">
<h2><a class="toc-backref" href="#id15">Initialisierung</a></h2>
<p>Das Argument <span class="docutils literal">format</span> ist „f8“, „f5“, oder „auto“:</p>
<blockquote>
<dl class="field-list simple">
<dt>f8</dt>
<dd><p>das originale, maximal 8-spaltige Wortlisten-Format (<a class="reference internal" href="#langform">Langform</a>),</p>
</dd>
<dt>f5</dt>
<dd><p>das neue, maximal 5-spaltige Wortlisten-Format (<a class="reference internal" href="#kurzform">Kurzform</a>),</p>
</dd>
<dt>auto</dt>
<dd><p>bestimme das Format automatisch.</p>
</dd>
</dl>
</blockquote>
<pre class="literal-block">def __init__(self, name, mode='r', encoding='utf8', format='f8'):
self.encoding = encoding
file.__init__(self, name, mode)
# Dateiformat bestimmen und die Eintrags-Klasse setzen:
self.set_entry_class(format)</pre>
<p>Klasse zum Verarbeiten der Zeilen setzen.
Mit self.format == „auto“, werden die ersten Zeilen der Datei untersucht
und der Pointer zurückgesetzt.</p>
<pre class="literal-block">def set_entry_class(self, format, search_limit=1000):
assert(format in ('f8', 'f5', 'auto'))
self.format = format # default
self.entry_class = WordEntry # default
n = 0 # Zählindex
# Format anhand des Dateiinhalts bestimmen:
if format == 'auto':
for e in self:
# nur ein Feld oder erstes Feld leer oder mit Trennzeichen:
if len(e) == 1 or e and re.search(u'[-=<>]', e[0]):
self.format = 'f5'
break
# mehr als 5 Felder: 8-Felder-Format (Langform)
elif len(e) > 5:
self.format = 'f8'
break
if n > search_limit:
break
n += 1
if self.format == 'f5':
self.entry_class = ShortEntry
self.seek(0) # Dateizeiger zurücksetzen</pre>
</div>
<div class="section" id="iteration">
<h2><a class="toc-backref" href="#id16">Iteration</a></h2>
<p>Die spezielle Funktion <cite>__iter__</cite> wird aufgerufen wenn über eine
Klasseninstanz iteriert wird.
Sie liefert einen Iterator über die „geparsten“ Zeilen (Datenfelder)</p>
<pre class="literal-block">def __iter__(self):
entry_class = self.entry_class
while True:
line = self.next().rstrip().decode(self.encoding)
yield entry_class(line)</pre>
</div>
<div class="section" id="asdict">
<h2><a class="toc-backref" href="#id17">asdict()</a></h2>
<p>Gib ein <cite>dictionary</cite> (assoziatives Array) mit ungetrenntem Wort als
Schlüssel (<cite>key</cite>) und den Datenfeldern als <cite>value</cite> zurück:</p>
<pre class="literal-block">def asdict(self):
words = dict()
for entry in self:
words[entry[0]] = entry
return words</pre>
</div>
<div class="section" id="writelines">
<h2><a class="toc-backref" href="#id18">writelines()</a></h2>
<p>Schreibe eine Liste von <cite>unicode</cite> Strings (Zeilen ohne Zeilenendezeichen)
in die Datei <cite>destination</cite>:</p>
<pre class="literal-block">def writelines(self, lines, destination, encoding=None):
outfile = codecs.open(destination, 'w',
encoding=(encoding or self.encoding))
outfile.writelines(lines)</pre>
</div>
<div class="section" id="write-entries">
<h2><a class="toc-backref" href="#id19">write_entries()</a></h2>
<p>Schreibe eine Liste von Einträgen (<a class="reference internal" href="#wordentry">WordEntry</a> oder <a class="reference internal" href="#shortentry">ShortEntry</a> Objekten) in
die Datei <cite>destination</cite>:</p>
<pre class="literal-block">def write_entries(self, wortliste, destination, encoding=None):
lines = (unicode(entry) for entry in wortliste)
self.writelines(lines, destination, encoding)</pre>
</div>
</div>
<div class="section" id="wordentry">
<h1><a class="toc-backref" href="#id20">WordEntry</a></h1>
<p>Klasse für Einträge (Zeilen) der <a class="reference external" href="../../../wortliste">Wortliste</a> in <a class="reference internal" href="#langform">Langform</a>.
Jede Zeile enthält einen Eintrag mit durch Semikolon „;“
getrennten Feldern.</p>
<p>Beispiel:</p>
<pre class="code python doctest">>>> from wortliste import WordEntry
</pre>
<pre class="code python doctest">>>> aalbestand = WordEntry(u'Aalbestand;Aal=be<stand # Test')
>>> print aalbestand
Aalbestand;Aal=be<stand # Test
</pre>
<p id="langform">Bedeutung der Felder in der „Langform“:</p>
<ol class="arabic simple">
<li><p>Wort ungetrennt</p></li>
<li><p>Wort mit Trennungen, falls für alle Varianten identisch,
anderenfalls leer</p></li>
<li><p>falls Feld 2 leer, Trennung nach traditioneller Rechtschreibung</p></li>
<li><p>falls Feld 2 leer, Trennung nach reformierter Rechtschreibung (2006)</p></li>
<li><p>falls Feld 2 leer, Trennung für Wortform, die entweder in
der Schweiz oder mit Großbuchstaben oder Kapitälchen benutzt wird
und für traditionelle und reformierte Rechtschreibung identisch ist</p></li>
<li><p>falls Feld 5 leer, Trennung für Wortform, die entweder in
der Schweiz oder mit Großbuchstaben oder Kapitälchen benutzt wird,
traditionelle Rechtschreibung</p></li>
<li><p>falls Feld 5 leer, Trennung für Wortform, die entweder in
der Schweiz oder mit Großbuchstaben oder Kapitälchen benutzt wird,
reformierte Rechtschreibung (2006)</p></li>
<li><p>falls Feld 5 leer, Trennung nach (deutsch)schweizerischer
Rechtschreibung; insbesondere Wörter mit „sss“ gefolgt von
einem Vokal, die wie andere Dreifachkonsonanten gehandhabt wurden
(also anders, als der Duden früher vorgeschrieben hat), z.B.
„süssauer“</p></li>
</ol>
<pre class="literal-block">class WordEntry(list):</pre>
<div class="section" id="argumente">
<h2><a class="toc-backref" href="#id21">Argumente</a></h2>
<div class="section" id="feldnamen-feldindizes">
<h3><a class="toc-backref" href="#id22">feldnamen, feldindizes</a></h3>
<p>Benennung der Felder mit Sprachkürzeln (Tags nach <a class="citation-reference" href="#bcp47" id="id1">[BCP47]</a>).
(Die Zählung der Indizes beginnt in Python bei 0.):</p>
<pre class="literal-block">feldnamen = ('key', 'de', 'de-1901', 'de-1996', 'de-x-versal',
'de-1901-x-versal', 'de-1996-x-versal', 'de-CH-1901')
feldindizes = {
'key': 0, # Schlüssel
'de': 1, # Deutsch, allgemeingültig
'de-1901': 2, # "traditionell" (nach Rechtschreibreform 1901)
'de-1996': 3, # reformierte Reformschreibung (1996)
'de-x-GROSS': 4, # ohne ß (Schweiz oder versal) allgemein
'de-x-versal': 4, # Alias
# 'de-CH': 4, # Alias
'de-1901-x-GROSS': 5, # ohne ß (Schweiz oder versal) "traditionell"
'de-1901-x-versal': 5, # Alias
'de-1996-x-GROSS': 6, # ohne ß (Schweiz oder versal) "reformiert"
'de-1996-x-versal': 6, # Alias
# 'de-CH-1996': 6, # Alias
'de-CH-1901': 7, # ohne ß (Schweiz) "traditionell" ("süssauer")
}</pre>
</div>
<div class="section" id="ersatzfelder">
<h3><a class="toc-backref" href="#id23">ersatzfelder</a></h3>
<p>Bei der Auswahl eines Wortes in einer Rechtschreibvariante werden
„generische“ Felder gewählt, falls das „Originalfeld“ fehlt. Die folgenden
Tupel listen die Ersatzfelder für das ensprechende Originalfeld.</p>
<p>Bsp: Ersatz-Felder für ‚de-CH-1901‘:</p>
<pre class="code python doctest">>>> for i in WordEntry.ersatzfelder[WordEntry.feldindizes['de-CH-1901']]:
... print WordEntry.feldnamen[i]
de-1901-x-versal
de-x-versal
de-1901
de
</pre>
<pre class="literal-block"># Ersatzindizes Index Nr Name
ersatzfelder = (tuple(), # 0 1 key
tuple(), # 1 2 'de'
(1,), # 2 3 'de-1901'
(1,), # 3 4 'de-1996'
(1,), # 4 5 'de-x-versal'
(4, 2, 1), # 5 6 'de-1901-x-versal'
(4, 3, 1), # 6 7 'de-1996-x-versal'
(5, 4, 2, 1), # 7 8 'de-CH-1901'
)</pre>
</div>
<div class="section" id="comment">
<h3><a class="toc-backref" href="#id24">comment</a></h3>
<p>Kommentar, Vorgabe ist ein leerer String:</p>
<pre class="literal-block">comment = u''</pre>
</div>
</div>
<div class="section" id="id2">
<h2><a class="toc-backref" href="#id25">Initialisierung</a></h2>
<pre class="literal-block">def __init__(self, line, delimiter=u';'):
self.delimiter = delimiter</pre>
<p>eventuell vorhandenen Kommentar abtrennen und speichern:</p>
<pre class="literal-block">if u'#' in line:
line, comment = line.split(u'#', 1)
self.comment = comment.strip()
line = line.rstrip()
# print (line, self.comment)
if not line: # kein Inhalt
return</pre>
<p>Zerlegen in Datenfelder, in Liste eintragen:</p>
<pre class="literal-block">for field in line.split(delimiter):
if field.startswith(u'-'):
self.append(u'')
else:
self.append(field)</pre>
</div>
<div class="section" id="ruckverwandlung-in-string">
<h2><a class="toc-backref" href="#id26">Rückverwandlung in String</a></h2>
<p>Erzeugen eines Eintrag-Strings (ohne Zeilenendezeichen) aus der Liste der
Datenfelder und dem Kommentar</p>
<div class="section" id="unicode">
<h3><a class="toc-backref" href="#id27">unicode()</a></h3>
<pre class="code python doctest">>>> unicode(aalbestand)
u'Aalbestand;Aal=be<stand # Test'
>>> leerkommentar = WordEntry(u'# Testkommentar ')
>>> leerkommentar
[]
>>> leerkommentar.comment
u'Testkommentar'
>>> unicode(leerkommentar)
u'# Testkommentar'
</pre>
<pre class="literal-block">def __unicode__(self):
# Nummerieren leerer Felder:
fields = [field or u'-%d-' % (i+1)
for (i, field) in enumerate(self)]
line = u';'.join(fields)
if self.comment:
line += u' # ' + self.comment
if not self:
line = line.lstrip()
return line</pre>
</div>
<div class="section" id="str">
<h3><a class="toc-backref" href="#id28">__str__()</a></h3>
<pre class="literal-block">def __str__(self):
return unicode(self).encode('utf8')</pre>
</div>
</div>
<div class="section" id="lang-index">
<h2><a class="toc-backref" href="#id29">lang_index()</a></h2>
<p>Bestimme den Index des zur Sprachvariante gehörenden Datenfeldes unter
Verwendung der Ersatzfelder:</p>
<pre class="code python doctest">>>> aalbestand.lang_index('de')
1
>>> aalbestand.lang_index('de-1901')
1
>>> aalbestand.lang_index('de-1996')
1
>>> aalbestand.lang_index('de-x-versal')
1
>>> aalbestand.lang_index('de-1901-x-versal')
1
>>> aalbestand.lang_index('de-1996-x-versal')
1
>>> abbeissen = WordEntry(
... u'abbeissen;-2-;-3-;-4-;-5-;ab<bei-ssen;ab<beis-sen;ab<beis-sen')
>>> print abbeissen.lang_index('de')
None
>>> print abbeissen.lang_index('de-x-versal')
None
>>> abbeissen.lang_index('de-1901-x-versal')
5
>>> abbeissen.lang_index('de-1996-x-versal')
6
>>> abbeissen.lang_index('de-CH-1901')
7
>>> urlaubstipp = WordEntry(u'Urlaubstipp;-2-;-3-;Ur<laubs=tipp')
>>> print urlaubstipp.lang_index('de')
None
>>> print urlaubstipp.lang_index('de-1901')
None
>>> print urlaubstipp.lang_index('de-1996')
3
>>> print urlaubstipp.lang_index('de-x-versal')
None
>>> print urlaubstipp.lang_index('de-1901-x-versal')
None
</pre>
<pre class="literal-block">def lang_index(self, lang):
assert lang in self.feldindizes, \
'Sprachvariante "%s" nicht in %s' % (lang,
self.feldindizes.keys())</pre>
<p>Einfacher Fall: eine allgemeine Schreibweise:</p>
<pre class="literal-block">if len(self) == 2:
if u'ß' in self[0] and lang in ('de-CH-1901', 'de-1901-x-versal',
'de-CH-1996', 'de-1996-x-versal'):
return None
else:
return 1</pre>
<p>Spezielle Schreibung:</p>
<pre class="literal-block">try:
i = self.feldindizes[lang]
feld = self[i]
except IndexError:
if lang == 'de-CH-1901':
return self.lang_index('de-1901-x-versal')
# Allgemeine Schweiz/versal Schreibung:
if i > 4 and len(self) == 5:
return 4
# versal == normal (kein sz):
if len(self) == 4 and u'ß' not in self[0]:
if lang in ('de-CH-1901', 'de-1901-x-versal'):
return self.lang_index('de-1901')
elif lang in ('de-CH-1996', 'de-1996-x-versal'):
return self.lang_index('de-1996')
return None # Feld nicht vorhanden
if not feld: # leeres Feld
return None
return i</pre>
</div>
<div class="section" id="key">
<h2><a class="toc-backref" href="#id30">key()</a></h2>
<p>Gib einen Schlüssel (ungetrenntes Wort) zurück.</p>
<p>Bei Einträgen im <a class="reference internal" href="#langform">Langform</a> ist der Schlüssel gleich dem Inhalt des ersten
Feldes. Die Funktion dient zur Kompatibilität mit <a class="reference internal" href="#shortentry">ShortEntry</a>. Das <cite>lang</cite>
Argument wird ignoriert, da der Schlüssel (im Gegensatz zur <a class="reference internal" href="#kurzform">Kurzform</a>)
stets eindeutig ist:</p>
<pre class="literal-block">def key(self, lang=None):
"""Gib den Schlüssel (ungetrenntes Wort) zurück."""
try:
return self[0]
except IndexError: # reiner Kommentar oder leerer Eintrag
if self.comment:
return u'#'
return u''</pre>
</div>
<div class="section" id="getitem">
<h2><a class="toc-backref" href="#id31">getitem()</a></h2>
<p>Gib Feld <span class="docutils literal">i</span> oder Ersatzfeld zurück.</p>
<pre class="literal-block">def getitem(self, i):
"""Return item ``i`` or a subsititute"""
try:
return self[i]
except IndexError: # Feld i nicht vorhanden
pass
# Ersatzregeln anwenden
for _i in self.ersatzfelder[i]:
try:
word = self[_i]
except IndexError: # Feld i nicht vorhanden
continue # nächsten `tag` versuchen
# Spezialfall: in Versalschreibung ungültige Ersatz-Wörter
if i >= 4 and _i <4 and u'ß' in word:
return u''
return word
return u''</pre>
</div>
<div class="section" id="get">
<span id="wordentry-get"></span><h2><a class="toc-backref" href="#id32">get()</a></h2>
<p>Trennmuster für eine Sprachvariante ausgeben:</p>
<pre class="code python doctest">>>> aalbestand.get('de')
u'Aal=be<stand'
>>> aalbestand.get('de-1901')
u'Aal=be<stand'
>>> aalbestand.get('de-1996')
u'Aal=be<stand'
>>> aalbestand.get('de-x-versal')
u'Aal=be<stand'
>>> aalbestand.get('de-1901-x-versal')
u'Aal=be<stand'
>>> aalbestand.get('de-1996-x-versal')
u'Aal=be<stand'
>>> aalbestand.get('de-CH-1901')
u'Aal=be<stand'
</pre>
<pre class="code python doctest">>>> weste = WordEntry(u'Weste;-2-;We-ste;Wes-te')
>>> weste.get('de')
u''
>>> weste.get('de-1901')
u'We-ste'
>>> weste.get('de-1996')
u'Wes-te'
</pre>
<pre class="code python doctest">>>> abbeissen.get('de')
u''
>>> abbeissen.get('de-x-versal')
u''
>>> abbeissen.get('de,de-x-versal')
u''
>>> abbeissen.get('de-1901-x-versal')
u'ab<bei-ssen'
>>> abbeissen.get('de,de-1901,de-1901-x-versal')
u'ab<bei-ssen'
>>> abbeissen.get('de-CH-1901')
u'ab<beis-sen'
</pre>
<pre class="literal-block">def get(self, tags):
for lang in tags.split(','):
word = self.getitem(self.feldindizes[lang])
if word:
return word
return u''</pre>
</div>
<div class="section" id="set">
<h2><a class="toc-backref" href="#id33">set()</a></h2>
<p>Trennmuster für Sprachvariante setzen:</p>
<pre class="code python doctest">>>> abbeissen.set('test', 'de-1901-x-versal')
>>> print abbeissen
abbeissen;-2-;-3-;-4-;-5-;test;ab<beis-sen;ab<beis-sen
</pre>
<pre class="code python doctest">>>> abbeissen.set('test', 'de-1901')
Traceback (most recent call last):
...
IndexError: kann kein leeres Feld setzen
</pre>
<pre class="code python doctest">>>> abbeissen.set('test', 'de-1901,de-1901-x-versal')
>>> print abbeissen
abbeissen;-2-;-3-;-4-;-5-;test;ab<beis-sen;ab<beis-sen
</pre>
<pre class="literal-block">def set(self, word, tags):
for lang in tags.split(','):
i = self.lang_index(lang)
if i is None:
continue
if word is None:
word = u''
self[i] = word
return
raise IndexError, "kann kein leeres Feld setzen"</pre>
</div>
<div class="section" id="setitem">
<h2><a class="toc-backref" href="#id34">setitem()</a></h2>
<p>Feld <span class="docutils literal">i</span> setzen:</p>
<pre class="code python doctest">>>> entry = WordEntry(u'test;test')
>>> entry.setitem(4, u's-x')
>>> print entry
test;test;-3-;-4-;s-x
>>> entry.setitem(3, u'sz')
>>> print entry
test;test;-3-;sz;s-x
</pre>
<pre class="literal-block">def setitem(self, i, word):
while len(self) < i+1:
self.append(u'')
self[i] = word</pre>
</div>
<div class="section" id="complete-completed">
<h2><a class="toc-backref" href="#id35">complete(), completed()</a></h2>
<p>Alle Felder setzen:</p>
<pre class="code python doctest">>>> print WordEntry(u'Ruhe;Ru-he').completed()
Ruhe;Ru-he;Ru-he;Ru-he;Ru-he;Ru-he;Ru-he;Ru-he
</pre>
<pre class="code python doctest">>>> print str(aalbestand), len(aalbestand)
Aalbestand;Aal=be<stand # Test 2
>>> print aalbestand.completed()
Aalbestand;Aal=be<stand;Aal=be<stand;Aal=be<stand;Aal=be<stand;Aal=be<stand;Aal=be<stand;Aal=be<stand # Test
</pre>
<pre class="code python doctest">>>> auffrass = WordEntry(u'auffrass;-2-;-3-;-4-;auf-frass')
>>> print auffrass.completed()
auffrass;-2-;-3-;-4-;auf-frass;auf-frass;auf-frass;auf-frass
</pre>
<pre class="code python doctest">>>> fresssack= WordEntry(u'Fresssack;-2-;-3-;Fress=sack;Fress=sack')
>>> print fresssack.completed()
Fresssack;-2-;-3-;Fress=sack;Fress=sack;Fress=sack;Fress=sack;Fress=sack
</pre>
<pre class="code python doctest">>>> line = u'Flussschiffahrt;-2-;-3-;-4-;-5-;Fluss=schi{ff/ff=f}ahrt;-7-'
>>> print WordEntry(line).completed()
Flussschiffahrt;-2-;-3-;-4-;-5-;Fluss=schi{ff/ff=f}ahrt;-7-;Fluss=schi{ff/ff=f}ahrt
</pre>
<pre class="code python doctest">>>> line = u'Ackerstraße;-2-;A{ck/k-k}er=stra-ße;Acker=stra-ße'
>>> ackerstrasse = WordEntry(line).completed()
>>> print unicode(ackerstrasse)
Ackerstraße;-2-;A{ck/k-k}er=stra-ße;Acker=stra-ße;-5-;-6-;-7-;-8-
</pre>
<pre class="literal-block">def complete(self):
for i in range(len(self),8):
self.append(self.getitem(i))
def completed(self):
"""Return expanded copy of self."""
neu = copy.copy(self)
neu.complete()
return neu</pre>
</div>
<div class="section" id="prune">
<h2><a class="toc-backref" href="#id36">prune()</a></h2>
<p>Felder für Sprachvarianten zusammenfassen, wenn gleich:</p>
<pre class="code python doctest">>>> aalbestand.prune()
>>> print aalbestand
Aalbestand;Aal=be<stand # Test
>>> auffrass.prune()
>>> print auffrass
auffrass;-2-;-3-;-4-;auf-frass
>>> entry = WordEntry(u'distanziert;-2-;di-stan-ziert;di-stan-ziert')
>>> entry.prune()
>>> print entry
distanziert;di-stan-ziert
>>> entry = WordEntry(u'Gauss;-2-;Gauss;Gauss;Gauss')
>>> entry.prune()
>>> print entry
Gauss;Gauss
>>> fresssack.prune()
>>> print fresssack
Fresssack;-2-;-3-;Fress=sack;Fress=sack
</pre>
<pre class="code python doctest">>>> masse = WordEntry(u'Masse;Mas-se;Mas-se;Mas-se;Mas-se;Mas-se;Mas-se;Mas-se')
>>> masse.prune()
>>> print masse
Masse;Mas-se
</pre>
<p>Aber nicht, wenn die Trennstellen sich unterscheiden:</p>
<pre class="code python doctest">>>> abenddienste = WordEntry(
... u'Abenddienste;-2-;Abend=dien-ste;Abend=diens-te')
>>> abenddienste.prune()
>>> print abenddienste
Abenddienste;-2-;Abend=dien-ste;Abend=diens-te
>>> ackerstrasse.prune()
>>> print unicode(ackerstrasse)
Ackerstraße;-2-;A{ck/k-k}er=stra-ße;Acker=stra-ße
>>> entry = WordEntry(
... u'Schlammmasse;-2-;-3-;Schlamm=mas-se;-5-;-6-;Schlamm=mas-se;-8-')
>>> entry.prune()
>>> print entry
Schlammmasse;-2-;-3-;Schlamm=mas-se
>>> entry = WordEntry(
... u'Flussschiffahrt;-2-;-3-;-4-;-5-;Fluss=schi{ff/ff=f}ahrt;-7-')
>>> entry.prune()
>>> print entry
Flussschiffahrt;-2-;-3-;-4-;-5-;Fluss=schi{ff/ff=f}ahrt;-7-
</pre>
<pre class="literal-block">def prune(self):
if len(self) == 8:
if self[7] == self[5]: # de-CH-1901 gleich versal-1901
self.pop()
if len(self) == 7:
if self[6] == self[5]:
self[4] = self[5] # umschreiben auf versal-allgemein
self.pop()
self.pop()
elif (not(self[4] or self[5] or self[6])
or self[5] == self[2] and self[6] == self[3]):
# alle leer oder ohne ß-Ersetzung
self.pop()
self.pop()
self.pop()
if len(self) == 5:
if not self[4]:
self.pop()
elif self[1] == self[4]: # de-x-versal == de
self.pop()
self.pop()
self.pop()
elif self[2] == self[3] == self[4]:
self[1] = self[2] # Umschreiben auf de (allgemein)
self.pop()
self.pop()
self.pop()
if len(self) == 4:
if self[3] == self[2]: # de-1996 == de-1901
self[1] = self[2] # Umschreiben auf de (allgemein)
self.pop()
self.pop()
if len(self) > 6:
self[4] = u''
if len(self) > 2:
self[1] = u''</pre>
</div>
<div class="section" id="merge">
<span id="wordentry-merge"></span><h2><a class="toc-backref" href="#id37">merge()</a></h2>
<p>Einträge zusammenfassen:</p>
<pre class="code python doctest">>>> entry = WordEntry(u'Abenddress;Abend=dress')
>>> entry.merge(WordEntry(u'Abenddress;-2-;-3-;-4-;Abend=dress'))
>>> print unicode(entry)
Abenddress;Abend=dress
>>> entry = WordEntry(u'Gauss;Gauss')
>>> entry.merge(WordEntry(u'Gauss;-2-;-3-;-4-;Gauss'))
>>> print unicode(entry)
Gauss;Gauss
>>> masse.merge(WordEntry(u'Masse;-2-;-3-;-4-;-5-;Ma-sse;Mas-se;Mas-se'), allow_alternatives=True)
>>> print masse
Masse;-2-;Mas-se;Mas-se;-5-;[Mas-se/Ma-sse];Mas-se;Mas-se
</pre>
<pre class="literal-block">def merge(self, other, allow_alternatives=False, prune=True):
self.complete()
other.complete()
conflict = False
for i, (s_i, o_i) in enumerate(zip(self,other)):
if not o_i:
continue
if not s_i:
self[i] = o_i
other[i] = u''
elif s_i == o_i:
other[i] = u''
elif s_i != o_i:
if allow_alternatives:
self[i] = u'[%s/%s]' % (s_i, o_i)
o_i = u''
else:
conflict = True
# self.comment = other.comment or self.comment
if self.comment != other.comment:
if not [v for v in other if v]: # no entries in `other`
self.comment = self.comment or other.comment
else:
conflict = True
if conflict:
raise AssertionError(u'Merge Error:\n %s\n %s '
% (unicode(self), unicode(other)))
if prune:
other.prune()
self.prune()</pre>
</div>
<div class="section" id="regelaenderungen">
<h2><a class="toc-backref" href="#id38">regelaenderungen()</a></h2>
<p>Teste Felder auf Konsistenz mit den Regeländerungen der Orthographiereform
1996, ändere Unstimmigkeiten <cite>in place</cite>.</p>
<p>Die neuere Funktion <a class="reference internal" href="#ableitung1901">ableitung1901()</a>, deckt mehr Ausnahmen ab aber
funktioniert nur in eine Richtung.</p>
<p>Falls ein generisches Feld von Änderung betroffen ist, schreibe die
korrekten Trennungen in die spezifischen Felder.</p>
<pre class="code python doctest">>>> entry = WordEntry(u'Würste;Wür-ste')
>>> entry.regelaenderungen()
>>> print unicode(entry)
Würste;-2-;Wür-ste;Würs-te
>>> entry = WordEntry(u'Würste;Würs-te')
>>> entry.regelaenderungen()
>>> print unicode(entry)
Würste;-2-;Wür-ste;Würs-te
>>> entry = WordEntry(u'Hecke;He-cke')
>>> entry.regelaenderungen()
>>> print unicode(entry)
Hecke;-2-;He{ck/k-k}e;He-cke
>>> entry = WordEntry(u'Ligusterhecke;Ligu-ster=he{ck/k-k}e')
>>> entry.regelaenderungen()
>>> print unicode(entry)
Ligusterhecke;-2-;Ligu-ster=he{ck/k-k}e;Ligus-ter=he-cke
</pre>
<p>Bei Änderungen der Schreibung wird das entsprechende Feld ausgekreuzt:</p>
<pre class="code python doctest">>>> entry = WordEntry(u'Hass;Hass')
>>> entry.regelaenderungen()
>>> print unicode(entry)
Hass;-2-;-3-;Hass;Hass
>>> entry = WordEntry(u'fasst;fasst')
>>> entry.regelaenderungen()
>>> print unicode(entry)
fasst;-2-;-3-;fasst;fasst
>>> entry = WordEntry(u'Missbrauch;Miss<brauch')
>>> entry.regelaenderungen()
>>> print unicode(entry)
Missbrauch;-2-;-3-;Miss<brauch;Miss<brauch
>>> entry = WordEntry(u'schlifffest;schliff=fest')
>>> entry.regelaenderungen()
>>> print unicode(entry)
schlifffest;-2-;-3-;schliff=fest
</pre>
<p>Bei gleicher, nicht betroffener Trennung werden Felder zusammengefasst:</p>
<pre class="code python doctest">>>> entry = WordEntry(u'austoben;-2-;aus<to-ben;aus<to-ben')
>>> entry.regelaenderungen()
>>> print unicode(entry)
austoben;aus<to-ben
</pre>
<p>Achtung: nicht narrensicher – Ausnahmen und Mehrdeutigkeiten werden nicht
erkannt:</p>
<pre class="code python doctest">>>> entry = WordEntry(u'Boss;Boss # engl.') # korrekt
>>> entry.regelaenderungen()
>>> print unicode(entry)
Boss;-2-;-3-;Boss;Boss # engl.
</pre>
<pre class="code python doctest">>>> entry = WordEntry(u'Fluß;Fluß') # in de-1996 nur Fluss
>>> entry.regelaenderungen()
>>> print unicode(entry)
Fluß;Fluß
</pre>
<pre class="literal-block">def regelaenderungen(self):
# Trennregeländerungen:
r1901 = (u'-st', u'{ck/k-k}')
r1996 = (u's-t', u'-ck')
w1901 = self.get('de-1901')
w1996 = self.get('de-1996')
w_versal = None
if w1901 is None or w1996 is None:
return
for r1, r2 in zip(r1901, r1996):
w1901 = w1901.replace(r2,r1)
w1996 = w1996.replace(r1,r2)
# kein Schluss-ss und sst in de-1901 (ungetrenntes "ss" nur in Ausnahmen)
# aber: 'ßt' und Schluß-ß auch in de-1996 möglich (langer Vokal)
if u'ss' in w1901:
w_versal = w1901
w1901 = None
# Dreikonsonantenregel:
if w1901 and re.search(ur'(.)\1=\1', w1901):
w1901 = None
# Speichern:
if w1901 == w1996: # keine Regeländerung im Wort
if len(self) > 2:
self.prune()
return
if w1901 is None:
self.extend( ['']*(4-len(self)) )
self[1] = u''
self[2] = u''
self[3] = w1996
else:
self.extend( ['']*(4-len(self)) )
self[1] = u''
self[2] = w1901
self[3] = w1996
if w_versal:
self.append(w_versal)</pre>
</div>
</div>
<div class="section" id="shortentry">
<h1><a class="toc-backref" href="#id39">ShortEntry</a></h1>
<p>Klasse für Einträge (Zeilen) der Wortlisten in <a class="reference internal" href="#kurzform">Kurzform</a>.</p>
<p>Beispiel:</p>
<pre class="code python doctest">>>> from wortliste import ShortEntry
>>> aalbst = ShortEntry(u'Aal=be<stand # Test')
>>> dse = ShortEntry(u'Diens-te')
>>> print dse.get('de'), dse.get('de-1901')
Diens-te Dien-ste
</pre>
<p id="kurzform">Belegung der Felder in der „Kurzform“ (Sprachtags nach <a class="citation-reference" href="#bcp47" id="id3">[BCP47]</a>):</p>
<dl>
<dt>de:</dt>
<dd><p>Wort mit Trennungen nach aktueller Rechtschreibung (de-1996).</p>
<p>Einziges Pflichtfeld. Alle weiteren Felder sind optional, falls der Inhalt
über <a class="reference internal" href="#transformationen">Transformationen</a> gewonnen werden kann.</p>
<p>„-1-“ falls die Schreibung in de-1996 unzulässig ist (-1-;Pro<zeß).</p>
</dd>
<dt>de-1901:</dt>
<dd><p>Wort mit Trennung nach traditioneller Rechtschreibung.</p>
<p>„-2-“ falls die Schreibung in de-1901 unzulässig ist (Ur<laubs=tipp;-2-).</p>
</dd>
<dt>de-CH oder de-x-versal:</dt>
<dd><p>Wort mit ß-Ersatzschreibung, die der Schweiz und bei Satz mit
Großbuchstaben oder Kapitälchen benutzt wird.
Trennungen nach aktueller Rechtschreibung (Grüs-se).</p>
<p>„-3-“ falls die Schreibung in de-CH-1996 unzulässig ist.</p>
</dd>
<dt>de-1901-x-versal:</dt>
<dd><p>Wort mit ß-Ersatzschreibung für de-1901 mit Großbuchstaben oder
Kapitälchen (Grü-sse).</p>
<p>„-4-“ falls die abgeleitete Schreibung in de-1901 unzulässig ist.</p>
</dd>
<dt>de-CH-1901:</dt>
<dd><p>Wort mit ß-Ersatzschreibung, die der Schweiz benutzt wird.
Insbesondere Wörter mit „sss“ gefolgt von einem Vokal, die wie
andere Dreifachkonsonanten gehandhabt wurden (also anders, als
bei Ersatzschreibung in Deutschland und Österreich), z.B. „süssauer“</p>
<p>„-5-“ falls die abgeleitete Schreibung in de-CH-1901 unzulässig ist.</p>
</dd>
</dl>
<pre class="literal-block">class ShortEntry(WordEntry):</pre>
<div class="section" id="id4">
<h2><a class="toc-backref" href="#id40">Argumente</a></h2>
<div class="section" id="id5">
<h3><a class="toc-backref" href="#id41">feldnamen, feldindizes</a></h3>
<p>Achtung: die „generischen“ Sprachtags sind</p>
<blockquote>
<ul class="simple">
<li><p>in der <a class="reference internal" href="#kurzform">Kurzform</a> ein Alias für die aktuelle Rechtschreibung,</p></li>
<li><p>in der <a class="reference internal" href="#langform">Langform</a> Bezeichner für allgemeingültige Trennungen.</p></li>
</ul>
</blockquote>
<pre class="code python doctest">>>> print aalbst.feldindizes['de-1901'], aalbst.feldindizes['de-CH']
1 2
</pre>
<pre class="code python doctest">>>> print aalbst.feldindizes['de'], aalbst.feldindizes['de-1996']
0 0
>>> print aalbestand.feldindizes['de'], aalbestand.feldindizes['de-1996']
1 3
</pre>
<pre class="literal-block">feldnamen = ('de', 'de-1901', 'de-CH', 'de-1901-x-versal', 'de-CH-1901')
feldindizes = {
'de': 0, # Deutsch, aktuell (Reform 1996)
'de-1996': 0, # Alias
'de-1901': 1, # "traditionell" (Reform 1901)
'de-CH': 2, # ohne ß (Schweiz oder versal) "aktuell"
'de-x-versal': 2, # Alias
'de-1996-x-versal': 2, # Alias
'de-1901-x-versal': 3, # ohne ß (Schweiz oder versal) "traditionell"
'de-CH-1901': 4, # ohne ß (Schweiz) "traditionell" ("süssauer")
}</pre>
</div>
<div class="section" id="id6">
<h3><a class="toc-backref" href="#id42">ersatzfelder</a></h3>
<p>Felder können weggelassen werden, wenn sich die getrennten Wörter über
<a class="reference internal" href="#transformationen">Transformationen</a> gewinnen lassen.</p>
<p>Die folgenden Tupel listen die Ersatzfelder für das ensprechende
Originalfeld.</p>
<p>Bsp: Ersatz-Felder für ‚de-CH-1901‘:</p>
<pre class="code python doctest">>>> for i in ShortEntry.ersatzfelder[ShortEntry.feldindizes['de-CH-1901']]:
... print ShortEntry.feldnamen[i]
de-1901
de
</pre>
<pre class="literal-block"># Ersatzindizes Index Name
ersatzfelder = (tuple(), # 0 'de'
(0,), # 1 'de-1901'
(0,), # 2 'de-CH'
(1, 0), # 3 'de-1901-x-versal'
(1, 0), # 4 'de-CH-1901'
)</pre>
</div>
</div>
<div class="section" id="id7">
<h2><a class="toc-backref" href="#id43">Initialisierung</a></h2>
<p>Das Argument <cite>line</cite> ist eine Zeichenkette (<cite>string</cite>, <cite>unicode</cite>) in
<a class="reference internal" href="#kurzform">Kurzform</a> oder eine Instanz der Klasse <a class="reference internal" href="#wordentry">WordEntry</a>.</p>
<p>Optionale Felder bleiben erhalten.
TODO: <cite>prune</cite> auch für Strings, was als default?</p>
<pre class="code python doctest">>>> dst = ShortEntry(u'Diens-te;Dien-ste')
>>> print dst
Diens-te;Dien-ste
>>> fluss = ShortEntry(u'Fluss;Fluß')
>>> print unicode(fluss)
Fluss;Fluß
>>> tpp = ShortEntry(u'Ur<laubs=tipp;-2-')
>>> print tpp
Ur<laubs=tipp;-2-
>>> drs = unicode(ShortEntry(u'-1-;Dreß'))
>>> print drs
-1-;Dreß
>>> print ShortEntry(u'# Testkommentar')
# Testkommentar
</pre>
<p>Wird dem Konstruktor eine <a class="reference internal" href="#wordentry">WordEntry</a>-Instanz übergeben, so wird diese in das
Kurzformat überführt:</p>
<pre class="code python doctest">>>> print abenddienste
Abenddienste;-2-;Abend=dien-ste;Abend=diens-te
>>> print ShortEntry(abenddienste)
Abend=diens-te
>>> print urlaubstipp
Urlaubstipp;-2-;-3-;Ur<laubs=tipp
>>> print ShortEntry(urlaubstipp)
Ur<laubs=tipp;-2-
>>> dress = WordEntry(u'Dress;Dress # engl.')
>>> print ShortEntry(dress)
Dress;Dress # engl.
>>> dresz = WordEntry(u'Dreß;-2-;Dreß;-4-')
>>> print unicode(ShortEntry(dresz))
-1-;Dreß;-3-;-4-;-5-
>>> bss = ShortEntry(WordEntry(u'Boss;Boss # engl.'))
>>> print bss
Boss;Boss # engl.
>>> g_ebene = WordEntry(u'Gaußebene;Gauß=ebe-ne')
>>> print unicode(ShortEntry(g_ebene))
Gauß=ebe-ne;Gauß=ebe-ne;-3-;-4-;-5-
>>> print unicode(ShortEntry(WordEntry(u'Abfalllager;-2-;-3-;Ab<fall=la-ger')))
Ab<fall=la-ger;-2-
>>> print auffrass
auffrass;-2-;-3-;-4-;auf-frass
>>> print ShortEntry(auffrass)
-1-;-2-;auf-frass;auf-frass;auf-frass
>>> fraesse = WordEntry(u'frässe;-2-;-3-;-4-;-5-;frä-sse;fräs-se;fräs-se')
>>> frs = ShortEntry(fraesse)
>>> print unicode(frs)
-1-;-2-;fräs-se;frä-sse;fräs-se
>>> print ShortEntry(WordEntry(u'Fussballliga;-2-;-3-;-4-;-5-;-6-;Fuss=ball==li-ga'))
-1-;-2-;Fuss=ball==li-ga
>>> print ShortEntry(WordEntry(u'Fussballiga;-2-;-3-;-4-;-5-;Fuss=ba{ll/ll=l}i-.ga;-7-'))
-1-;-2-;-3-;Fuss=ba{ll/ll=l}i-.ga;Fuss=ba{ll/ll=l}i-.ga
>>> messignal = WordEntry(u'Messignal;-2-;-3-;-4-;-5-;-6-;-7-;Me{ss/ss=s}i-.gnal')
>>> print unicode(ShortEntry(messignal))
-1-;-2-;-3-;-4-;Me{ss/ss=s}i-.gnal
>>> loesz = WordEntry(u'Lößboden;Löß=bo-den')
>>> print unicode(ShortEntry(loesz))
Löß=bo-den;Löß=bo-den;-3-;-4-;-5-
>>> loess = WordEntry(u'Lössboden;-2-;-3-;Löss=bo-den;Löss=bo-den')
>>> print unicode(ShortEntry(loess))
Löss=bo-den;-2-;Löss=bo-den;Löss=bo-den;Löss=bo-den
>>> print ShortEntry(WordEntry(u'Amnesty;Am-nes-ty # en.'))
Am-nes-ty;Am-nes-ty # en.
>>> print ShortEntry(WordEntry(u'# nur Kommentar'))
# nur Kommentar
</pre>
<pre class="literal-block">def __init__(self, line, delimiter=';', prune=True):
if type(line) == WordEntry:
self.comment = line.comment
self.append(line.getitem(3)) # Deutsch, aktuell (Reform 1996)
self.append(line.getitem(2)) # "traditionell" (Reform 1901)
self.append(line.getitem(6)) # ohne ß (Schweiz oder versal) "aktuell"
self.append(line.getitem(5)) # ohne ß (Schweiz oder versal) "traditionell"
self.append(line.getitem(7)) # ohne ß (Schweiz) "traditionell" ("süssauer")
# Felder zusammenfassen
if prune:
self.prune()
else:
WordEntry.__init__(self, line, delimiter)</pre>
</div>
<div class="section" id="id8">
<h2><a class="toc-backref" href="#id44">key()</a></h2>
<p>Gib einen Schlüssel (ungetrenntes Wort) zurück.</p>
<p>Bei Einträgen im Kurzformat ist der Schlüssel nicht eindeutig: durch
<a class="reference internal" href="#transformationen">Transformationen</a> kann ein Wort in verschiedenen Schreibungen vorkommen.</p>
<p>Standardmäßig wird das erste nichtleere Feld ohne Trennzeichen, bei Angabe
des optionalen Arguments <span class="docutils literal">lang</span> die Schreibweise in dieser Rechtschreibung
verwendet.</p>
<pre class="code python doctest">>>> print fluss.key()
Fluss
>>> print ShortEntry(u'-1-;Dreß').key()
Dreß
</pre>
<p>Die Key-Auswahl kann über das <cite>lang</cite> Argument gesteuert werden:</p>
<pre class="code python doctest">>>> print ShortEntry(u'-1-;Dreß').key('de-CH-1901')
Dress
</pre>
<pre class="literal-block">def key(self, lang=None):
"""Erstelle einen Schlüssel (ungetrenntes Wort)."""
if lang:
return join_word(self.get(lang))
for f in self:
if f:
return join_word(f)
return u''</pre>
</div>
<div class="section" id="getitem-get">
<h2><a class="toc-backref" href="#id45">getitem, get()</a></h2>
<p>Gib Trennmuster für Sprachvariante zurück (ggf. über <a class="reference internal" href="#transformationen">Transformationen</a>).</p>
<p>Beispiele:</p>
<p>ohne Transformation</p>
<pre class="code python doctest">>>> aalbst.get('de')
u'Aal=be<stand'
>>> aalbst.get('de-1996')
u'Aal=be<stand'
>>> aalbst.get('de-1901')
u'Aal=be<stand'
>>> aalbst.get('de-x-versal')
u'Aal=be<stand'
>>> aalbst.get('de-1901-x-versal')
u'Aal=be<stand'
>>> aalbst.get('de-1996-x-versal')
u'Aal=be<stand'
>>> aalbst.get('de-CH-1901')
u'Aal=be<stand'
</pre>
<p>st und ck:</p>
<pre class="code python doctest">>>> print dst.get('de'), dst.get('de-1901'), dst.get('de-1996')
Diens-te Dien-ste Diens-te
>>> print ShortEntry(u'Es-te').get('de-1901')
Este
>>> sck = ShortEntry(u'Stre-cke')
>>> print sck.get('de'), sck.get('de-1901')
Stre-cke Stre{ck/k-k}e
</pre>
<p>Versalschreibung:</p>
<pre class="code python doctest">>>> abus = ShortEntry(u'ab<bü-ßen')
>>> print abus.get('de'), abus.get('de-CH')
ab<bü-ßen ab<büs-sen
>>> print abus.get('de-1901-x-versal'), abus.get('de-CH-1901')
ab<bü-ssen ab<büs-sen
</pre>
<pre class="code python doctest">>>> print ShortEntry(u'passt').get('de-1901')
paßt
>>> print ShortEntry(u'passt').get('de-1901-x-versal')
passt
>>> rs = ShortEntry(u'-1-;-2-;Russ') # versal für Ruß
>>> print rs.get('de-x-versal')
Russ
>>> rs.get('de-1901-x-versal')
u''
</pre>
<pre class="code python doctest">>>> ssr = ShortEntry(u'süß=sau-er')
>>> print ssr.get('de-CH'), ssr.get('de-1901-x-versal'), ssr.get('de-CH-1901')
süss=sau-er süss=sau-er sü{ss/ss=s}au-er
</pre>
<pre class="code python doctest">>>> ShortEntry(u'Pro<zess=en-.de;Pro<zeß=en-de;Pro<zess=en-.de').get('de-CH-1901')
u'Pro<zess=en-.de'
>>> pstr = ShortEntry(u'Pass=stra-ße')
>>> print pstr.get('de-1996'), pstr.get('de-1901')
Pass=stra-ße Paß=stra-ße
>>> print pstr.get('de-x-versal'), pstr.get('de-1901-x-versal')
Pass=stras-se Pass=stra-sse
</pre>
<p>Test: Wenn keine Ersatzschreibung vorliegt, wird auch in traditioneller
Versalschreibung s-s getrennt:</p>
<pre class="code python doctest">>>> print ShortEntry(u'Bu-ße').get('de-1901-x-versal')
Bu-sse
>>> print ShortEntry(u'Bus-se').get('de-1901-x-versal')
Bus-se
</pre>
<pre class="literal-block">def getitem(self, i):
"""Return item ``i`` or a subsititute"""
try:
return self[i]
except IndexError: # Feld i nicht vorhanden
pass
# Transformationen anwenden
for _i in self.ersatzfelder[i]:
try:
word = self[_i]
except IndexError: # Feld i nicht vorhanden
continue # nächsten `tag` versuchen
if not word: # "ausgekreuzt"
return u'' # nicht ableiten
# if '1901' in lang and ersatz_lang == 'de':
if i in (1, 3, 4) and _i == 0:
word = ableitung1901(word)
# if ('-CH' in lang) or ('x-versal' in lang) and (u'ß' in word):
if i > 1 and (u'ß' in word):
word = versalschreibung(word, self.feldnamen[i])
return word
return u''</pre>
<p>Geerbt von <a class="reference internal" href="#wordentry-get">WordEntry.get()</a>.</p>
</div>
<div class="section" id="id9">
<h2><a class="toc-backref" href="#id46">complete(), completed()</a></h2>
<p>Felder für alle Sprachvarianten ausfüllen</p>
<pre class="code python doctest">>>> dst.complete()
>>> print dst
Diens-te;Dien-ste;Diens-te;Dien-ste;Dien-ste
>>> aalbst.complete()
>>> print aalbst
Aal=be<stand;Aal=be<stand;Aal=be<stand;Aal=be<stand;Aal=be<stand # Test
>>> abus.complete()
>>> print unicode(abus)
ab<bü-ßen;ab<bü-ßen;ab<büs-sen;ab<bü-ssen;ab<büs-sen
>>> bss.complete()
>>> print unicode(bss)
Boss;Boss;Boss;Boss;Boss # engl.
>>> frs.complete()
>>> print unicode(frs)
-1-;-2-;fräs-se;frä-sse;fräs-se
>>> tpp.complete()
>>> print tpp
Ur<laubs=tipp;-2-;Ur<laubs=tipp;-4-;-5-
</pre>
<pre class="code python doctest">>>> ShortEntry(u'-1-;-2-;fräs-se').completed()
[u'', u'', u'fr\xe4s-se', u'', u'']
>>> print unicode(pstr.completed())
Pass=stra-ße;Paß=stra-ße;Pass=stras-se;Pass=stra-sse;Pass=stras-se
</pre>
<pre class="literal-block">def complete(self):
if len(self) == 5: # schon ausführlich
return
fields = ((i, self.getitem(i)) for i in range(len(self), 5))
for i, field in fields:
self.append(field)</pre>
</div>
<div class="section" id="id10">
<h2><a class="toc-backref" href="#id47">prune()</a></h2>
<p>Eintrag kürzen.</p>
<p>Felder für Sprachvarianten zusammenfassen, wenn sich der Inhalt durch
<a class="reference internal" href="#transformationen">Transformationen</a> gewinnen läßt:</p>
<pre class="code python doctest">>>> aalbst.prune()
>>> print aalbst
Aal=be<stand # Test
>>> dst.prune()
>>> print dst
Diens-te
>>> abus.prune()
>>> print unicode(abus)
ab<bü-ßen
>>> bss.prune()
>>> print unicode(bss)
Boss;Boss # engl.
>>> tpp.prune()
>>> print tpp
Ur<laubs=tipp;-2-
</pre>
<p>Wenn ein Wort in „traditioneller“ Rechtschreibung nicht existiert, reicht
das „Auskreuzen“ von Feld 2:</p>
<pre class="code python doctest">>>> entry = ShortEntry(u'Tipp;-2-;Tipp;-4-;-5-')
>>> entry.prune()
>>> print entry
Tipp;-2-
</pre>
<p>Wenn ein Wort in aktueller Rechtschreibung nicht existiert, reicht das
„Auskreuzen“ von Feld 1:</p>
<pre class="code python doctest">>>> entry = ShortEntry(u'-1-;Rauh=nacht;-3-;Rauh=nacht')
>>> entry.prune()
>>> print entry
-1-;Rauh=nacht
</pre>
<p>Felder werden nicht gekürzt, wenn die Rekonstruktion einen anderen Wert
ergäbe:</p>
<pre class="code python doctest">>>> frs.prune()
>>> print unicode(frs)
-1-;-2-;fräs-se;frä-sse;fräs-se
</pre>
<p>Das gilt auch für ausgekreuzte Einträge</p>
<pre class="code python doctest">>>> entry = ShortEntry(u'-1-;Dreß;-3-;-4-;-5-')
>>> entry.prune()
>>> print unicode(entry)
-1-;Dreß;-3-;-4-;-5-
</pre>
<p>und als ungünstig markierte Trennstellen:</p>
<pre class="code python doctest">>>> entry = ShortEntry(u'hun-dert=ers-ter;hun-dert=er-.ster')
>>> entry.prune()
>>> print unicode(entry)
hun-dert=ers-ter;hun-dert=er-.ster
</pre>
<pre class="literal-block">def prune(self):
if len(self) == 1: # bereits kompakt
return
for i in range(len(self)-1, 0, -1):
wort = self.pop()
rekonstruktion = self.getitem(i)
if wort != rekonstruktion:
# print tag, repr(self), wort, rekonstruktion
self.append(wort)
return
if len(self) == 1 and not self[0]:
self.pop()</pre>
</div>
<div class="section" id="id11">
<h2><a class="toc-backref" href="#id48">merge()</a></h2>
<p>Einträge zusammenlegen.</p>
<p>Das als Argument übergebene WordEntry Objekt wird in dem eigenen Eintrag
eingegliedert.</p>
<p>„Ausgekreuzte“ Felder werden überschrieben:</p>
<pre class="code python doctest">>>> entry = ShortEntry(u'be<wusst;-2-')
>>> entry.merge(ShortEntry(u'-1-;be<wußt'))
>>> print unicode(entry)
be<wusst
</pre>
<p>Identische Felder bleiben erhalten. Alle Felder die über <a class="reference internal" href="#transformationen">Transformationen</a>
rekonstruiert werden können werden entfernt (es sei den die Option
<span class="docutils literal">prune</span> ist <span class="docutils literal">False</span>).</p>
<pre class="code python doctest">>>> entry = ShortEntry(u'Maß=nah-me # < nehmen')
>>> entry.merge(ShortEntry(u'-1-;-2-;Mass=nah-me'))
>>> print unicode(entry)
Maß=nah-me # < nehmen
>>> entry = ShortEntry(u'-1-;-2-;Mass=nah-me')
>>> entry.merge(ShortEntry(u'Maß=nah-me # < nehmen'))
>>> print unicode(entry)
Maß=nah-me # < nehmen
</pre>
<p>Bei Konflikten wird ein AssertionError erzeugt:</p>
<pre class="code python doctest">>>> entry = ShortEntry(u'be<wusst;-2-')
>>> entry.merge(ShortEntry(u'-1-;-2-;ver<bor-gen'))
Traceback (most recent call last):
...
AssertionError: Merge Error:
be<wusst;-2-;be<wusst;-4-;-5-
-1-;-2-;ver<bor-gen;-4-;-5-
</pre>
<p>Geerbt von <a class="reference internal" href="#wordentry-merge">WordEntry.merge()</a></p>
</div>
<div class="section" id="wordentries">
<h2><a class="toc-backref" href="#id49">wordentries()</a></h2>
<p>Umwandeln in die <a class="reference internal" href="#langform">Langform</a>.</p>
<p>Gibt eine Liste mit <a class="reference internal" href="#wordentry">WordEntry</a> Instanzen zurück (denn aus einem <a class="reference internal" href="#shortentry">ShortEntry</a>
kann mehr als ein <a class="reference internal" href="#wordentry">WordEntry</a> entstehen).</p>
<pre class="code python doctest">>>> entry = ShortEntry(u'Mas-se')
>>> entry.wordentries()
[[u'Masse', u'Mas-se']]
</pre>
<p>Eine Hilfsfunktion vereinfacht die folgenden Tests:</p>
<pre class="code python doctest">>>> def print_langform(line, prune=True):
... for e in ShortEntry(line).wordentries(prune):
... print unicode(e)
</pre>
<p>Bei gleicher Schreibung des ungetrennten Wortes in allen Feldern enthält der
Rückgabewert nur einen Eintrag.</p>
<pre class="code python doctest">>>> print_langform(u'ba-den')
baden;ba-den
>>> print_langform(u'Wes-te')
Weste;-2-;We-ste;Wes-te
>>> print_langform(u'Toll-patsch;-2-')
Tollpatsch;-2-;-3-;Toll-patsch
>>> print_langform(u'-1-;rau-he')
rauhe;-2-;rau-he;-4-
</pre>
<p>Bei variabler Schreibung (Dreikonsonantenregel, ß-Ersatzschreibung)
enthält das Resultat bis zu vier Einträge:</p>
<pre class="code python doctest">>>> print_langform(u'Fall=laub # Dreikonsonantenregel')
Falllaub;-2-;-3-;Fall=laub # Dreikonsonantenregel
Fallaub;-2-;Fa{ll/ll=l}aub;-4- # Dreikonsonantenregel
</pre>
<pre class="code python doctest">>>> print_langform(u'Ab<guss')
Abguss;-2-;-3-;Ab<guss;Ab<guss
Abguß;-2-;Ab<guß;-4-
</pre>
<pre class="code python doctest">>>> print_langform(u'groß')
groß;groß
gross;-2-;-3-;-4-;gross
</pre>
<pre class="code python doctest">>>> print_langform(u'gro-ßen')
großen;gro-ßen
grossen;-2-;-3-;-4-;-5-;gro-ssen;gros-sen;gros-sen
</pre>
<pre class="code python doctest">>>> print_langform(u'ab<bü-ßen')
abbüßen;ab<bü-ßen
abbüssen;-2-;-3-;-4-;-5-;ab<bü-ssen;ab<büs-sen;ab<büs-sen
</pre>
<pre class="code python doctest">>>> print_langform(u'Pro<zess=en-.de;Pro<zeß=en-de;Pro<zess=en-.de')
Prozessende;-2-;-3-;Pro<zess=en-.de;Pro<zess=en-.de
Prozeßende;-2-;Pro<zeß=en-de;-4-
</pre>
<pre class="code python doctest">>>> print_langform(u'Pass=sys-tem')
Passsystem;-2-;-3-;Pass=sys-tem;-5-;Pass=sy-stem;Pass=sys-tem;-8-
Paßsystem;-2-;Paß=sy-stem;-4-
Passystem;-2-;-3-;-4-;-5-;-6-;-7-;Pa{ss/ss=s}y-.stem
</pre>
<pre class="code python doctest">>>> print_langform(u'Press=saft')
Presssaft;-2-;-3-;Press=saft;-5-;Press=saft;Press=saft;-8-
Preßsaft;-2-;Preß=saft;-4-
Pressaft;-2-;-3-;-4-;-5-;-6-;-7-;Pre{ss/ss=s}aft
</pre>
<pre class="code python doctest">>>> print_langform(u'Pass=stra-ße')
Passstraße;-2-;-3-;Pass=stra-ße
Paßstraße;-2-;Paß=stra-ße;-4-
Passstrasse;-2-;-3-;-4-;-5-;Pass=stra-sse;Pass=stras-se;Pass=stras-se
</pre>
<pre class="code python doctest">>>> print_langform(u'süß=sau-er')
süßsauer;süß=sau-er
süsssauer;-2-;-3-;-4-;-5-;süss=sau-er;süss=sau-er;-8-
süssauer;-2-;-3-;-4-;-5-;-6-;-7-;sü{ss/ss=s}au-er
</pre>
<pre class="code python doctest">>>> print_langform(u'Pro<gramm==maß=nah-me')
Programmmaßnahme;-2-;-3-;Pro<gramm==maß=nah-me
Programmaßnahme;-2-;Pro<gra{mm/mm==m}aß=nah-me;-4-
Programmmassnahme;-2-;-3-;-4-;-5-;-6-;Pro<gramm==mass=nah-me
Programmassnahme;-2-;-3-;-4-;-5-;Pro<gra{mm/mm==m}ass=nah-me;-7-
</pre>
<p>Wenn in aktueller Rechtschreibung Varianten zugelassen sind, können sich die
Ergebnisse verschiedener Kurzeinträge „kreuzen“. Sie sollten sich mit
<a class="reference internal" href="#wordentry-merge">WordEntry.merge()</a> vereinen lassen (vergleiche <span class="docutils literal">umformatierung.py</span>):</p>
<pre class="code python doctest">>>> print_langform(u'Spaß')
Spaß;Spaß
Spass;-2-;-3-;-4-;Spass
>>> print_langform(u'Spass')
Spass;-2-;-3-;Spass;Spass
Spaß;-2-;Spaß;-4-
</pre>
<p>Ausnahmen der <a class="reference internal" href="#transformationen">Transformationen</a> bleiben erhalten:</p>
<pre class="code python doctest">>>> print_langform(u'Boss;Boss # engl.')
Boss;Boss # engl.
>>> print_langform(u'Biss;-2-')
Biss;-2-;-3-;Biss
>>> print_langform(u'Es-ther;Esther # Name < hebr.')
Esther;-2-;Esther;Es-ther # Name < hebr.
</pre>
<pre class="code python doctest">>>> print_langform(u'Abend=dress;Abend=dress')
Abenddress;Abend=dress
>>> print_langform(u'-1-;Abend=dreß')
Abenddreß;-2-;Abend=dreß;-4-
Abenddress;-2-;-3-;-4-;-5-;Abend=dress;-7-
</pre>
<p>Nur Versalschreibung:</p>
<pre class="code python doctest">>>> print_langform(u'-1-;-2-;Fuss;Fuss;Fuss')
Fuss;-2-;-3-;-4-;Fuss
>>> line = u'Fussballiga;-2-;-3-;-4-;-5-;Fuss=ba{ll/ll=l}i-.ga'
>>> print ShortEntry(WordEntry(line), prune=False)
-1-;-2-;-3-;Fuss=ba{ll/ll=l}i-.ga;Fuss=ba{ll/ll=l}i-.ga
>>> print_langform(u'-1-;-2-;-3-;Fuss=ba{ll/ll=l}i-.ga;Fuss=ba{ll/ll=l}i-.ga')
Fussballiga;-2-;-3-;-4-;-5-;Fuss=ba{ll/ll=l}i-.ga;-7-
>>> print_langform(u'-1-;-2-;Fuss=ball==li-ga')
Fussballliga;-2-;-3-;-4-;-5-;-6-;Fuss=ball==li-ga
</pre>
<p>Nur Kommentar:</p>
<pre class="code python doctest">>>> print_langform(u'# holla')
# holla
</pre>
<pre class="literal-block">def wordentries(self, prune=True):
if not self and self.comment: # leerer Kommentar
return [WordEntry(u'# '+self.comment)]
entries = [] # liste von WordEntry Einträgen
keys = {} # list-index des Eintrags mit Schlüssel key
# Zuordnung der Indizes: ShortEntry[s] == WordEntry[l]
indices = (3, 2, 6, 5, 7)
for s,l in enumerate(indices):
# print s,l
word = self.getitem(s)
if not word: # unklar wo einzutragen da kein passender Schlüssel
continue # -> überspringen.
key = join_word(word)
# Felder mit gleichem Schlüssel in eine WordEntry Instanz:
try:
entry = entries[keys[key]]
except KeyError:
# neuen Eintrag mit Schlüssel und Kommentar erzeugen:
entry = WordEntry(key)
entry.comment = self.comment
keys[key] = len(entries)
entries.append(entry)
# Eintrag in entry[j]:
entry.setitem(l, word)
# Auffüllen und Komprimieren
for entry in entries:
while len(entry) < 8:
entry.append(u'')
if prune:
entry.prune()
return entries</pre>
</div>
</div>
<div class="section" id="funktionen">
<h1><a class="toc-backref" href="#id50">Funktionen</a></h1>
<div class="section" id="transformationen">
<h2><a class="toc-backref" href="#id51">Transformationen</a></h2>
<div class="section" id="ableitung1901">
<h3><a class="toc-backref" href="#id52">ableitung1901()</a></h3>
<p>Ableitung von de-1901 aus de-1996 (Reversion der Reform 1996).</p>
<p>Mit keep_key == True werden nur Änderungen vorgenommen, die die
Schreibweise des ungetrennten Wortes nicht verändern.</p>
<pre class="code python doctest">>>> from wortliste import ableitung1901
</pre>
<pre class="literal-block">def ableitung1901(wort, keep_key=False):</pre>
<div class="section" id="trennregelanderungen">
<h4><a class="toc-backref" href="#id53">Trennregeländerungen</a></h4>
<p>Diese Regeln ändern nicht das Wort, nur die Trennmöglichkeiten.</p>
<ol class="arabic">
<li><p>Trenne nie st: Ersetze ‚s-t‘ mit u‘-st‘.</p>
<pre class="code python doctest">>>> ableitung1901(u'Diens-te')
u'Dien-ste'
>>> print ableitung1901(u'wuss-te', keep_key=True)
wuss-te
</pre>
<p>Keine Trennung nach nur einem Buchstaben:</p>
<pre class="code python doctest">>>> ableitung1901(u'Es-te')
u'Este'
>>> print ableitung1901(u'Nord=os-ten')
Nord=osten
>>> print ableitung1901(u'Po-ly<es-ter')
Po-ly<ester
>>> print ableitung1901(u'the-is-tisch')
the-istisch
</pre>
<p>Trennung von s-theta „schon immer“ erlaubt:</p>
<pre class="code python doctest">>>> print ableitung1901(u'Äs-thet')
Äs-thet
</pre>
<pre class="code python doctest">>>> print ableitung1901(u'pssst') # Sonderfall: falsche Umwandlung
psßt
</pre>
</li>
<li><p>Trenne ck als k-k: Ersetze ‚-ck‘ mit ‚{ck/k-k}‘.</p>
<pre class="code python doctest">>>> ableitung1901(u'Ha-cke')
u'Ha{ck/k-k}e'
>>> ableitung1901(u'Acker')
u'A{ck/k-k}er'
>>> ableitung1901(u'Got-tes=acker')
u'Got-tes=a{ck/k-k}er'
>>> ableitung1901(u'Aal=beck')
u'Aal=beck'
>>> ableitung1901(u'be<spick-te')
u'be<spick-te'
</pre>
</li>
</ol>
<pre class="literal-block">wort = re.sub(u'(?<!s)s-t(?!h)', u'-st', wort)
wort = wort.replace(u'-ck', u'{ck/k-k}')
wort = re.sub(u'(?<=[AEIOUYÄÖÜaeiouyäöü])ck(?=[aeiouyäöü])',
u'{ck/k-k}', wort)
# keine Trennung nach nur 1 Buchstaben:
wort = re.sub(u'((?<=[=<-].)|(?<=^.))-', ur'', wort)
if keep_key:
return wort</pre>
</div>
<div class="section" id="rechtschreibanderungen">
<h4><a class="toc-backref" href="#id54">Rechtschreibänderungen</a></h4>
<p>Diese Regeln ändern die Schreibung des ungetrennten Worts (und somit den
Schlüssel im Langformat der Wortliste).</p>
<ol class="arabic" start="3">
<li><p>kein ss und sst am Wortende (ungetrenntes „ss“ nur in Ausnahmen):</p>
<p>Ersetze ‚ss‘ (evt. gefolgt von t), wenn es am Silbenende auftaucht
(vor [-=<>]) mit ß (und evt. t).</p>
<p>Aber: ‚ßt‘ und Schluss-ß auch in de-1996 möglich (langer Vokal)</p>
<pre class="code python doctest">>>> print ableitung1901(u'passt')
paßt
>>> print ableitung1901(u'Hass')
Haß
>>> print ableitung1901(u'Was-ser')
Was-ser
>>> print ableitung1901(u'Fass=brau-se')
Faß=brau-se
>>> print ableitung1901(u'wuss-te')
wuß-te
</pre>
</li>
</ol>
<pre class="literal-block">wort = re.sub(u'ss(t?)(?=[-=<>]|$)', ur'ß\1', wort)</pre>
<ol class="arabic" start="4">
<li><p>Dreikonsonantenregel:</p>
<p>Ersetze ‚mm=m‘ mit ‚{mm/mm=m}‘ (für alle Konsonanten vor Selbstlaut)</p>
<pre class="code python doctest">>>> print ableitung1901(u'Kipp=pflug')
Kipp=pflug
>>> print ableitung1901(u'Kipp=punkt')
Ki{pp/pp=p}unkt
>>> print ableitung1901(u'Ab<fall=la-ger')
Ab<fa{ll/ll=l}a-.ger
>>> print ableitung1901(u'All<lie-be')
A{ll/ll<l}ie-be
>>> print ableitung1901(u'hell>licht')
he{ll/ll>l}icht
>>> print ableitung1901(u'Pro<gramm==maß=nah-me')
Pro<gra{mm/mm==m}aß=nah-me
</pre>
</li>
</ol>
<pre class="literal-block">wort = re.sub(ur'([bfglmnprt])\1([<=>]+)\1(?=[aeiouyäöü])',
ur'{\1\1/\1\1\2\1}', wort)
# Unterdrücken der Trennung nach nur einem Buchstaben
wort = re.sub(ur'(?<=[=>].}[aeiouyäöü])([-<])\.?', ur'\1.', wort)
return wort</pre>
</div>
</div>
<div class="section" id="versalschreibung">
<h3><a class="toc-backref" href="#id55">versalschreibung()</a></h3>
<p>Ableitung von de-CH/de-x-versal (SZ-Ersatzschreibung):</p>
<pre class="code python doctest">>>> from wortliste import versalschreibung
>>> print versalschreibung(u'paßt')
passt
>>> print versalschreibung(u'bü-ßen', 'de-CH')
büs-sen
>>> print versalschreibung(u'bü-ßen', 'de-1996-x-versal')
büs-sen
>>> print versalschreibung(u'bü-ßen', 'de-CH-1901')
büs-sen
>>> print versalschreibung(u'äßen', 'de-CH-1901')
äs-sen
>>> print versalschreibung(u'auf<äßen', 'de-CH-1901')
auf<äs-sen
>>> print versalschreibung(u'auf<eßt', 'de-CH-1901')
auf<esst
>>> print versalschreibung(u'Groß=se-gel', 'de-1901-x-versal')
Gross=se-gel
>>> print versalschreibung(u'Groß=se-gel', 'de-CH-1901')
Gro{ss/ss=s}e-.gel
>>> print versalschreibung(u'Pass=sy-ste-me', 'de-CH-1901')
Pa{ss/ss=s}y-.ste-me
>>> print versalschreibung(u'Pro<zeß=en-de', 'de-CH-1901')
Pro<zess=en-.de
>>> print versalschreibung(u'Pro<zess=en-.de', 'de-CH-1901')
Pro<zess=en-.de
>>> print versalschreibung(u'Fluß==sy-stem', 'de-CH-1901')
Flu{ss/ss==s}y-.stem
>>> print versalschreibung(u'Meß==sen-der', 'de-CH-1901')
Me{ss/ss==s}en-.der
</pre>
<pre class="literal-block">def versalschreibung(wort, lang='de'):</pre>
<p>Ersetze ‚ß‘ mit ‚ss‘</p>
<pre class="literal-block">wort = wort.replace(u'ß', u'ss')</pre>
<p>Trennung von Ersatz-ss in de-CH und de-1996 nach Sprechsilbenregel:</p>
<pre class="literal-block">if '1901-x-versal' not in lang:
wort = re.sub(u'(?<=[aeiouyäöü])-\.?ss', u's-s', wort)
wort = re.sub(u'(?<=^[aeiouyäöü])ss(?=[aeiouyäöü])', u's-s', wort)
wort = re.sub(u'(?<=[=<][aeiouyäöü])ss(?=[aeiouyäöü])', u's-s', wort)</pre>
<p>Unterdrückung irreführender Trennung:</p>
<pre class="literal-block">wort = re.sub(u'ss(=+)(en|er)([<-])\.?', ur'ss\1\2\3.', wort)</pre>
<p>Dreikonsonantenregel für Ersatz-ss in de-CH-1901:</p>
<pre class="literal-block">if 'CH-1901' in lang:
wort = re.sub(u'ss(=+)s(?=[aeiouyäöü])', ur'{ss/ss\1s}', wort)
# Unterdrücken der Trennung nach nur einem Buchstaben und irreführender Trennungen
wort = re.sub(ur'(?<=[=>]s}[aeiouyäöü])([-<])\.?', ur'\1.', wort)
# wort = re.sub(ur'(?<===s}[aeiouyäöü])([-<])\.?', ur'\1.', wort) # Reißverschus=sy-.stem
wort = re.sub(u'(?<=[=>]s})(en|er)([<-])\.?', ur'\1\2.', wort)
return wort</pre>
</div>
</div>
<div class="section" id="join-word">
<h2><a class="toc-backref" href="#id56">join_word()</a></h2>
<p>Trennzeichen entfernen:</p>
<pre class="literal-block">def join_word(wort, assert_complete=False):</pre>
<p>Einfache Trennzeichen:</p>
<table>
<colgroup>
<col style="width: 3%" />
<col style="width: 97%" />
</colgroup>
<tbody>
<tr><td><p>=</p></td>
<td><p>Trennstelle an Wortfugen (Wort=fu-ge)</p></td>
</tr>
<tr><td><p><</p></td>
<td><p>Trennstelle nach Präfix (Vor<sil-be)</p></td>
</tr>
<tr><td><p>></p></td>
<td><p>Trennstelle vor Suffix (Freund>schaf-ten)</p></td>
</tr>
<tr><td><p>-</p></td>
<td><p>Nebentrennstelle (ge-hen)</p></td>
</tr>
<tr><td><p>.</p></td>
<td><p>unerwünschte/ungünstige Trennstelle (Ge<schoss=en<.er-gie)</p></td>
</tr>
</tbody>
</table>
<pre class="literal-block">table = {}
for char in u'.=-<>':
table[ord(char)] = None
key = wort.translate(table)</pre>
<p>Spezielle Trennungen für die traditionelle Rechtschreibung
(siehe ../../dokumente/README.wortliste):</p>
<pre class="literal-block">if '{' in key or '}' in key:
key = key.replace(u'{ck/kk}', u'ck')
key = key.replace(u'{ck/k', u'k')
key = key.replace(u'k}', u'k')
# Konsonanthäufungen an Wortfuge: '{xx/xxx}' -> 'xx':
key = re.sub(ur'\{(.)\1/\1\1\1\}', ur'\1\1', key)
# schon getrennt: ('{xx/xx' -> 'xx' und 'x}' -> 'x'):
key = re.sub(ur'\{(.)\1/\1\1$', ur'\1\1', key)
key = re.sub(ur'^(.)\}', ur'\1', key)</pre>
<p>Trennstellen in doppeldeutigen Wörtern:</p>
<pre class="literal-block">if '[' in key or ']' in key:
key = re.sub(ur'\[(.*)/\1\]', ur'\1', key)
# schon getrennt:
key = re.sub(ur'\[([^/\[]+)$', ur'\1', key)
key = re.sub(ur'^([^/\]]+)\]', ur'\1', key)</pre>
<p>Test auf verbliebene komplexe Trennstellen:</p>
<pre class="literal-block">if assert_complete:
for spez in u'[{/}]':
if spez in key:
raise AssertionError('Spezialtrennung %s, %s' %
(wort.encode('utf8'), key.encode('utf8')))
return key</pre>
</div>
<div class="section" id="zerlege">
<h2><a class="toc-backref" href="#id57">zerlege()</a></h2>
<p>Zerlege ein Wort mit Trennzeichen in eine Liste von Silben und eine Liste
von Trennzeichen)</p>
<pre class="code python doctest">>>> from wortliste import zerlege
</pre>
<pre class="code python doctest">>>> zerlege(u'Haupt=stel-le')
([u'Haupt', u'stel', u'le'], [u'=', u'-'])
>>> zerlege(u'Ge<samt=be<triebs=rats==chef')
([u'Ge', u'samt', u'be', u'triebs', u'rats', u'chef'], [u'<', u'=', u'<', u'=', u'=='])
>>> zerlege(u'an<stands>los')
([u'an', u'stands', u'los'], [u'<', u'>'])
>>> zerlege(u'An<al.pha-bet')
([u'An', u'al', u'pha', u'bet'], [u'<', u'.', u'-'])
</pre>
<pre class="literal-block">def zerlege(wort):
silben = re.split(u'[-·._<>=]+', wort)
trennzeichen = re.split(u'[^-·._|<>=]+', wort)
return silben, [tz for tz in trennzeichen if tz]</pre>
</div>
<div class="section" id="transfererror">
<h2><a class="toc-backref" href="#id58">TransferError</a></h2>
<p>Fehler beim Übertragen von Trennstellen mit uebertrage()_:</p>
<pre class="literal-block">class TransferError(ValueError):
def __init__(self, wort1, wort2):
msg = u'Inkompatibel: %s %s' % (wort1, wort2)
ValueError.__init__(self, msg.encode('utf8'))
def __unicode__(self):
return str(self).decode('utf8')</pre>
</div>
<div class="section" id="uebertrage">
<h2><a class="toc-backref" href="#id59">uebertrage()</a></h2>
<p>Übertrage die Trennzeichen von <cite>wort1</cite> auf <cite>wort2</cite>:</p>
<pre class="code python doctest">>>> from wortliste import uebertrage, TransferError
</pre>
<pre class="code python doctest">>>> uebertrage(u'Haupt=stel-le', u'Haupt·stel·le')
u'Haupt=stel-le'
</pre>
<p>Auch teilweise Übertragung, von „kategorisiert“ nach „unkategorisiert“:</p>
<pre class="code python doctest">>>> print uebertrage(u'Haupt=stel-le', u'Haupt=stel·le')
Haupt=stel-le
</pre>
<pre class="code python doctest">>>> print uebertrage(u'Haupt·stel-le', u'Haupt=stel·le')
Haupt=stel-le
</pre>
<pre class="code python doctest">>>> print uebertrage(u'Aus<stel-ler', u'Aus-stel-ler')
Aus<stel-ler
</pre>
<pre class="code python doctest">>>> print uebertrage(u'Freund>schaf·ten', u'Freund-schaf-ten')
Freund>schaf-ten
</pre>
<p>Übertragung doppelter Marker:</p>
<pre class="code python doctest">>>> print uebertrage(u'ver<<aus<ga-be', u'ver<aus<ga-be')
ver<<aus<ga-be
</pre>
<pre class="code python doctest">>>> print uebertrage(u'freund>lich>>keit', u'freund>lich>keit')
freund>lich>>keit
</pre>
<pre class="code python doctest">>>> print uebertrage(u'Amts==haupt=stel-le', u'Amts=haupt=stel-le')
Amts==haupt=stel-le
</pre>
<p>Kein Überschreiben doppelter Marker:
>>> print uebertrage(u’ver<aus<ga-be‘, u’ver<<aus<ga-be‘)
ver<<aus<ga-be</p>
<pre class="code python doctest">>>> print uebertrage(u'Amts=haupt=stel-le', u'Amts==haupt=stel·le')
Amts==haupt=stel-le
</pre>
<p>Erhalt des Markers für ungünstige Stellen:
>>> print uebertrage(u’An·al.pha·bet‘, u’An<al.pha-bet‘)
An<al.pha-bet</p>
<p>Keine Übertragung, wenn die Zahl oder Position der Trennstellen
unterschiedlich ist oder bei unterschiedlichen Wörtern:</p>
<pre class="code python doctest">>>> try:
... uebertrage(u'Ha-upt=stel-le', u'Haupt=stel·le')
... uebertrage(u'Haupt=ste-lle', u'Haupt=stel·le')
... uebertrage(u'Waupt=stel-le', u'Haupt=stel·le')
... except TransferError:
... pass
</pre>
<p>Übertragung auch bei unterschiedlicher Schreibung oder Position der
Trennstellen mit <cite>strict=False</cite> (für Abgleich zwischen Sprachvarianten):</p>
<pre class="code python doctest">>>> uebertrage(u'er-ster', u'ers·ter', strict=False)
u'ers-ter'
>>> uebertrage(u'Fluß=bett', u'Fluss·bett', strict=False)
u'Fluss=bett'
>>> uebertrage(u'ab>bei-ßen', u'ab>beis·sen', strict=False)
u'ab>beis-sen'
>>> print uebertrage(u'Aus<tausch=dien-stes', u'Aus-tausch=diens-tes', False)
Aus<tausch=diens-tes
</pre>
<p>Auch mit <cite>strict=False</cite> muß die Zahl der Trennstellen übereinstimmen
(Ausnahmen siehe unten):</p>
<pre class="code python doctest">>>> try:
... uebertrage(u'Ha-upt=ste-lle', u'Haupt=stel·le', strict=False)
... except TransferError:
... pass
</pre>
<p>Akzeptiere unterschiedliche Anzahl von Trennungen bei st und ck nach
Selbstlaut:</p>
<pre class="code python doctest">>>> uebertrage(u'acht=ecki-ge', u'acht·e{ck/k·k}i·ge', strict=False)
u'acht=e{ck/k-k}i-ge'
>>> uebertrage(u'As-to-ria', u'Asto·ria', strict=False)
u'Asto-ria'
>>> uebertrage(u'Asto-ria', u'As·to·ria', strict=False)
u'As-to-ria'
>>> uebertrage(u'So-fa=ecke', u'So·fa=e{ck/k-k}e', strict=False)
u'So-fa=e{ck/k-k}e'
>>> uebertrage(u'Drei=ecks=ecke', u'Drei=ecks==e{ck/k-k}e', strict=False)
u'Drei=ecks==e{ck/k-k}e'
</pre>
<p>Mit <span class="docutils literal">upgrade=False</span> werden nur unspezifische Trennstellen überschrieben:</p>
<pre class="code python doctest">>>> print uebertrage(u'an=stel-le', u'an<stel·le', upgrade=False)
an<stel-le
</pre>
<pre class="code python doctest">>>> print uebertrage(u'Aus<stel-ler', u'Aus-stel-ler', upgrade=False)
Aus-stel-ler
</pre>
<pre class="code python doctest">>>> print uebertrage(u'Aus-stel-ler', u'Aus<stel-ler', upgrade=False)
Aus<stel-ler
</pre>
<pre class="code python doctest">>>> print uebertrage(u'vor<an<<stel-le', u'vor-an<stel·le', upgrade=False)
vor-an<stel-le
</pre>
<pre class="literal-block">selbstlaute = u'aeiouäöüAEIOUÄÖÜ'
def uebertrage(wort1, wort2, strict=True, upgrade=True):
silben1, trennzeichen1 = zerlege(wort1)
silben2, trennzeichen2 = zerlege(wort2)
# Prüfe strikte Übereinstimmung:
if silben1 != silben2 and strict:
if u'<' in trennzeichen1 or u'·' in trennzeichen2:
raise TransferError(wort1, wort2)
else:
return wort2
# Prüfe ungefähre Übereinstimmung:
if len(trennzeichen1) != len(trennzeichen2):
# Selbstlaut + st oder ck?
for s in selbstlaute:
if (wort2.find(s+u'{ck/k·k}') != -1 or
wort2.find(s+u'{ck/k-k}') != -1):
wort1 = re.sub(u'%sck([%s])'%(s,selbstlaute),
ur'%s-ck\1'%s, wort1)
silben1, trennzeichen1 = zerlege(wort1)
if wort2.find(s+u's·t') != -1:
wort1 = wort1.replace(s+u'st', s+u's-t')
silben1, trennzeichen1 = zerlege(wort1)
elif wort1.find(s+u's-t') != -1:
wort1 = wort1.replace(s+u's-t', s+u'st')
silben1, trennzeichen1 = zerlege(wort1)
# print u'retry:', silben1, trennzeichen1
# immer noch ungleiche Zahl an Trennstellen?
if len(trennzeichen1) != len(trennzeichen2):
raise TransferError(wort1, wort2)
# Baue wort3 aus silben2 und spezifischeren Trennzeichen:
wort3 = silben2.pop(0)
for t1,t2 in zip(trennzeichen1, trennzeichen2):
if ((t2 == u'·' and t1 != u'.') # unspezifisch
or upgrade and
((t2 in (u'-', u'<') and t1 in (u'<', u'<<', u'<=')) # Praefixe
or (t2 in (u'-', u'>') and t1 in (u'>', u'>>', u'=>')) # Suffixe
or (t2 in (u'-', u'=') and t1 in (u'=', u'==', u'===')) # W-fugen
)
):
wort3 += t1
elif t2 == u'.' and t1 not in u'·.':
wort3 += t1 + t2
else:
wort3 += t2
wort3 += silben2.pop(0)
return wort3</pre>
<p>Übertrag kategorisierter Trennstellen zwischen den Feldern aller Einträge
in <cite>wortliste</cite>:</p>
<pre class="literal-block">def sprachabgleich(entry, vorbildentry=None):
if len(entry) <= 2:
return # allgemeine Schreibung
mit_affix = None # < oder >
kategorisiert = None # kein ·
unkategorisiert = None # mindestens ein ·
gewichtet = None # == oder <= oder =>
for field in entry[1:]:
if not field: # -2-, -3-, ...
continue
if u'{' in field and u'[' in field: # Bi-ber==be[t=t/{tt/tt=t}]uch
continue # zu komplex
if u'·' in field:
unkategorisiert = field
elif u'<' in field or u'>' in field:
mit_affix = field
else:
kategorisiert = field
if u'==' in field or u'<=' in field or u'=>' in field:
gewichtet = field
if vorbildentry:
for field in vorbildentry[1:]:
if not field: # -2-, -3-, ...
continue
if u'{' in field and u'[' in field: # Bi-ber==be[t=t/{tt/tt=t}]uch
continue # zu komplex
if not mit_affix and u'<' in field or u'>' in field :
mit_affix = field
elif not kategorisiert and unkategorisiert and u'·' not in field:
kategorisiert = field
if not gewichtet and u'==' in field or u'<=' in field or u'=>' in field:
gewichtet = field
# print 've:', mit_affix, kategorisiert, unkategorisiert
if mit_affix and (kategorisiert or unkategorisiert or gewichtet):
for i in range(1,len(entry)):
if not entry[i]: # -2-, -3-, ...
continue
if u'<' not in entry[i] or u'·' in entry[i]:
try:
entry[i] = uebertrage(mit_affix, entry[i], strict=False)
except TransferError, e:
if not '/' in entry[i]:
print u'Sprachabgleich:', unicode(e)
# print mit_affix+u':', unicode(entry)
elif kategorisiert and unkategorisiert:
for i in range(1,len(entry)):
if u'·' in entry[i]:
try:
entry[i] = uebertrage(kategorisiert, entry[i], strict=False)
except TransferError, e:
print u'Sprachabgleich:', unicode(e)
# print kategorisiert, unicode(entry)
elif gewichtet:
for i in range(1,len(entry)):
if u'=' in entry[i] and not (
u'{' in entry[i] and u'[' in entry[i]):
try:
entry[i] = uebertrage(gewichtet, entry[i], strict=False)
except TransferError, e:
print u'Sprachabgleich:', unicode(e)</pre>
<p>Großschreibung in Kleinschreibung wandeln und umgekehrt</p>
<p>Diese Version funktioniert auch für Wörter mit Trennzeichen (während
str.title() nach jedem Trennzeichen wieder groß anfängt)</p>
<pre class="code python doctest">>>> from wortliste import toggle_case
>>> toggle_case(u'Ha-se')
u'ha-se'
>>> toggle_case(u'arm')
u'Arm'
>>> toggle_case(u'frei=bier')
u'Frei=bier'
>>> toggle_case(u'L}a-ger')
u'l}a-ger'
</pre>
<p>Keine Änderung bei Wörtern mit Großbuchstaben im Inneren:</p>
<pre class="code python doctest">>>> toggle_case(u'USA')
u'USA'
>>> toggle_case(u'iRFD')
u'iRFD'
</pre>
<pre class="code python doctest">>>> toggle_case(u'gri[f-f/{ff/ff')
u'Gri[f-f/{ff/ff'
>>> toggle_case(u'Gri[f-f/{ff/ff')
u'gri[f-f/{ff/ff'
</pre>
<pre class="literal-block">def toggle_case(wort):
try:
key = join_word(wort, assert_complete=True)
except AssertionError:
key = wort[0]
if key.istitle():
return wort.lower()
elif key.islower():
return wort[0].upper() + wort[1:]
else:
return wort</pre>
</div>
</div>
<div class="section" id="sortierschlussel">
<h1><a class="toc-backref" href="#id60">Sortierschlüssel</a></h1>
<p>Duden-Sortierung für die Wortliste</p>
<pre class="code python doctest">>>> from wortliste import sortkey_duden
>>> sortkey_duden([u"Abflußröhren"])
u'abflussrohren a*bflu*szroehren'
>>> sortkey_duden([u"Abflußrohren"])
u'abflussrohren a*bflu*szro*hren'
>>> sortkey_duden([u"Abflussrohren"])
u'abflussrohren'
</pre>
<pre class="code python doctest">>>> s = sorted([[u"Abflußröhren"], [u"Abflußrohren"], [u"Abflussrohren"]],
... key=sortkey_duden)
>>> print ', '.join(e[0] for e in s)
Abflussrohren, Abflußrohren, Abflußröhren
</pre>
<p>Umschreibung</p>
<p>Ligaturen auflösen und andere „normalisierunde“ Ersetzungen für den
(Haupt-)Sortierschlüssel (Akzente werden über <span class="docutils literal">unicodedata.normalize</span>
entfernt):</p>
<pre class="literal-block">umschrift_skey = {
ord(u'æ'): u'ae',
ord(u'œ'): u'oe',
ord(u'ſ'): u's',
}</pre>
<p>„Zweitschlüssel“ zur Unterscheidung von Umlauten/SZ und Basisbuchstaben:</p>
<pre class="literal-block">umschrift_subkey = {
ord(u'a'): u'a*',
ord(u'å'): u'aa',
ord(u'ä'): u'ae',
ord(u'o'): u'o*',
ord(u'ö'): u'oe',
ord(u'ø'): u'oe',
ord(u'u'): u'u*',
ord(u'ü'): u'ue',
ord(u'ß'): u'sz',
}</pre>
<div class="section" id="sortkey-duden">
<h2><a class="toc-backref" href="#id61">sortkey_duden()</a></h2>
<p>Schlüssel für die alphabetische Sortierung gemäß Duden-Regeln.</p>
<p>Argument ist ein Eintrag im WordEntry oder ShortEntry Format oder
ein (Unicode) String:</p>
<pre class="code python doctest">>>> print sortkey_duden(weste) # WordEntry
weste
>>> print sortkey_duden(dst) # ShortEntry
dienste
</pre>
<pre class="code python doctest">>>> print sortkey_duden(u'Stra-ße')
strasse stra*sze
>>> print sortkey_duden([u'Büh-ne'])
buhne buehne
>>> print sortkey_duden(u'Weiß=flog;Weiß=flog;-3-;-4-;-5-')
weissflog weiszflo*g
>>> print sortkey_duden(u'-1-;Meß=sen-der;-3-;-4-;-5-')
messsender meszsender
>>> print sortkey_duden(u'As-sen # (geogr. und Eigen-) Name\n')
assen
>>> print sortkey_duden(u'aßen;aßen;-3-;-4-;-5-\n')
assen a*szen
>>> print sortkey_duden(u'äßen\n')
assen aeszen
</pre>
<pre class="literal-block">def sortkey_duden(entry):</pre>
<p>ggf. ungetrenntes Wort extrahieren oder generieren:</p>
<pre class="literal-block">if isinstance(entry, list):
try:
key = entry.key()
except AttributeError:
key = entry[0]
if len(entry) == 1: # ein Muster pro Zeile, siehe z.B. pre-1901
key = join_word(key)
else:
match = re.search(u'^[-0-9;]*([^;\s]+)', entry) # erstes volles Feld
if match:
key = match.group(1)
else:
key = u''
key = join_word(key)
key = re.sub(u'[0-9;]', ur'', key)</pre>
<p>Großschreibung ignorieren:</p>
<p>Der Duden sortiert Wörter, die sich nur in der Großschreibung unterscheiden
„klein vor groß“ (ASCII sortiert „groß vor klein“). In der
<cite>Trennmuster-Wortliste</cite> kommen Wörter nur mit der häufiger anzutreffenden
Großschreibung vor, denn der TeX-Trennalgorithmus ignoriert Großschreibung.</p>
<pre class="literal-block">key = key.lower()</pre>
<p>Ersetzungen:</p>
<p>ß -> ss</p>
<pre class="literal-block">skey = key.replace(u'ß', u'ss')</pre>
<p>Restliche Akzente weglassen: Wandeln in Darstellung von Buchstaben mit
Akzent als „Grundzeichen + kombinierender Akzent“. Anschließend alle
nicht-ASCII-Zeichen ignorieren:</p>
<pre class="literal-block">skey = skey.translate(umschrift_skey)
skey = unicodedata.normalize('NFKD', skey)
skey = unicode(skey.encode('ascii', 'ignore'))</pre>
<p>„Zweitschlüssel“ für das eindeutige Einsortieren von Wörtern mit
gleichem Schlüssel (Masse/Maße, waren/wären, …):</p>
<ul class="simple">
<li><p>„*“ nach aou für die Unterscheidung Grund-/Umlaut</p></li>
<li><p>ß->sz</p></li>
</ul>
<pre class="literal-block">if key != skey:
subkey = key.translate(umschrift_subkey)
skey = u'%s %s' % (skey,subkey)</pre>
<p>Gib den Sortierschlüssel zurück:</p>
<pre class="literal-block">return skey</pre>
</div>
<div class="section" id="udiff">
<h2><a class="toc-backref" href="#id62">udiff()</a></h2>
<p>Vergleiche zwei Sequenzen von <cite>WordEntries</cite> (genauer: alle Objekte, die
sich sinnvoll zu Unicode wandeln lassen).</p>
<p>Beispiel:</p>
<pre class="code python doctest">>>> from wortliste import udiff
>>> print udiff([abbeissen, aalbestand], [abbeissen,dresz], 'alt', 'neu')
--- alt
+++ neu
@@ -1,2 +1,2 @@
abbeissen;-2-;-3-;-4-;-5-;test;ab<beis-sen;ab<beis-sen
-Aalbestand;Aal=be<stand # Test
+Dreß;-2-;Dreß;-4-
<BLANKLINE>
>>> udiff([abbeissen, aalbestand], [abbeissen, aalbestand], 'alt', 'neu')
u''
</pre>
<pre class="literal-block">def udiff(a, b, fromfile='', tofile='',
fromfiledate='', tofiledate='', n=1, encoding='utf8'):
a = [unicode(entry).rstrip().encode(encoding) for entry in a]
b = [unicode(entry).rstrip().encode(encoding) for entry in b]
diff = '\n'.join(difflib.unified_diff(a, b, fromfile, tofile,
fromfiledate, tofiledate, n, lineterm=''))
if diff:
diff += '\n'
return diff.decode(encoding)</pre>
</div>
</div>
<div class="section" id="sprachtags">
<h1><a class="toc-backref" href="#id63">Sprachtags</a></h1>
<p>Normalisierung und Expansion von Sprachtags nach <a class="citation-reference" href="#bcp47" id="id12">[BCP47]</a></p>
<pre class="code python doctest">>>> from wortliste import normalize_language_tag
>>> normalize_language_tag('de_AT-1901')
['de-AT-1901', 'de-AT', 'de-1901', 'de']
</pre>
<pre class="code python doctest">>>> normalize_language_tag('de') # Deutsch, allgemeingültig
['de']
>>> normalize_language_tag('de_1901') # traditionell (Reform 1901)
['de-1901', 'de']
>>> normalize_language_tag('de_1996') # reformiert (Reform 1996)
['de-1996', 'de']
>>> normalize_language_tag('de_CH') # ohne ß (Schweiz oder versal)
['de-CH', 'de']
>>> normalize_language_tag('de-x-versal') # versal
['de-x-versal', 'de']
>>> normalize_language_tag('de-1901-x-versal') # versal
['de-1901-x-versal', 'de-1901', 'de-x-versal', 'de']
>>> normalize_language_tag('de_CH-1996') # Schweiz traditionell (süssauer)
['de-CH-1996', 'de-CH', 'de-1996', 'de']
</pre>
<p>‚de‘: 1, # Deutsch, allgemeingültig
‚de-1901‘: 2, # „traditionell“ (nach Rechtschreibreform 1901)
‚de-1996‘: 3, # reformierte Reformschreibung (1996)
‚de-x-versal‘: 4, # ohne ß (Schweiz oder versal) allgemein
# ‚de-CH‘: 4, # Alias
‚de-1901-x-versal‘: 5, # ohne ß (Schweiz oder versal) „traditionell“
‚de-1996-x-versal‘: 6, # ohne ß (Schweiz oder versal) „reformiert“
# ‚de-CH-1996‘: 6, # Alias
‚de-CH-1901‘: 7, # ohne ß (Schweiz) „traditionell“ („süssauer“)</p>
<pre class="literal-block">def normalize_language_tag(tag):
"""Return a list of normalized combinations for a `BCP 47` language tag.
"""
# normalize:
tag = tag.replace('_','-')
# split (except singletons, which mark the following tag as non-standard):
tag = re.sub(r'-([a-zA-Z0-9])-', r'-\1_', tag)
taglist = []
subtags = [subtag.replace('_', '-') for subtag in tag.split('-')]
base_tag = [subtags.pop(0)]
# find all combinations of subtags
for n in range(len(subtags), 0, -1):
# for tags in unique_combinations(subtags, n):
for tags in itertools.combinations(subtags, n):
taglist.append('-'.join(base_tag+list(tags)))
taglist += base_tag
return taglist</pre>
</div>
<div class="section" id="tests">
<h1><a class="toc-backref" href="#id64">Tests</a></h1>
<p>Teste Übereinstimmung des ungetrennten Wortes in Feld 1 mit den
Trennmustern nach Entfernen der Trennmarker. Schreibe Inkonsistenzen auf die
Standardausgabe.</p>
<p>Das Argument ist ein Iterator über die Einträge (Klasse <cite>WordEntry</cite>).</p>
<pre class="literal-block">def test_keys(wortliste):
print u"Teste Schlüssel-Trennmuster-Übereinstimmung:"
is_OK = True
for entry in wortliste:
# Test der Übereinstimmung ungetrenntes/getrenntes Wort
# für alle Felder:
key = entry.key()
for wort in entry[1:]:
if not wort: # leere Felder
continue
if key != join_word(wort):
is_OK = False
print u"\nkey '%s' != join_word('%s')" % (key, wort),
if key.lower() == join_word(wort).lower():
print(u" Abgleich der Großschreibung mit"
u"`prepare-patch.py grossabgleich`."),
if is_OK:
print u"OK"</pre>
<p>Finde Doppeleinträge (teste, ob jeder Schlüssel nur einmal vorkommt).
Schreibe Inkonsistenzen auf die Standardausgabe.</p>
<p>Das Argument ist ein Iterator über die Einträge (Klasse <cite>WordEntry</cite>).</p>
<pre class="literal-block">def test_uniqueness(wortliste):
doppelte = 0
words = set()
for entry in wortliste:
key = entry.key()
if key in words:
doppelte += 1
print unicode(entry)
words.add(key)
print doppelte,
print u"Doppeleinträge (ohne Berücksichtigung der Großschreibung)."
if doppelte:
print u" Entfernen mit `prepare-patch.py doppelte`."
print u" Patch vor Anwendung durchsehen!"</pre>
<p>Teste die Wandlung einer Zeile im „wortliste“-Format in eine
<span class="docutils literal">WordEntry</span>-Instanz und zurück:</p>
<pre class="literal-block">def test_str_entry_str_conversion(wordfile):
OK = 0
for line in file(wordfile.name):
line = line.rstrip().decode(wordfile.encoding)
entry = WordEntry(line)
if line == unicode(entry):
OK +=1
else:
print u'-', line,
print u'+', unicode(entry)
print OK, u"Einträge rekonstruiert"</pre>
<p>Teste Vervollständigung und Zusammenfassung von Einträgen:</p>
<pre class="literal-block">def test_completion_pruning(entries):
reko = []
for entry in entries:
new = copy.copy(entry)
new.complete()
new.prune()
reko.append(new)
patch = udiff(entries, reko, 'wortliste', 'neu')
if patch:
print patch
else:
print u"alle Einträge rekonstruiert"</pre>
</div>
<div class="section" id="aufruf-von-der-kommandozeile">
<h1><a class="toc-backref" href="#id65">Aufruf von der Kommandozeile</a></h1>
<pre class="literal-block">if __name__ == '__main__':
import sys
# sys.stdout mit UTF8 encoding (wie in Python 3)
sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)
# sys.stderr = codecs.getwriter('UTF-8')(sys.stderr)
print u"Test der Werkzeuge und inneren Konsistenz der Wortliste\n"</pre>
<p>Ein WordFile Dateiobjekt:</p>
<pre class="literal-block">wordfile = WordFile('../../../wortliste')
print wordfile.name, u"Format", wordfile.format
# wordfile = WordFile('../../../wlst', format='auto') # wortliste im Kurzformat
# print wordfile.name, u"Format", wordfile.format
# wordfile = WordFile('neu.todo')
# print wordfile.name, u"Format", wordfile.format
# wordfile = WordFile('neu-kurz.todo', format='f5')
# print wordfile.name, u"Format", wordfile.format
# wordfile = WordFile('korrektur.todo', format='auto')
# print wordfile.name, u"Format", wordfile.format</pre>
<p>Liste der Datenfelder (die Klasseninstanz als Argument für <cite>list</cite> liefert
den Iterator über die Felder, <cite>list</cite> macht daraus eine Liste):</p>
<pre class="literal-block">wordlist = list(wordfile)
print len(wordlist), u"Einträge"</pre>
<p>Sprachauswahl:</p>
<pre class="literal-block"># Sprachtags:
#
# sprache = 'de-1901' # traditionell
sprache = 'de-1996' # Reformschreibung
# sprache = 'de-x-versal' # ohne ß (Schweiz oder versal) allgemein
# sprache = 'de-1901-x-versal' # ohne ß (Schweiz oder versal) "traditionell"
# sprache = 'de-1996-x-versal' # ohne ß (Schweiz oder versal) "reformiert"
# sprache = 'de-CH-1901' # ohne ß (Schweiz) "traditionell" ("süssauer")
#
# worte = [entry.get(sprache) for entry in wordlist]
# worte = [wort for wort in worte if wort]
# print len(worte), u"Einträge für Sprachvariante", sprache</pre>
<p>Teste Schlüssel-Trennmuster-Übereinstimmung:</p>
<pre class="literal-block"># test_keys(wordlist)</pre>
<p>Test auf Doppeleinträge:</p>
<pre class="literal-block"># test_uniqueness(wordlist)</pre>
<p>Teste Komplettieren/Zusammenfassen der Einträge:</p>
<pre class="literal-block"># test_completion_pruning(wordlist)</pre>
<p>Ein Wörterbuch (dict Instanz):</p>
<pre class="literal-block"># wordfile.seek(0) # Pointer zurücksetzen
# words = wordfile.asdict()
# print len(words), u"Wörterbucheinträge"</pre>
<p>Zeilenrekonstruktion:</p>
<pre class="literal-block"># test_str_entry_str_conversion(wordfile)</pre>
</div>
<div class="section" id="quellen">
<h1><a class="toc-backref" href="#id66">Quellen</a></h1>
<dl class="citation">
<dt class="label" id="bcp47"><span class="brackets">BCP47</span><span class="fn-backref">(<a href="#id1">1</a>,<a href="#id3">2</a>,<a href="#id12">3</a>)</span></dt>
<dd><p>A. Phillips und M. Davis, (Editoren.),
<cite>Tags for Identifying Languages</cite>, <a class="reference external" href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a></p>
</dd>
</dl>
</div>
</div>
<div class="footer">
<hr class="footer" />
<p><a class="reference external" href="wortliste.py.txt">View document source</a>.
Generated on: 2018-03-15.
</p>
</div>
</body>
</html>