Coverage for /var/devmt/py/utils4_1.8.0/utils4/validation.py: 100%
41 statements
« prev ^ index » next coverage.py v7.6.9, created at 2025-08-26 21:39 +0100
« prev ^ index » next coverage.py v7.6.9, created at 2025-08-26 21:39 +0100
1# -*- coding: utf-8 -*-
2r"""
3:Purpose: This module serves as a general validation processor.
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.
10:Developer: J Berendt
11:Email: support@s3dev.uk
13:Comments: n/a
15:Example:
17 Test if an IP address is valid::
19 >>> from utils4 import validation
21 >>> validation.rules.is_ip(value='128.31.0.62')
22 True
25 Test if a set of geo coordinates is valid::
27 >>> from utils4 import validation
29 >>> validation.rules.is_coordinates(value=['4.6097100', '-74.0817500'])
30 True
33 Return the regex pattern for latitude::
35 >>> from utils4 import validation
37 >>> validation.regex.latitude
38 re.compile(r'^(-)?(([0-9]|[1-8][0-9])(\.[0-9]{1,})?|90)$', re.UNICODE)
40"""
42import re
43import ipaddress
44from typing import List
47class RegEx:
48 """This class holds a variety of validation regex strings.
50 Each property in this class returns a *compiled* regex pattern, of the
51 type ``re.Pattern``.
53 """
55 @property
56 def latitude(self):
57 """Regex string for latitude.
59 Returns:
60 re.Pattern: A compiled regex pattern for latitude.
62 """
63 return re.compile(r'^(-)?(([0-9]|[1-8][0-9])(\.[0-9]{1,})?|90)$')
65 @property
66 def longitude(self):
67 """Regex string for longitude.
69 Returns:
70 re.Pattern: A compiled regex pattern for longitude.
72 """
73 return r'^(-)?(([0-9]|[1-9][0-9]|1[0-7][0-9])(\.[0-9]{1,})?|180)$'
76class Rules:
77 """A collection of validation rules."""
79 def __init__(self):
80 """Class initialiser."""
81 self._re = RegEx()
83 def is_coordinates(self, value: List[str]) -> bool:
84 """Test ``value`` is a valid set of geo coordinates.
86 Args:
87 value (List[str]): A list containing latitude and longitude as
88 strings.
90 :Rules:
92 - ``value`` is a ``list``
93 - The index 0 is a valid latitude coordinate (-90, 90)
94 - The index 1 is a valid longitude coordinate (-180, 180)
95 - For example::
97 ['4.6097100', '-74.0817500']
99 Returns:
100 bool: True if ``value`` is a *valid* set of coordinates, otherwise
101 False.
103 """
104 is_lat = False
105 is_lon = False
106 is_list = self.is_list(value, indexes=2)
107 if is_list:
108 is_lat = self.is_latitude(value=value[0])
109 is_lon = self.is_longitude(value=value[1])
110 return all([is_list, is_lat, is_lon])
112 @staticmethod
113 def is_ip(value: str) -> bool:
114 """Test if an IP address (IPv4 or IPv6) is valid.
116 This function wraps the built-in :func:`ipaddress.ip_address` function
117 to test whether an IP address is valid, or not.
119 Args:
120 value (str): The IP address to be tested.
122 Returns:
123 bool: True if ``value`` is a valid IPv4 or IPv6 address, otherwise
124 False.
126 """
127 try:
128 ipaddress.ip_address(address=value)
129 return True
130 except ValueError:
131 return False
133 def is_latitude(self, value: str) -> bool:
134 """Test ``value`` is a latitude coordinate (-90, 90).
136 Args:
137 value (str): The latitude coordinate to be tested.
139 Returns:
140 bool: True if ``value`` is a valid latitude coordinate, otherwise
141 False.
143 """
144 return bool(re.match(self._re.latitude, value))
146 @staticmethod
147 def is_list(value: object, indexes: int=None) -> bool:
148 """Validate if ``value`` is a ``list`` with (n) number of indexes.
150 Args:
151 value (list): The object to be tested.
152 indexes (int, optional): Number of expected indexes in the list.
153 Defaults to None.
155 Returns:
156 bool: True if ``value`` is a ``list`` with (n) indexes, otherwise
157 False.
159 """
160 _idx = True
161 _list = isinstance(value, list)
162 if _list and indexes:
163 _idx = len(value) == indexes
164 return all([_list, _idx])
166 def is_longitude(self, value: str) -> bool:
167 """Test ``value`` is a longitude coordinate (-180, 180).
169 Args:
170 value (str): The longitude coordinate to be tested.
172 Returns:
173 bool: True if ``value`` is a valid longitude coordinate, otherwise
174 False.
176 """
177 return bool(re.match(self._re.longitude, value))
180regex = RegEx()
181rules = Rules()