Coverage for presidio_analyzer / predefined_recognizers / country_specific / uk / uk_nhs_recognizer.py: 100%
16 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, Tuple
3from presidio_analyzer import EntityRecognizer, Pattern, PatternRecognizer
6class NhsRecognizer(PatternRecognizer):
7 """
8 Recognizes NHS number using regex and checksum.
10 :param patterns: List of patterns to be used by this recognizer
11 :param context: List of context words to increase confidence in detection
12 :param supported_language: Language this recognizer supports
13 :param supported_entity: The entity this recognizer can detect
14 :param replacement_pairs: List of tuples with potential replacement values
15 for different strings to be used during pattern matching.
16 This can allow a greater variety in input, for example by removing dashes or spaces.
17 """
19 PATTERNS = [
20 Pattern(
21 "NHS (medium)",
22 r"\b([0-9]{3})[- ]?([0-9]{3})[- ]?([0-9]{4})\b",
23 0.5,
24 ),
25 ]
27 CONTEXT = [
28 "national health service",
29 "nhs",
30 "health services authority",
31 "health authority",
32 ]
34 def __init__(
35 self,
36 patterns: Optional[List[Pattern]] = None,
37 context: Optional[List[str]] = None,
38 supported_language: str = "en",
39 supported_entity: str = "UK_NHS",
40 replacement_pairs: Optional[List[Tuple[str, str]]] = None,
41 name: Optional[str] = None,
42 ):
43 self.replacement_pairs = (
44 replacement_pairs if replacement_pairs else [("-", ""), (" ", "")]
45 )
46 patterns = patterns if patterns else self.PATTERNS
47 context = context if context else self.CONTEXT
48 super().__init__(
49 supported_entity=supported_entity,
50 patterns=patterns,
51 context=context,
52 supported_language=supported_language,
53 name=name,
54 )
56 def validate_result(self, pattern_text: str) -> bool:
57 """
58 Validate the pattern logic e.g., by running checksum on a detected pattern.
60 :param pattern_text: the text to validated.
61 Only the part in text that was detected by the regex engine
62 :return: A bool indicating whether the validation was successful.
63 """
64 text = EntityRecognizer.sanitize_value(pattern_text, self.replacement_pairs)
65 total = sum(
66 [int(c) * multiplier for c, multiplier in zip(text, reversed(range(11)))]
67 )
68 remainder = total % 11
69 check_remainder = remainder == 0
71 return check_remainder