Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/validators/i18n/fi.py: 66%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Finland."""
3# standard
4from datetime import date
5from functools import lru_cache
6import re
8# local
9from validators.utils import validator
12@lru_cache
13def _business_id_pattern():
14 """Business ID Pattern."""
15 return re.compile(r"^[0-9]{7}-[0-9]$")
18@lru_cache
19def _ssn_pattern(ssn_check_marks: str):
20 """SSN Pattern."""
21 return re.compile(
22 r"""^
23 (?P<date>(0[1-9]|[1-2]\d|3[01])
24 (0[1-9]|1[012])
25 (\d{{2}}))
26 (?P<century>[ABCDEFYXWVU+-])
27 (?P<serial>(\d{{3}}))
28 (?P<checksum>[{check_marks}])$""".format(check_marks=ssn_check_marks),
29 re.VERBOSE | re.ASCII,
30 )
33@validator
34def fi_business_id(value: str, /):
35 """Validate a Finnish Business ID.
37 Each company in Finland has a distinct business id. For more
38 information see [Finnish Trade Register][1]
40 [1]: http://en.wikipedia.org/wiki/Finnish_Trade_Register
42 Examples:
43 >>> fi_business_id('0112038-9') # Fast Monkeys Ltd
44 True
45 >>> fi_business_id('1234567-8') # Bogus ID
46 ValidationError(func=fi_business_id, args={'value': '1234567-8'})
48 Args:
49 value:
50 Business ID string to be validated.
52 Returns:
53 (Literal[True]): If `value` is a valid finnish business id.
54 (ValidationError): If `value` is an invalid finnish business id.
55 """
56 if not value:
57 return False
58 if not re.fullmatch(_business_id_pattern(), value):
59 return False
60 factors = [7, 9, 10, 5, 8, 4, 2]
61 numbers = map(int, value[:7])
62 checksum = int(value[8])
63 modulo = sum(f * n for f, n in zip(factors, numbers)) % 11
64 return (11 - modulo == checksum) or (modulo == checksum == 0)
67@validator
68def fi_ssn(value: str, /, *, allow_temporal_ssn: bool = True):
69 """Validate a Finnish Social Security Number.
71 This validator is based on [django-localflavor-fi][1].
73 [1]: https://github.com/django/django-localflavor-fi/
75 Examples:
76 >>> fi_ssn('010101-0101')
77 True
78 >>> fi_ssn('101010-0102')
79 ValidationError(func=fi_ssn, args={'value': '101010-0102'})
81 Args:
82 value:
83 Social Security Number to be validated.
84 allow_temporal_ssn:
85 Whether to accept temporal SSN numbers. Temporal SSN numbers are the
86 ones where the serial is in the range [900-999]. By default temporal
87 SSN numbers are valid.
89 Returns:
90 (Literal[True]): If `value` is a valid finnish SSN.
91 (ValidationError): If `value` is an invalid finnish SSN.
92 """
93 if not value:
94 return False
95 ssn_check_marks = "0123456789ABCDEFHJKLMNPRSTUVWXY"
96 if not (result := re.fullmatch(_ssn_pattern(ssn_check_marks), value)):
97 return False
98 gd = result.groupdict()
99 century = 1800 if gd["century"] == "+" else 2000 if gd["century"] in "ABCDEF" else 1900
100 birth_date = gd["date"]
101 date(century + int(birth_date[4:]), int(birth_date[2:4]), int(birth_date[:2]))
102 checksum = int(gd["date"] + gd["serial"])
103 return (
104 int(gd["serial"]) >= 2
105 and (allow_temporal_ssn or int(gd["serial"]) <= 899)
106 and ssn_check_marks[checksum % len(ssn_check_marks)] == gd["checksum"]
107 )