Skip to content

Commit 5540a9e

Browse files
committed
gh-151769: Fix IPv6Address ordering to account for scope_id
1 parent f28ef85 commit 5540a9e

3 files changed

Lines changed: 29 additions & 0 deletions

File tree

Lib/ipaddress.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,6 +2002,21 @@ def __str__(self):
20022002
def __hash__(self):
20032003
return hash((self._ip, self._scope_id))
20042004

2005+
def __lt__(self, other):
2006+
if not isinstance(other, IPv6Address):
2007+
return NotImplemented
2008+
if self._ip != other._ip:
2009+
return self._ip < other._ip
2010+
self_scope = self._scope_id
2011+
other_scope = other._scope_id
2012+
if self_scope is None and other_scope is None:
2013+
return False
2014+
if other_scope is None:
2015+
return False
2016+
if self_scope is None:
2017+
return True
2018+
return self_scope < other_scope
2019+
20052020
def __eq__(self, other):
20062021
address_equal = super().__eq__(other)
20072022
if address_equal is NotImplemented:

Lib/test/test_ipaddress.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,17 @@ def test_same_type_ordering(self):
986986
self.assertFalse(lhs >= rhs)
987987
self.assertFalse(rhs <= lhs)
988988

989+
def test_scoped_ipv6_ordering_same_ip(self):
990+
# gh-151769: addresses with the same integer but different
991+
# scope_id must be ordered; None < any string
992+
unscoped = self.v6addr_scoped
993+
scoped = ipaddress.IPv6Address(str(unscoped) + '%eth0')
994+
self.assertNotEqual(unscoped, scoped)
995+
self.assertLess(unscoped, scoped)
996+
self.assertGreater(scoped, unscoped)
997+
# sorted() must be deterministic
998+
self.assertEqual(sorted([scoped, unscoped]), [unscoped, scoped])
999+
9891000
def test_containment(self):
9901001
for obj in self.v4_addresses:
9911002
self.assertIn(obj, self.v4net)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :class:`ipaddress.IPv6Address` ordering to account for ``scope_id``,
2+
so addresses with the same IP but different scope IDs compare as ordered
3+
and :func:`sorted` is deterministic.

0 commit comments

Comments
 (0)