Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f186e12

Browse files
Issue #23268: Fixed bugs in the comparison of ipaddress classes.
1 parent f4b7a02 commit f186e12

3 files changed

Lines changed: 51 additions & 45 deletions

File tree

Lib/ipaddress.py

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -388,40 +388,7 @@ def get_mixed_type_key(obj):
388388
return NotImplemented
389389

390390

391-
class _TotalOrderingMixin:
392-
# Helper that derives the other comparison operations from
393-
# __lt__ and __eq__
394-
# We avoid functools.total_ordering because it doesn't handle
395-
# NotImplemented correctly yet (http://bugs.python.org/issue10042)
396-
def __eq__(self, other):
397-
raise NotImplementedError
398-
def __ne__(self, other):
399-
equal = self.__eq__(other)
400-
if equal is NotImplemented:
401-
return NotImplemented
402-
return not equal
403-
def __lt__(self, other):
404-
raise NotImplementedError
405-
def __le__(self, other):
406-
less = self.__lt__(other)
407-
if less is NotImplemented or not less:
408-
return self.__eq__(other)
409-
return less
410-
def __gt__(self, other):
411-
less = self.__lt__(other)
412-
if less is NotImplemented:
413-
return NotImplemented
414-
equal = self.__eq__(other)
415-
if equal is NotImplemented:
416-
return NotImplemented
417-
return not (less or equal)
418-
def __ge__(self, other):
419-
less = self.__lt__(other)
420-
if less is NotImplemented:
421-
return NotImplemented
422-
return not less
423-
424-
class _IPAddressBase(_TotalOrderingMixin):
391+
class _IPAddressBase:
425392

426393
"""The mother class."""
427394

@@ -554,6 +521,7 @@ def _prefix_from_ip_string(self, ip_str):
554521
self._report_invalid_netmask(ip_str)
555522

556523

524+
@functools.total_ordering
557525
class _BaseAddress(_IPAddressBase):
558526

559527
"""A generic IP object.
@@ -578,12 +546,11 @@ def __eq__(self, other):
578546
return NotImplemented
579547

580548
def __lt__(self, other):
549+
if not isinstance(other, _BaseAddress):
550+
return NotImplemented
581551
if self._version != other._version:
582552
raise TypeError('%s and %s are not of the same version' % (
583553
self, other))
584-
if not isinstance(other, _BaseAddress):
585-
raise TypeError('%s and %s are not of the same type' % (
586-
self, other))
587554
if self._ip != other._ip:
588555
return self._ip < other._ip
589556
return False
@@ -613,6 +580,7 @@ def _get_address_key(self):
613580
return (self._version, self)
614581

615582

583+
@functools.total_ordering
616584
class _BaseNetwork(_IPAddressBase):
617585

618586
"""A generic IP network object.
@@ -662,12 +630,11 @@ def __getitem__(self, n):
662630
return self._address_class(broadcast + n)
663631

664632
def __lt__(self, other):
633+
if not isinstance(other, _BaseNetwork):
634+
return NotImplemented
665635
if self._version != other._version:
666636
raise TypeError('%s and %s are not of the same version' % (
667637
self, other))
668-
if not isinstance(other, _BaseNetwork):
669-
raise TypeError('%s and %s are not of the same type' % (
670-
self, other))
671638
if self.network_address != other.network_address:
672639
return self.network_address < other.network_address
673640
if self.netmask != other.netmask:

Lib/test/test_ipaddress.py

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import unittest
88
import re
99
import contextlib
10+
import functools
1011
import operator
1112
import ipaddress
1213

@@ -528,6 +529,20 @@ def test_ip_network(self):
528529
self.assertFactoryError(ipaddress.ip_network, "network")
529530

530531

532+
@functools.total_ordering
533+
class LargestObject:
534+
def __eq__(self, other):
535+
return isinstance(other, LargestObject)
536+
def __lt__(self, other):
537+
return False
538+
539+
@functools.total_ordering
540+
class SmallestObject:
541+
def __eq__(self, other):
542+
return isinstance(other, SmallestObject)
543+
def __gt__(self, other):
544+
return False
545+
531546
class ComparisonTests(unittest.TestCase):
532547

533548
v4addr = ipaddress.IPv4Address(1)
@@ -581,6 +596,28 @@ def test_mixed_type_ordering(self):
581596
self.assertRaises(TypeError, lambda: lhs <= rhs)
582597
self.assertRaises(TypeError, lambda: lhs >= rhs)
583598

599+
def test_foreign_type_ordering(self):
600+
other = object()
601+
smallest = SmallestObject()
602+
largest = LargestObject()
603+
for obj in self.objects:
604+
with self.assertRaises(TypeError):
605+
obj < other
606+
with self.assertRaises(TypeError):
607+
obj > other
608+
with self.assertRaises(TypeError):
609+
obj <= other
610+
with self.assertRaises(TypeError):
611+
obj >= other
612+
self.assertTrue(obj < largest)
613+
self.assertFalse(obj > largest)
614+
self.assertTrue(obj <= largest)
615+
self.assertFalse(obj >= largest)
616+
self.assertFalse(obj < smallest)
617+
self.assertTrue(obj > smallest)
618+
self.assertFalse(obj <= smallest)
619+
self.assertTrue(obj >= smallest)
620+
584621
def test_mixed_type_key(self):
585622
# with get_mixed_type_key, you can sort addresses and network.
586623
v4_ordered = [self.v4addr, self.v4net, self.v4intf]
@@ -601,7 +638,7 @@ def test_incompatible_versions(self):
601638
v4addr = ipaddress.ip_address('1.1.1.1')
602639
v4net = ipaddress.ip_network('1.1.1.1')
603640
v6addr = ipaddress.ip_address('::1')
604-
v6net = ipaddress.ip_address('::1')
641+
v6net = ipaddress.ip_network('::1')
605642

606643
self.assertRaises(TypeError, v4addr.__lt__, v6addr)
607644
self.assertRaises(TypeError, v4addr.__gt__, v6addr)
@@ -1248,10 +1285,10 @@ def testNetworkComparison(self):
12481285
unsorted = [ip4, ip1, ip3, ip2]
12491286
unsorted.sort()
12501287
self.assertEqual(sorted, unsorted)
1251-
self.assertRaises(TypeError, ip1.__lt__,
1252-
ipaddress.ip_address('10.10.10.0'))
1253-
self.assertRaises(TypeError, ip2.__lt__,
1254-
ipaddress.ip_address('10.10.10.0'))
1288+
self.assertIs(ip1.__lt__(ipaddress.ip_address('10.10.10.0')),
1289+
NotImplemented)
1290+
self.assertIs(ip2.__lt__(ipaddress.ip_address('10.10.10.0')),
1291+
NotImplemented)
12551292

12561293
# <=, >=
12571294
self.assertTrue(ipaddress.ip_network('1.1.1.1') <=

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ Core and Builtins
5050
Library
5151
-------
5252

53+
- Issue #23268: Fixed bugs in the comparison of ipaddress classes.
54+
5355
- Issue #21408: Removed incorrect implementations of __ne__() which didn't
5456
returned NotImplemented if __eq__() returned NotImplemented. The default
5557
__ne__() now works correctly.

0 commit comments

Comments
 (0)