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