Coverage for presidio_analyzer / predefined_recognizers / country_specific / italy / it_vat_code.py: 100%
28 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 ItVatCodeRecognizer(PatternRecognizer):
7 """
8 Recognizes Italian VAT code using regex and checksum.
10 For more information about italian VAT code:
11 https://en.wikipedia.org/wiki/VAT_identification_number#:~:text=%5B2%5D)-,Italy,-Partita%20IVA
13 :param patterns: List of patterns to be used by this recognizer
14 :param context: List of context words to increase confidence in detection
15 :param supported_language: Language this recognizer supports
16 :param supported_entity: The entity this recognizer can detect
17 :param replacement_pairs: List of tuples with potential replacement values
18 for different strings to be used during pattern matching.
19 This can allow a greater variety in input, for example by removing dashes or spaces.
20 """
22 # Class variables
23 PATTERNS = [
24 Pattern(
25 "IT Vat code (piva)",
26 r"\b([0-9][ _]?){11}\b",
27 0.1,
28 )
29 ]
31 CONTEXT = ["piva", "partita iva", "pi"]
33 def __init__(
34 self,
35 patterns: Optional[List[Pattern]] = None,
36 context: Optional[List[str]] = None,
37 supported_language: str = "it",
38 supported_entity: str = "IT_VAT_CODE",
39 replacement_pairs: Optional[List[Tuple[str, str]]] = None,
40 name: Optional[str] = None,
41 version: str = "0.0.1",
42 ):
43 self.replacement_pairs = (
44 replacement_pairs
45 if replacement_pairs
46 else [("-", ""), (" ", ""), ("_", "")]
47 )
48 patterns = patterns if patterns else self.PATTERNS
49 context = context if context else self.CONTEXT
50 super().__init__(
51 supported_entity=supported_entity,
52 patterns=patterns,
53 context=context,
54 supported_language=supported_language,
55 name=name,
56 version=version,
57 )
59 def validate_result(self, pattern_text: str) -> bool:
60 """
61 Validate the pattern logic e.g., by running checksum on a detected pattern.
63 :param pattern_text: the text to validated.
64 Only the part in text that was detected by the regex engine
65 :return: A bool indicating whether the validation was successful.
66 """
68 # Pre-processing before validation checks
69 text = EntityRecognizer.sanitize_value(pattern_text, self.replacement_pairs)
71 # Edge-case that passes the checksum even though it is not a
72 # valid italian vat code.
73 if text == "00000000000":
74 return False
76 x = 0
77 y = 0
79 for i in range(0, 5):
80 x += int(text[2 * i])
81 tmp_y = int(text[2 * i + 1]) * 2
82 if tmp_y > 9:
83 tmp_y = tmp_y - 9
84 y += tmp_y
86 t = (x + y) % 10
87 c = (10 - t) % 10
89 if c == int(text[10]):
90 result = True
91 else:
92 result = False
94 return result