Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/validators/i18n/fi.py: 70%

30 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:08 +0000

1"""Finland.""" 

2# -*- coding: utf-8 -*- 

3 

4# standard 

5from functools import lru_cache 

6import re 

7 

8# local 

9from validators.utils import validator 

10 

11 

12@lru_cache 

13def _business_id_pattern(): 

14 """Business ID Pattern.""" 

15 return re.compile(r"^[0-9]{7}-[0-9]$") 

16 

17 

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 [ABCDEFYXWVU+-] 

27 (?P<serial>(\d{{3}})) 

28 (?P<checksum>[{check_marks}])$""".format( 

29 check_marks=ssn_check_marks 

30 ), 

31 re.VERBOSE, 

32 ) 

33 

34 

35@validator 

36def fi_business_id(value: str, /): 

37 """Validate a Finnish Business ID. 

38 

39 Each company in Finland has a distinct business id. For more 

40 information see [Finnish Trade Register][1] 

41 

42 [1]: http://en.wikipedia.org/wiki/Finnish_Trade_Register 

43 

44 Examples: 

45 >>> fi_business_id('0112038-9') # Fast Monkeys Ltd 

46 # Output: True 

47 >>> fi_business_id('1234567-8') # Bogus ID 

48 # Output: ValidationFailure(func=fi_business_id, ...) 

49 

50 Args: 

51 value: 

52 Business ID string to be validated. 

53 

54 Returns: 

55 (Literal[True]): 

56 If `value` is a valid finnish business id. 

57 (ValidationFailure): 

58 If `value` is an invalid finnish business id. 

59 

60 Note: 

61 - *In version 0.5.0*: 

62 - Function renamed from `finnish_business_id` to `fi_business_id` 

63 

64 > *New in version 0.4.0*. 

65 """ 

66 if not value: 

67 return False 

68 if not re.match(_business_id_pattern(), value): 

69 return False 

70 factors = [7, 9, 10, 5, 8, 4, 2] 

71 numbers = map(int, value[:7]) 

72 checksum = int(value[8]) 

73 modulo = sum(f * n for f, n in zip(factors, numbers)) % 11 

74 return (11 - modulo == checksum) or (modulo == checksum == 0) 

75 

76 

77@validator 

78def fi_ssn(value: str, /, *, allow_temporal_ssn: bool = True): 

79 """Validate a Finnish Social Security Number. 

80 

81 This validator is based on [django-localflavor-fi][1]. 

82 

83 [1]: https://github.com/django/django-localflavor-fi/ 

84 

85 Examples: 

86 >>> fi_ssn('010101-0101') 

87 # Output: True 

88 >>> fi_ssn('101010-0102') 

89 # Output: ValidationFailure(func=fi_ssn, args=...) 

90 

91 Args: 

92 value: 

93 Social Security Number to be validated. 

94 allow_temporal_ssn: 

95 Whether to accept temporal SSN numbers. Temporal SSN numbers are the 

96 ones where the serial is in the range [900-999]. By default temporal 

97 SSN numbers are valid. 

98 

99 Returns: 

100 (Literal[True]): 

101 If `value` is a valid finnish SSN. 

102 (ValidationFailure): 

103 If `value` is an invalid finnish SSN. 

104 

105 > *New in version 0.5.0*. 

106 """ 

107 if not value: 

108 return False 

109 ssn_check_marks = "0123456789ABCDEFHJKLMNPRSTUVWXY" 

110 if not (result := re.match(_ssn_pattern(ssn_check_marks), value)): 

111 return False 

112 gd = result.groupdict() 

113 checksum = int(gd["date"] + gd["serial"]) 

114 return ( 

115 int(gd["serial"]) >= 2 

116 and (allow_temporal_ssn or int(gd["serial"]) <= 899) 

117 and ssn_check_marks[checksum % len(ssn_check_marks)] == gd["checksum"] 

118 )