Coverage for presidio_analyzer / predefined_recognizers / country_specific / germany / de_plz_recognizer.py: 100%
9 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-03-29 09:03 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-03-29 09:03 +0000
1from typing import List, Optional
3from presidio_analyzer import Pattern, PatternRecognizer
6class DePlzRecognizer(PatternRecognizer):
7 """
8 Recognizes German postal codes (Postleitzahl, PLZ).
10 German postal codes consist of exactly 5 digits in the range 01001–99998,
11 assigned by Deutsche Post AG. A PLZ alone is generally not sufficient to
12 identify a specific natural person and is therefore not directly personal data
13 under DSGVO Art. 4 Nr. 1. However, in combination with other data (e.g., street
14 address, name), it contributes to identifying an individual, and in very rural
15 areas a single PLZ may cover only a handful of addresses.
17 Legal basis: DSGVO Art. 4 Nr. 1 in combination with other address data; BDSG.
19 Format:
20 5 digits, 01001–99998 (boundary values 01000 and 99999 are excluded).
21 Examples: 10115 (Berlin Mitte), 80331 (München), 22085 (Hamburg)
23 !! ACCURACY WARNING !!
24 The pattern `[0-9]{5}` is extremely generic and will produce a very high number
25 of false positives when used without context (e.g., year numbers, prices, order
26 IDs, phone number fragments, reference numbers). The base confidence is
27 therefore set to 0.05 – the recognizer is only actionable when strong context
28 words such as "PLZ", "Postleitzahl" or "Postanschrift" are present nearby.
29 This recognizer should only be enabled in pipelines where German address data
30 is expected. Formal accuracy evaluation has not been performed on a labelled
31 dataset.
33 :param patterns: List of patterns to be used by this recognizer
34 :param context: List of context words to increase confidence in detection
35 :param supported_language: Language this recognizer supports
36 :param supported_entity: The entity this recognizer can detect
37 """
39 # Regex covers 01001–09999 (leading zero) and 10000–99998.
40 # Does NOT match 00000 (not a valid PLZ), 01000, 99999, or 6-digit numbers.
41 # Reference: Deutsche Post AG PLZ-Verzeichnis.
42 PATTERNS = [
43 Pattern(
44 "Postleitzahl (5 digits, very low base confidence – context required)",
45 r"\b(?!01000\b|99999\b)(0[1-9]\d{3}|[1-9]\d{4})\b",
46 0.05,
47 ),
48 ]
50 CONTEXT = [
51 "plz",
52 "postleitzahl",
53 "postanschrift",
54 "adresse",
55 "wohnort",
56 "ort",
57 "wohnanschrift",
58 "lieferadresse",
59 "rechnungsadresse",
60 "straße",
61 "strasse",
62 "hausnummer",
63 "postfach",
64 "bundesland",
65 "gemeinde",
66 "stadt",
67 "dorf",
68 ]
70 def __init__(
71 self,
72 patterns: Optional[List[Pattern]] = None,
73 context: Optional[List[str]] = None,
74 supported_language: str = "de",
75 supported_entity: str = "DE_PLZ",
76 name: Optional[str] = None,
77 ):
78 patterns = patterns if patterns else self.PATTERNS
79 context = context if context else self.CONTEXT
80 super().__init__(
81 supported_entity=supported_entity,
82 patterns=patterns,
83 context=context,
84 supported_language=supported_language,
85 name=name,
86 )