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

Skip to content

Commit ffd48c9

Browse files
Issue #23268: Fixed bugs in the comparison of ipaddress classes.
2 parents 34af502 + f186e12 commit ffd48c9

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
@@ -382,40 +382,7 @@ def get_mixed_type_key(obj):
382382
return NotImplemented
383383

384384

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

420387
"""The mother class."""
421388

@@ -567,6 +534,7 @@ def __reduce__(self):
567534
return self.__class__, (str(self),)
568535

569536

537+
@functools.total_ordering
570538
class _BaseAddress(_IPAddressBase):
571539

572540
"""A generic IP object.
@@ -586,12 +554,11 @@ def __eq__(self, other):
586554
return NotImplemented
587555

588556
def __lt__(self, other):
557+
if not isinstance(other, _BaseAddress):
558+
return NotImplemented
589559
if self._version != other._version:
590560
raise TypeError('%s and %s are not of the same version' % (
591561
self, other))
592-
if not isinstance(other, _BaseAddress):
593-
raise TypeError('%s and %s are not of the same type' % (
594-
self, other))
595562
if self._ip != other._ip:
596563
return self._ip < other._ip
597564
return False
@@ -624,6 +591,7 @@ def __reduce__(self):
624591
return self.__class__, (self._ip,)
625592

626593

594+
@functools.total_ordering
627595
class _BaseNetwork(_IPAddressBase):
628596

629597
"""A generic IP network object.
@@ -673,12 +641,11 @@ def __getitem__(self, n):
673641
return self._address_class(broadcast + n)
674642

675643
def __lt__(self, other):
644+
if not isinstance(other, _BaseNetwork):
645+
return NotImplemented
676646
if self._version != other._version:
677647
raise TypeError('%s and %s are not of the same version' % (
678648
self, other))
679-
if not isinstance(other, _BaseNetwork):
680-
raise TypeError('%s and %s are not of the same type' % (
681-
self, other))
682649
if self.network_address != other.network_address:
683650
return self.network_address < other.network_address
684651
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 pickle
1213
import ipaddress
@@ -552,6 +553,20 @@ def test_ip_network(self):
552553
self.assertFactoryError(ipaddress.ip_network, "network")
553554

554555

556+
@functools.total_ordering
557+
class LargestObject:
558+
def __eq__(self, other):
559+
return isinstance(other, LargestObject)
560+
def __lt__(self, other):
561+
return False
562+
563+
@functools.total_ordering
564+
class SmallestObject:
565+
def __eq__(self, other):
566+
return isinstance(other, SmallestObject)
567+
def __gt__(self, other):
568+
return False
569+
555570
class ComparisonTests(unittest.TestCase):
556571

557572
v4addr = ipaddress.IPv4Address(1)
@@ -605,6 +620,28 @@ def test_mixed_type_ordering(self):
605620
self.assertRaises(TypeError, lambda: lhs <= rhs)
606621
self.assertRaises(TypeError, lambda: lhs >= rhs)
607622

623+
def test_foreign_type_ordering(self):
624+
other = object()
625+
smallest = SmallestObject()
626+
largest = LargestObject()
627+
for obj in self.objects:
628+
with self.assertRaises(TypeError):
629+
obj < other
630+
with self.assertRaises(TypeError):
631+
obj > other
632+
with self.assertRaises(TypeError):
633+
obj <= other
634+
with self.assertRaises(TypeError):
635+
obj >= other
636+
self.assertTrue(obj < largest)
637+
self.assertFalse(obj > largest)
638+
self.assertTrue(obj <= largest)
639+
self.assertFalse(obj >= largest)
640+
self.assertFalse(obj < smallest)
641+
self.assertTrue(obj > smallest)
642+
self.assertFalse(obj <= smallest)
643+
self.assertTrue(obj >= smallest)
644+
608645
def test_mixed_type_key(self):
609646
# with get_mixed_type_key, you can sort addresses and network.
610647
v4_ordered = [self.v4addr, self.v4net, self.v4intf]
@@ -625,7 +662,7 @@ def test_incompatible_versions(self):
625662
v4addr = ipaddress.ip_address('1.1.1.1')
626663
v4net = ipaddress.ip_network('1.1.1.1')
627664
v6addr = ipaddress.ip_address('::1')
628-
v6net = ipaddress.ip_address('::1')
665+
v6net = ipaddress.ip_network('::1')
629666

630667
self.assertRaises(TypeError, v4addr.__lt__, v6addr)
631668
self.assertRaises(TypeError, v4addr.__gt__, v6addr)
@@ -1383,10 +1420,10 @@ def testNetworkComparison(self):
13831420
unsorted = [ip4, ip1, ip3, ip2]
13841421
unsorted.sort()
13851422
self.assertEqual(sorted, unsorted)
1386-
self.assertRaises(TypeError, ip1.__lt__,
1387-
ipaddress.ip_address('10.10.10.0'))
1388-
self.assertRaises(TypeError, ip2.__lt__,
1389-
ipaddress.ip_address('10.10.10.0'))
1423+
self.assertIs(ip1.__lt__(ipaddress.ip_address('10.10.10.0')),
1424+
NotImplemented)
1425+
self.assertIs(ip2.__lt__(ipaddress.ip_address('10.10.10.0')),
1426+
NotImplemented)
13901427

13911428
# <=, >=
13921429
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
@@ -218,6 +218,8 @@ Core and Builtins
218218
Library
219219
-------
220220

221+
- Issue #23268: Fixed bugs in the comparison of ipaddress classes.
222+
221223
- Issue #21408: Removed incorrect implementations of __ne__() which didn't
222224
returned NotImplemented if __eq__() returned NotImplemented. The default
223225
__ne__() now works correctly.

0 commit comments

Comments
 (0)