Skip to content

Commit 2e0aed3

Browse files
vuolterkvesteri
authored andcommitted
Support IPv4-compatible + IPv4-mapped (python-validators#56)
Add support for IPv4-compatible address and IPv4-mapped address Code cleanup and small speedup
1 parent 19a58d0 commit 2e0aed3

File tree

2 files changed

+38
-20
lines changed

2 files changed

+38
-20
lines changed

tests/test_ipv6.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
('::1',),
99
('dead:beef:0:0:0:0:42:1',),
1010
('abcd:ef::42:1',),
11+
('0:0:0:0:0:ffff:1.2.3.4',),
12+
('::192.168.30.2',),
1113
])
12-
def test_returns_true_on_valid_ipv4_address(address):
14+
def test_returns_true_on_valid_ipv6_address(address):
1315
assert ipv6(address)
1416

1517

validators/ip_address.py

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,17 @@ def ipv4(value):
2323
2424
:param value: IP address string to validate
2525
"""
26-
parts = value.split('.')
27-
if len(parts) == 4 and all(x.isdigit() for x in parts):
28-
numbers = list(int(x) for x in parts)
29-
return all(num >= 0 and num < 256 for num in numbers)
30-
return False
26+
groups = value.split('.')
27+
if len(groups) != 4 or any(not x.isdigit() for x in groups):
28+
return False
29+
return all(0 <= int(part) < 256 for part in groups)
3130

3231

3332
@validator
3433
def ipv6(value):
3534
"""
36-
Return whether or not given value is a valid IP version 6 address.
35+
Return whether or not given value is a valid IP version 6 address
36+
(including IPv4-mapped IPv6 addresses).
3737
3838
This validator is based on `WTForms IPAddress validator`_.
3939
@@ -45,32 +45,48 @@ def ipv6(value):
4545
>>> ipv6('abcd:ef::42:1')
4646
True
4747
48+
>>> ipv6('::ffff:192.0.2.128')
49+
True
50+
51+
>>> ipv6('::192.0.2.128')
52+
True
53+
4854
>>> ipv6('abc.0.0.1')
4955
ValidationFailure(func=ipv6, args={'value': 'abc.0.0.1'})
5056
5157
.. versionadded:: 0.2
5258
5359
:param value: IP address string to validate
5460
"""
55-
parts = value.split(':')
56-
if len(parts) > 8:
61+
ipv6_groups = value.split(':')
62+
ipv4_groups = ipv6_groups[-1].split('.')
63+
64+
if len(ipv4_groups) > 1:
65+
if not ipv4(ipv6_groups[-1]):
66+
return False
67+
ipv6_groups = ipv6_groups[:-1]
68+
else:
69+
ipv4_groups = []
70+
71+
max_groups = 6 if ipv4_groups else 8
72+
if len(ipv6_groups) > max_groups:
5773
return False
5874

59-
num_blank = 0
60-
for part in parts:
75+
count_blank = 0
76+
for part in ipv6_groups:
6177
if not part:
62-
num_blank += 1
78+
count_blank += 1
79+
continue
80+
try:
81+
num = int(part, 16)
82+
except ValueError:
83+
return False
6384
else:
64-
try:
65-
value = int(part, 16)
66-
except ValueError:
85+
if not 0 <= num <= 65536:
6786
return False
68-
else:
69-
if value < 0 or value >= 65536:
70-
return False
7187

72-
if num_blank < 2:
88+
if count_blank < 2:
7389
return True
74-
elif num_blank == 2 and not parts[0] and not parts[1]:
90+
elif count_blank == 2 and not ipv6_groups[0] and not ipv6_groups[1]:
7591
return True
7692
return False

0 commit comments

Comments
 (0)