99 IPv6Network ,
1010 NetmaskValueError ,
1111)
12+ import re
13+ from typing import Optional
1214
1315# local
1416from .utils import validator
1517
1618
19+ def _check_private_ip (value : str , is_private : Optional [bool ]):
20+ if is_private is None :
21+ return True
22+ if is_private and (
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 True
37+ return False
38+
39+
1740@validator
18- def ipv4 (value : str , / , * , cidr : bool = True , strict : bool = False , host_bit : bool = True ):
41+ def ipv4 (
42+ value : str ,
43+ / ,
44+ * ,
45+ cidr : bool = True ,
46+ strict : bool = False ,
47+ private : Optional [bool ] = None ,
48+ host_bit : bool = True ,
49+ ):
1950 """Returns whether a given value is a valid IPv4 address.
2051
2152 From Python version 3.9.5 leading zeros are no longer tolerated
@@ -36,9 +67,11 @@ def ipv4(value: str, /, *, cidr: bool = True, strict: bool = False, host_bit: bo
3667 value:
3768 IP address string to validate.
3869 cidr:
39- IP address string may contain CIDR notation
70+ IP address string may contain CIDR notation.
4071 strict:
41- IP address string is strictly in CIDR notation
72+ IP address string is strictly in CIDR notation.
73+ private:
74+ IP address is public if `False`, private/local/loopback/broadcast if `True`.
4275 host_bit:
4376 If `False` and host bits (along with network bits) _are_ set in the supplied
4477 address, this function raises a validation error. ref [IPv4Network][2].
@@ -54,8 +87,8 @@ def ipv4(value: str, /, *, cidr: bool = True, strict: bool = False, host_bit: bo
5487 if cidr :
5588 if strict and value .count ("/" ) != 1 :
5689 raise ValueError ("IPv4 address was expected in CIDR notation" )
57- return IPv4Network (value , strict = not host_bit )
58- return IPv4Address (value )
90+ return IPv4Network (value , strict = not host_bit ) and _check_private_ip ( value , private )
91+ return IPv4Address (value ) and _check_private_ip ( value , private )
5992 except (ValueError , AddressValueError , NetmaskValueError ):
6093 return False
6194
@@ -81,9 +114,9 @@ def ipv6(value: str, /, *, cidr: bool = True, strict: bool = False, host_bit: bo
81114 value:
82115 IP address string to validate.
83116 cidr:
84- IP address string may contain CIDR annotation
117+ IP address string may contain CIDR annotation.
85118 strict:
86- IP address string is strictly in CIDR notation
119+ IP address string is strictly in CIDR notation.
87120 host_bit:
88121 If `False` and host bits (along with network bits) _are_ set in the supplied
89122 address, this function raises a validation error. ref [IPv6Network][2].
0 commit comments