Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/validators/ip_address.py: 85%
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"""IP Address."""
3# standard
4from ipaddress import (
5 AddressValueError,
6 IPv4Address,
7 IPv4Network,
8 IPv6Address,
9 IPv6Network,
10 NetmaskValueError,
11)
12import re
13from typing import Optional
15# local
16from .utils import validator
19def _check_private_ip(value: str, is_private: Optional[bool]):
20 if is_private is None:
21 return True
22 if (
23 any(
24 value.startswith(l_bit)
25 for l_bit in {
26 "10.", # private
27 "192.168.", # private
28 "169.254.", # link-local
29 "127.", # localhost
30 "0.0.0.0", # loopback #nosec
31 }
32 )
33 or re.match(r"^172\.(?:1[6-9]|2\d|3[0-1])\.", value) # private
34 or re.match(r"^(?:22[4-9]|23[0-9]|24[0-9]|25[0-5])\.", value) # broadcast
35 ):
36 return is_private
38 return not is_private
41@validator
42def ipv4(
43 value: str,
44 /,
45 *,
46 cidr: bool = True,
47 strict: bool = False,
48 private: Optional[bool] = None,
49 host_bit: bool = True,
50):
51 """Returns whether a given value is a valid IPv4 address.
53 From Python version 3.9.5 leading zeros are no longer tolerated
54 and are treated as an error. The initial version of ipv4 validator
55 was inspired from [WTForms IPAddress validator][1].
57 [1]: https://github.com/wtforms/wtforms/blob/master/src/wtforms/validators.py
59 Examples:
60 >>> ipv4('123.0.0.7')
61 # Output: True
62 >>> ipv4('1.1.1.1/8')
63 # Output: True
64 >>> ipv4('900.80.70.11')
65 # Output: ValidationError(func=ipv4, args={'value': '900.80.70.11'})
67 Args:
68 value:
69 IP address string to validate.
70 cidr:
71 IP address string may contain CIDR notation.
72 strict:
73 IP address string is strictly in CIDR notation.
74 private:
75 IP address is public if `False`, private/local/loopback/broadcast if `True`.
76 host_bit:
77 If `False` and host bits (along with network bits) _are_ set in the supplied
78 address, this function raises a validation error. ref [IPv4Network][2].
79 [2]: https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Network
81 Returns:
82 (Literal[True]): If `value` is a valid IPv4 address.
83 (ValidationError): If `value` is an invalid IPv4 address.
84 """
85 if not value:
86 return False
87 try:
88 if cidr:
89 if strict and value.count("/") != 1:
90 raise ValueError("IPv4 address was expected in CIDR notation")
91 return IPv4Network(value, strict=not host_bit) and _check_private_ip(value, private)
92 return IPv4Address(value) and _check_private_ip(value, private)
93 except (ValueError, AddressValueError, NetmaskValueError):
94 return False
97@validator
98def ipv6(value: str, /, *, cidr: bool = True, strict: bool = False, host_bit: bool = True):
99 """Returns if a given value is a valid IPv6 address.
101 Including IPv4-mapped IPv6 addresses. The initial version of ipv6 validator
102 was inspired from [WTForms IPAddress validator][1].
104 [1]: https://github.com/wtforms/wtforms/blob/master/src/wtforms/validators.py
106 Examples:
107 >>> ipv6('::ffff:192.0.2.128')
108 # Output: True
109 >>> ipv6('::1/128')
110 # Output: True
111 >>> ipv6('abc.0.0.1')
112 # Output: ValidationError(func=ipv6, args={'value': 'abc.0.0.1'})
114 Args:
115 value:
116 IP address string to validate.
117 cidr:
118 IP address string may contain CIDR annotation.
119 strict:
120 IP address string is strictly in CIDR notation.
121 host_bit:
122 If `False` and host bits (along with network bits) _are_ set in the supplied
123 address, this function raises a validation error. ref [IPv6Network][2].
124 [2]: https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv6Network
126 Returns:
127 (Literal[True]): If `value` is a valid IPv6 address.
128 (ValidationError): If `value` is an invalid IPv6 address.
129 """
130 if not value:
131 return False
132 try:
133 if cidr:
134 if strict and value.count("/") != 1:
135 raise ValueError("IPv6 address was expected in CIDR notation")
136 return IPv6Network(value, strict=not host_bit)
137 return IPv6Address(value)
138 except (ValueError, AddressValueError, NetmaskValueError):
139 return False