Coverage for /var/devmt/py/utils4_1.6.0/utils4/validation.py: 100%

41 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-11-13 09:50 +0000

1# -*- coding: utf-8 -*- 

2r""" 

3:Purpose: This module serves as a general validation processor. 

4 

5 .. note:: 

6 This is currently **very basic** module, and only contains 

7 validation rules which are commonly used by S3DEV projects. 

8 More functionality will be added as needed. 

9 

10:Platform: Linux/Windows | Python 3.7+ 

11:Developer: J Berendt 

12:Email: support@s3dev.uk 

13 

14:Comments: n/a 

15 

16:Example: 

17 

18 Test if an IP address is valid:: 

19 

20 >>> from utils4 import validation 

21 

22 >>> validation.rules.is_ip(value='128.31.0.62') 

23 True 

24 

25 

26 Test if a set of geo coordinates is valid:: 

27 

28 >>> from utils4 import validation 

29 

30 >>> validation.rules.is_coordinates(value=['4.6097100', '-74.0817500']) 

31 True 

32 

33 

34 Return the regex pattern for latitude:: 

35 

36 >>> from utils4 import validation 

37 

38 >>> validation.regex.latitude 

39 re.compile(r'^(-)?(([0-9]|[1-8][0-9])(\.[0-9]{1,})?|90)$', re.UNICODE) 

40 

41""" 

42 

43import re 

44import ipaddress 

45from typing import List 

46 

47 

48class RegEx: 

49 """This class holds a variety of validation regex strings. 

50 

51 Each property in this class returns a *compiled* regex pattern, of the 

52 type ``re.Pattern``. 

53 

54 """ 

55 

56 @property 

57 def latitude(self): 

58 """Regex string for latitude. 

59 

60 Returns: 

61 re.Pattern: A compiled regex pattern for latitude. 

62 

63 """ 

64 return re.compile(r'^(-)?(([0-9]|[1-8][0-9])(\.[0-9]{1,})?|90)$') 

65 

66 @property 

67 def longitude(self): 

68 """Regex string for longitude. 

69 

70 Returns: 

71 re.Pattern: A compiled regex pattern for longitude. 

72 

73 """ 

74 return r'^(-)?(([0-9]|[1-9][0-9]|1[0-7][0-9])(\.[0-9]{1,})?|180)$' 

75 

76 

77class Rules: 

78 """A collection of validation rules.""" 

79 

80 def __init__(self): 

81 """Class initialiser.""" 

82 self._re = RegEx() 

83 

84 def is_coordinates(self, value: List[str]) -> bool: 

85 """Test ``value`` is a valid set of geo coordinates. 

86 

87 Args: 

88 value (List[str]): A list containing latitude and longitude as 

89 strings. 

90 

91 :Rules: 

92 

93 - ``value`` is a ``list`` 

94 - The index 0 is a valid latitude coordinate (-90, 90) 

95 - The index 1 is a valid longitude coordinate (-180, 180) 

96 - For example:: 

97 

98 ['4.6097100', '-74.0817500'] 

99 

100 Returns: 

101 bool: True if ``value`` is a *valid* set of coordinates, otherwise 

102 False. 

103 

104 """ 

105 is_lat = False 

106 is_lon = False 

107 is_list = self.is_list(value, indexes=2) 

108 if is_list: 

109 is_lat = self.is_latitude(value=value[0]) 

110 is_lon = self.is_longitude(value=value[1]) 

111 return all([is_list, is_lat, is_lon]) 

112 

113 @staticmethod 

114 def is_ip(value: str) -> bool: 

115 """Test if an IP address (IPv4 or IPv6) is valid. 

116 

117 This function wraps the built-in :func:`ipaddress.ip_address` function 

118 to test whether an IP address is valid, or not. 

119 

120 Args: 

121 value (str): The IP address to be tested. 

122 

123 Returns: 

124 bool: True if ``value`` is a valid IPv4 or IPv6 address, otherwise 

125 False. 

126 

127 """ 

128 try: 

129 ipaddress.ip_address(address=value) 

130 return True 

131 except ValueError: 

132 return False 

133 

134 def is_latitude(self, value: str) -> bool: 

135 """Test ``value`` is a latitude coordinate (-90, 90). 

136 

137 Args: 

138 value (str): The latitude coordinate to be tested. 

139 

140 Returns: 

141 bool: True if ``value`` is a valid latitude coordinate, otherwise 

142 False. 

143 

144 """ 

145 return bool(re.match(self._re.latitude, value)) 

146 

147 @staticmethod 

148 def is_list(value: object, indexes: int=None) -> bool: 

149 """Validate if ``value`` is a ``list`` with (n) number of indexes. 

150 

151 Args: 

152 value (list): The object to be tested. 

153 indexes (int, optional): Number of expected indexes in the list. 

154 Defaults to None. 

155 

156 Returns: 

157 bool: True if ``value`` is a ``list`` with (n) indexes, otherwise 

158 False. 

159 

160 """ 

161 _idx = True 

162 _list = isinstance(value, list) 

163 if _list and indexes: 

164 _idx = len(value) == indexes 

165 return all([_list, _idx]) 

166 

167 def is_longitude(self, value: str) -> bool: 

168 """Test ``value`` is a longitude coordinate (-180, 180). 

169 

170 Args: 

171 value (str): The longitude coordinate to be tested. 

172 

173 Returns: 

174 bool: True if ``value`` is a valid longitude coordinate, otherwise 

175 False. 

176 

177 """ 

178 return bool(re.match(self._re.longitude, value)) 

179 

180 

181regex = RegEx() 

182rules = Rules()