FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
python-docs-de/tools/check_markup.py at 3.15 · python/python-docs-de · GitHub
python
python-docs-de
Repository navigation
Code
Issues
Pull requests
2
(2)
Actions
Security and quality
Insights
Expand file tree
Breadcrumbs
python-docs-de
/
tools
/
check_markup.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
448 lines (375 loc) · 18.3 KB
Breadcrumbs
python-docs-de
/
tools
/
check_markup.py
Copy path
File metadata and controls
448 lines (375 loc) · 18.3 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
#!/usr/bin/env python3
"""check_markup.py -- Findet Auszeichnungsfehler in deutschen .po-Uebersetzungen.
Ergaenzt check_roles.py: dort geht es um fehlende oder ueberzaehlige Rollen,
hier um Schaeden *innerhalb* der Auszeichnung, die Sphinx entweder gar nicht
meldet oder erst als Folgefehler. Die meisten stammen aus maschineller
Voruebersetzung, bei der reST-Syntax wie Fließtext behandelt wurde.
Geprueft werden acht Fehlerarten (Kuerzel fuer --art):
klammer Ueberfluessige Backtick- oder Stern-Klammer um eine Rolle:
Ein ` :class:`tuple` `, der ...
Sphinx paart Backticks von links nach rechts. Das einzelne
Backtick findet seinen Partner im oeffnenden Backtick der Rolle,
und ab da verrutscht die Paarung ueber den ganzen Satz -- alle
folgenden Querverweise werden zu gewoehnlichem Text.
anzeige Rolle ohne Anzeigetext: :term:` <parameter>`
Der sichtbare Text ist beim Uebersetzen verloren gegangen.
code Codeblock, dessen Uebersetzung ausserhalb von Kommentarzeilen
vom Original abweicht. Betrifft uebersetzte Schluesselwoerter
(">>> x ist 7"), eingedeutschte Interpreter-Ausgaben
("Traceback (letzter Aufruf zuletzt):") und Beispiele, deren
Eingabe und Ausgabe nicht mehr zueinander passen.
literal ``Literale`` aus dem Original fehlen in der Uebersetzung.
Literale sind Code und duerfen nicht uebersetzt werden.
Zusaetzliche Literale in der Uebersetzung sind erlaubt.
typo Typografische Anfuehrungszeichen innerhalb von Code oder
Literalen: "hello“ statt "hello"
verweis Benannte Hyperlink-Verweise (`Text`_ oder `Text <url>`_) fehlen
in der Uebersetzung oder haben den abschliessenden Unterstrich
verloren. Ohne ihn ist es kein Verweis mehr, sondern Kursivtext.
bindestrich Leerzeichen zwischen Rolle und angehaengtem Wort:
:exc:`GeneratorExit` -Ausnahme
Technisch harmlos, im Satz aber ein Fremdkoerper.
titel Der Seitentitel eines LaTeX-Wurzeldokuments beginnt mit
Auszeichnung:
``optparse``-Code nach ``argparse`` migrieren
Sphinx baut aus jedem HOWTO und aus jedem Wurzeldokument ein
eigenes LaTeX-Dokument. Dessen erste Ueberschrift wird zum
\\
title{} -- und dafuer verlangt der LaTeX-Writer einen reinen
Textknoten am Anfang (sphinx/writers/latex.py, visit_title).
Sonst warnt er "document title is not a single Text node", und
weil der CPython-Build mit -W laeuft, bricht er ab. Im
Fliesstext und in Zwischenueberschriften ist Auszeichnung am
Anfang dagegen unbedenklich -- nur die H1 dieser Seiten zaehlt.
Abhilfe: umformulieren, sodass der Titel mit Text beginnt
("Migration von ``optparse``-Code zu ``argparse``").
Das Skript aendert nichts. Es meldet nur, wo etwas zu tun ist -- die
Korrekturen sind oft Ermessensfragen und gehoeren von Hand entschieden.
Aufruf:
python tools/check_markup.py # ganzes Repo
python tools/check_markup.py reference library # nur diese Pfade
python tools/check_markup.py --art code,klammer # nur diese Fehlerarten
python tools/check_markup.py --max 5 # je Art hoechstens 5 Beispiele
python tools/check_markup.py -o bericht.md # Markdown-Bericht schreiben
python tools/check_markup.py --nur-zahlen # nur die Zusammenfassung
Rueckgabewert: 0 wenn nichts gefunden wurde, sonst 1 -- damit laesst sich das
Skript in pre_push_check.sh und in die CI einhaengen.
Es werden nur .po-Dateien gelesen; nichts wird geschrieben.
"""
import
argparse
import
re
import
sys
from
pathlib
import
Path
AUSSCHLUSS
=
[
".venv"
,
".git"
,
"cpython-src"
,
"__pycache__"
,
"locales"
]
# --- Fehlermuster ----------------------------------------------------------
ROLLE
=
r":[a-zA-Z][\w-]*:`"
MUSTER
=
{
"klammer"
: [
# Ein '*' direkt nach einem Wort schliesst eine Hervorhebung
# (*keine* :attr:`...`) und ist kein Fehler.
(
re
.
compile
(
r'(?<![\w*])\*[ \t]+'
+
ROLLE
),
"Stern vor Rolle"
),
(
re
.
compile
(
ROLLE
+
r'[^`]*`[ \t]*\*(?!\*)(?=[\s,.;:)])'
),
"Stern nach Rolle"
),
],
"anzeige"
: [
(
re
.
compile
(
ROLLE
+
r'[ \t]*<'
),
"Rolle ohne Anzeigetext"
),
],
"bindestrich"
: [
(
re
.
compile
(
r'(?:'
+
ROLLE
+
r'[^`]*`|``[^`]+``)[ \t]+-[A-Za-zÄÖÜäöüß]'
),
"Leerzeichen vor Bindestrich"
),
],
}
# Spans, die zu gueltiger Auszeichnung gehoeren -- alles andere ist ein
# einzelnes, "loses" Backtick.
GUELTIG
=
re
.
compile
(
r'``[^`]+``'
# ``Literal``
r'|:[a-zA-Z][\w-]*:`[^`]*`'
# :rolle:`Text`
r'|`[^`]+`__?'
# `Link <url>`_ bzw. `_
)
def
lose_klammer
(
text
:
str
)
->
str
:
"""Meldet eine ueberfluessige Backtick-Klammer um eine Rolle/ein Literal.
Gueltige Auszeichnung wird zuerst ausmaskiert. Was an Backticks uebrig
bleibt, gehoert zur Standardrolle (`x`) -- und wenn so ein Paar eine
Rolle oder ein Literal *umschliesst*, ist genau das der Schaden.
"""
maske
=
bytearray
(
len
(
text
))
spans
=
[]
for
m
in
GUELTIG
.
finditer
(
text
):
spans
.
append
((
m
.
start
(),
m
.
end
()))
for
i
in
range
(
m
.
start
(),
m
.
end
()):
maske
[
i
]
=
1
lose
=
[
i
for
i
,
z
in
enumerate
(
text
)
if
z
==
'`'
and
not
maske
[
i
]]
for
a
,
b
in
zip
(
lose
[
0
::
2
],
lose
[
1
::
2
]):
for
s
,
e
in
spans
:
if
a
<
s
and
e
<=
b
:
return
text
[
max
(
0
,
a
-
30
):
min
(
len
(
text
),
b
+
20
)].
replace
(
"
\n
"
,
" "
)
if
len
(
lose
)
%
2
:
i
=
lose
[
-
1
]
return
text
[
max
(
0
,
i
-
30
):
i
+
25
].
replace
(
"
\n
"
,
" "
)
return
""
TYPOGRAFISCH
=
"„“”‚‘’"
VERWEIS
=
re
.
compile
(
r'`[^`]+`__?(?![\w`])'
)
LITERAL
=
re
.
compile
(
r'``([^`]+)``'
)
CODE_START
=
re
.
compile
(
r'^(>>>|\.\.\.|def |class |async def |import |from )'
)
def
ist_code
(
msgid
:
str
)
->
bool
:
return
"
\n
"
in
msgid
and
bool
(
CODE_START
.
match
(
msgid
.
lstrip
()))
# --- Titel von LaTeX-Wurzeldokumenten --------------------------------------
#
# CPythons Doc/conf.py macht aus jeder Datei in latex_documents ein eigenes
# .tex -- und zusaetzlich aus *jedem* howto/*.rst ausser index.rst. Nur bei
# diesen Seiten wird die erste Ueberschrift zum \title{} und damit von
# sphinx/writers/latex.py geprueft. Alle anderen Seiten (etwa library/json)
# duerfen mit einer Rolle beginnen; dort passiert nichts.
WURZELN
=
{
"about.po"
,
"bugs.po"
,
"contents.po"
,
"glossary.po"
,
"c-api/index.po"
,
"distributing/index.po"
,
"extending/index.po"
,
"faq/index.po"
,
"installing/index.po"
,
"library/index.po"
,
"reference/index.po"
,
"tutorial/index.po"
,
"using/index.po"
,
"whatsnew/index.po"
,
}
# Auszeichnung, die einen eigenen Knoten erzeugt und deshalb nicht am
# Titelanfang stehen darf.
TITEL_AUSZEICHNUNG
=
re
.
compile
(
r'^\s*('
r'``[^`]+``'
# ``Literal``
r'|:[a-zA-Z][\w-]*:`[^`]*`'
# :rolle:`Text`
r'|`[^`]+`__?'
# `Verweis`_
r'|\*\*[^*]+\*\*'
# **fett**
r'|\*[^*]+\*'
# *kursiv*
r')'
)
def
ist_latex_wurzel
(
datei
:
Path
)
->
bool
:
teile
=
datei
.
parts
name
=
teile
[
-
1
]
ordner
=
teile
[
-
2
]
if
len
(
teile
)
>=
2
else
""
if
ordner
==
"howto"
and
name
!=
"index.po"
:
return
True
if
ordner
==
"whatsnew"
and
re
.
fullmatch
(
r"3\.\d+\.po"
,
name
):
return
True
return
name
in
WURZELN
or
f"
{
ordner
}
/
{
name
}
"
in
WURZELN
def
pruefe_titel
(
datei
:
Path
,
msgstr
:
str
)
->
list
:
"""Prueft die erste Ueberschrift eines LaTeX-Wurzeldokuments."""
if
not
ist_latex_wurzel
(
datei
):
return
[]
treffer
=
TITEL_AUSZEICHNUNG
.
match
(
msgstr
)
if
not
treffer
:
return
[]
# Besteht der Titel *nur* aus der Auszeichnung, ist es ein einzelner
# Knoten -- genau den laesst der LaTeX-Writer durchgehen.
if
not
msgstr
[
treffer
.
end
():].
strip
():
return
[]
return
[(
"titel"
,
"Seitentitel beginnt mit Auszeichnung"
,
msgstr
[:
70
].
replace
(
"
\n
"
,
" "
))]
# --- PO-Parser (bewusst ohne polib, damit das Skript ueberall laeuft) ------
ENTKOMMEN
=
{
"
\\
n"
:
"
\n
"
,
"
\\
t"
:
"
\t
"
,
"
\\
r"
:
"
\r
"
,
"
\\
\"
"
:
"
\"
"
,
"
\\
\\
"
:
"
\\
"
}
def
entkomme
(
s
:
str
)
->
str
:
aus
,
i
=
[],
0
while
i
<
len
(
s
):
if
s
[
i
]
==
"
\\
"
and
i
+
1
<
len
(
s
):
paar
=
s
[
i
:
i
+
2
]
if
paar
in
ENTKOMMEN
:
aus
.
append
(
ENTKOMMEN
[
paar
]);
i
+=
2
;
continue
aus
.
append
(
s
[
i
]);
i
+=
1
return
""
.
join
(
aus
)
def
po_eintraege
(
pfad
:
Path
):
"""Liefert (po_zeile, quelle, msgid, msgstr) je Eintrag."""
zeilen
=
pfad
.
read_text
(
encoding
=
"utf-8"
,
errors
=
"replace"
).
split
(
"
\n
"
)
i
,
n
=
0
,
len
(
zeilen
)
while
i
<
n
:
if
not
zeilen
[
i
].
startswith
((
"#"
,
"msgid"
,
"msgctxt"
)):
i
+=
1
continue
if
zeilen
[
i
].
startswith
(
"#~"
):
# obsolet
i
+=
1
continue
quelle
=
""
while
i
<
n
and
zeilen
[
i
].
startswith
(
"#"
):
if
zeilen
[
i
].
startswith
(
"#:"
)
and
not
quelle
:
quelle
=
zeilen
[
i
][
2
:].
strip
().
split
()[
0
]
if
zeilen
[
i
][
2
:].
strip
()
else
""
i
+=
1
if
i
<
n
and
zeilen
[
i
].
startswith
(
"msgctxt"
):
i
+=
1
while
i
<
n
and
zeilen
[
i
].
startswith
(
'"'
):
i
+=
1
if
i
>=
n
or
not
zeilen
[
i
].
startswith
(
"msgid"
):
i
+=
1
continue
po_zeile
=
i
+
1
def
sammle
(
start
,
schluessel
):
teile
,
j
=
[],
start
m
=
re
.
match
(
schluessel
+
r'\s+"(.*)"\s*$'
,
zeilen
[
j
])
if
m
:
teile
.
append
(
m
.
group
(
1
))
j
+=
1
while
j
<
n
and
zeilen
[
j
].
startswith
(
'"'
):
teile
.
append
(
zeilen
[
j
].
strip
()[
1
:
-
1
])
j
+=
1
return
""
.
join
(
teile
),
j
msgid
,
i
=
sammle
(
i
,
"msgid"
)
if
i
<
n
and
zeilen
[
i
].
startswith
(
"msgid_plural"
):
_
,
i
=
sammle
(
i
,
"msgid_plural"
)
if
i
>=
n
or
not
zeilen
[
i
].
startswith
(
"msgstr"
):
continue
msgstr
,
i
=
sammle
(
i
,
re
.
escape
(
"msgstr"
)
+
r'(?:\[\d+\])?'
)
if
msgid
and
msgstr
:
yield
po_zeile
,
quelle
,
entkomme
(
msgid
),
entkomme
(
msgstr
)
# --- Pruefungen ------------------------------------------------------------
def
pruefe_eintrag
(
msgid
:
str
,
msgstr
:
str
,
arten
:
set
)
->
list
:
"""Liefert [(art, beschreibung, ausschnitt), ...]."""
funde
=
[]
if
"klammer"
in
arten
and
not
ist_code
(
msgid
):
# In Codebloecken sind Backticks gewoehnlicher Text -- dort greift
# stattdessen die Pruefung "code".
schaden
=
lose_klammer
(
msgstr
)
if
schaden
and
not
lose_klammer
(
msgid
):
funde
.
append
((
"klammer"
,
"Backtick-Klammer um Rolle/Literal"
,
schaden
))
for
art
in
(
"klammer"
,
"anzeige"
,
"bindestrich"
):
if
art
not
in
arten
:
continue
for
rx
,
name
in
MUSTER
[
art
]:
tr
=
rx
.
search
(
msgstr
)
if
tr
and
not
rx
.
search
(
msgid
):
a
=
max
(
0
,
tr
.
start
()
-
35
)
funde
.
append
((
art
,
name
,
msgstr
[
a
:
tr
.
end
()
+
25
].
replace
(
"
\n
"
,
" "
)))
break
if
"verweis"
in
arten
:
a
=
len
(
VERWEIS
.
findall
(
msgid
.
replace
(
"
\n
"
,
" "
)))
b
=
len
(
VERWEIS
.
findall
(
msgstr
.
replace
(
"
\n
"
,
" "
)))
if
a
!=
b
:
funde
.
append
((
"verweis"
,
"Benannte Verweise weichen ab"
,
f"Original
{
a
}
, Uebersetzung
{
b
}
"
))
if
"literal"
in
arten
:
a
=
sorted
(
LITERAL
.
findall
(
msgid
.
replace
(
"
\n
"
,
" "
)))
b
=
sorted
(
LITERAL
.
findall
(
msgstr
.
replace
(
"
\n
"
,
" "
)))
# Nur *verlorene* Literale sind ein Fehler. Zusaetzliche Literale in
# der Uebersetzung sind meist Absicht (z. B. ein Objekttyp, den das
# Original als Flie\u00dftext fuehrt) und werden nicht gemeldet.
fehlt
=
[
x
for
x
in
a
if
x
not
in
b
]
if
fehlt
:
funde
.
append
((
"literal"
,
"Literale fehlen in der Uebersetzung"
,
f"fehlt:
{
fehlt
}
"
))
if
"code"
in
arten
and
ist_code
(
msgid
):
za
,
zb
=
msgid
.
split
(
"
\n
"
),
msgstr
.
split
(
"
\n
"
)
if
len
(
za
)
!=
len
(
zb
):
funde
.
append
((
"code"
,
"Zeilenzahl weicht ab"
,
f"
{
len
(
za
)
}
Zeilen im Original,
{
len
(
zb
)
}
in der Uebersetzung"
))
else
:
for
x
,
y
in
zip
(
za
,
zb
):
if
x
!=
y
and
"#"
not
in
x
:
funde
.
append
((
"code"
,
"Code ausserhalb von Kommentaren geaendert"
,
f"
{
x
.
strip
()[:
55
]!r
}
->
{
y
.
strip
()[:
55
]!r
}
"
))
break
if
"typo"
in
arten
:
verdaechtig
=
[]
if
ist_code
(
msgid
):
verdaechtig
=
[(
msgid
,
msgstr
)]
else
:
verdaechtig
=
[(
" "
.
join
(
LITERAL
.
findall
(
msgid
.
replace
(
"
\n
"
,
" "
))),
" "
.
join
(
LITERAL
.
findall
(
msgstr
.
replace
(
"
\n
"
,
" "
))))]
for
quelle_t
,
ziel_t
in
verdaechtig
:
treffer
=
[
z
for
z
in
TYPOGRAFISCH
if
z
in
ziel_t
and
z
not
in
quelle_t
]
if
treffer
:
funde
.
append
((
"typo"
,
"Typografische Anfuehrungszeichen im Code"
,
f"
{
''
.
join
(
treffer
)
}
in:
{
ziel_t
[:
60
]
}
"
))
break
return
funde
# --- Hauptprogramm ---------------------------------------------------------
ALLE_ARTEN
=
[
"klammer"
,
"anzeige"
,
"verweis"
,
"code"
,
"literal"
,
"typo"
,
"bindestrich"
,
"titel"
]
ERKLAERUNG
=
{
"klammer"
:
"Ueberfluessige Backtick-/Stern-Klammer um eine Rolle -- zerstoert die folgenden Querverweise"
,
"anzeige"
:
"Rolle ohne Anzeigetext -- der sichtbare Text fehlt"
,
"verweis"
:
"Benannte Hyperlink-Verweise (`Text`_) fehlen oder sind beschaedigt"
,
"code"
:
"Codeblock ausserhalb von Kommentarzeilen veraendert -- Beispiel ist nicht mehr lauffaehig"
,
"literal"
:
"``Literale`` aus dem Original fehlen in der Uebersetzung -- Code wurde mituebersetzt"
,
"typo"
:
"Typografische Anfuehrungszeichen innerhalb von Code oder Literalen"
,
"bindestrich"
:
"Leerzeichen zwischen Rolle und angehaengtem Wort"
,
"titel"
:
"Seitentitel eines LaTeX-Wurzeldokuments beginnt mit Auszeichnung -- bricht den LaTeX-Build mit -W ab"
,
}
def
main
()
->
None
:
p
=
argparse
.
ArgumentParser
(
description
=
__doc__
,
formatter_class
=
argparse
.
RawDescriptionHelpFormatter
)
p
.
add_argument
(
"pfade"
,
nargs
=
"*"
,
default
=
[
"."
],
help
=
"zu pruefende Verzeichnisse oder Dateien (Vorgabe: alles)"
)
p
.
add_argument
(
"--art"
,
help
=
"nur diese Fehlerarten, kommagetrennt: "
+
", "
.
join
(
ALLE_ARTEN
))
p
.
add_argument
(
"--exclude"
,
default
=
","
.
join
(
AUSSCHLUSS
),
help
=
"Verzeichnisse auslassen (kommagetrennt)"
)
p
.
add_argument
(
"--max"
,
type
=
int
,
default
=
20
,
metavar
=
"N"
,
help
=
"hoechstens N Beispiele je Fehlerart (0 = alle)"
)
p
.
add_argument
(
"--nur-zahlen"
,
action
=
"store_true"
,
dest
=
"nur_zahlen"
,
help
=
"nur die Zusammenfassung ausgeben"
)
p
.
add_argument
(
"-o"
,
"--ausgabe"
,
metavar
=
"DATEI"
,
help
=
"Bericht zusaetzlich als Markdown schreiben"
)
args
=
p
.
parse_args
()
arten
=
set
(
ALLE_ARTEN
)
if
args
.
art
:
gewaehlt
=
{
a
.
strip
()
for
a
in
args
.
art
.
split
(
","
)
if
a
.
strip
()}
unbekannt
=
gewaehlt
-
set
(
ALLE_ARTEN
)
if
unbekannt
:
sys
.
exit
(
f"Unbekannte Fehlerart(en):
{
', '
.
join
(
sorted
(
unbekannt
))
}
"
)
arten
=
gewaehlt
aus
=
[
a
.
strip
()
for
a
in
args
.
exclude
.
split
(
","
)
if
a
.
strip
()]
dateien
=
[]
for
roh
in
args
.
pfade
:
pfad
=
Path
(
roh
)
if
pfad
.
is_file
()
and
pfad
.
suffix
==
".po"
:
dateien
.
append
(
pfad
)
else
:
dateien
.
extend
(
sorted
(
pfad
.
rglob
(
"*.po"
)))
dateien
=
[
d
for
d
in
dateien
if
not
any
(
t
in
d
.
parts
for
t
in
aus
)]
if
not
dateien
:
sys
.
exit
(
"Keine .po-Dateien gefunden."
)
print
(
f"
{
len
(
dateien
)
}
Dateien werden geprueft ..."
,
file
=
sys
.
stderr
)
funde
=
{
a
: []
for
a
in
ALLE_ARTEN
}
betroffene_dateien
=
{
a
:
set
()
for
a
in
ALLE_ARTEN
}
for
nr
,
datei
in
enumerate
(
dateien
,
1
):
if
nr
%
100
==
0
:
print
(
f"
{
nr
}
/
{
len
(
dateien
)
}
"
,
file
=
sys
.
stderr
)
try
:
erster
=
True
for
po_zeile
,
quelle
,
msgid
,
msgstr
in
po_eintraege
(
datei
):
treffer
=
list
(
pruefe_eintrag
(
msgid
,
msgstr
,
arten
))
if
erster
:
# Der erste uebersetzte Eintrag einer Datei ist ihre H1.
erster
=
False
if
"titel"
in
arten
:
treffer
+=
pruefe_titel
(
datei
,
msgstr
)
for
art
,
name
,
ausschnitt
in
treffer
:
funde
[
art
].
append
((
str
(
datei
),
po_zeile
,
quelle
,
name
,
ausschnitt
))
betroffene_dateien
[
art
].
add
(
str
(
datei
))
except
Exception
as
fehler
:
# defekte Datei nicht verschlucken
print
(
f" !!
{
datei
}
:
{
fehler
}
"
,
file
=
sys
.
stderr
)
zeilen
=
[]
gesamt
=
sum
(
len
(
v
)
for
v
in
funde
.
values
())
zeilen
.
append
(
"## Zusammenfassung
\n
"
)
zeilen
.
append
(
"| Fehlerart | Eintraege | Dateien | Bedeutung |"
)
zeilen
.
append
(
"|---|---:|---:|---|"
)
for
art
in
ALLE_ARTEN
:
if
art
not
in
arten
:
continue
zeilen
.
append
(
f"| `
{
art
}
` |
{
len
(
funde
[
art
])
}
| "
f"
{
len
(
betroffene_dateien
[
art
])
}
|
{
ERKLAERUNG
[
art
]
}
|"
)
zeilen
.
append
(
f"| **gesamt** | **
{
gesamt
}
** | "
f"**
{
len
(
set
().
union
(
*
betroffene_dateien
.
values
())
if
gesamt
else
set
())
}
** | |"
)
if
not
args
.
nur_zahlen
:
for
art
in
ALLE_ARTEN
:
if
art
not
in
arten
or
not
funde
[
art
]:
continue
zeilen
.
append
(
f"
\n
##
{
art
}
--
{
ERKLAERUNG
[
art
]
}
\n
"
)
zeigen
=
funde
[
art
]
if
args
.
max
==
0
else
funde
[
art
][:
args
.
max
]
for
datei
,
po_zeile
,
quelle
,
name
,
ausschnitt
in
zeigen
:
zeilen
.
append
(
f"- `
{
datei
}
:
{
po_zeile
}
` (
{
quelle
}
) --
{
name
}
"
)
zeilen
.
append
(
f" - `
{
ausschnitt
}
`"
)
if
len
(
funde
[
art
])
>
len
(
zeigen
):
zeilen
.
append
(
f"- ... und
{
len
(
funde
[
art
])
-
len
(
zeigen
)
}
weitere "
f"(mit `--max 0` vollstaendig)"
)
bericht
=
"
\n
"
.
join
(
zeilen
)
print
()
print
(
bericht
)
if
args
.
ausgabe
:
Path
(
args
.
ausgabe
).
write_text
(
"# Auszeichnungspruefung der PO-Dateien
\n
\n
"
+
bericht
+
"
\n
"
,
encoding
=
"utf-8"
)
print
(
f"
\n
Bericht geschrieben:
{
args
.
ausgabe
}
"
,
file
=
sys
.
stderr
)
sys
.
exit
(
1
if
gesamt
else
0
)
if
__name__
==
"__main__"
:
main
()
Back
|
FazBrowse Home
|
New Git URL