diff -r 031fc0231f3d Lib/ipaddress.py --- a/Lib/ipaddress.py Thu Jan 15 22:53:21 2015 +0100 +++ b/Lib/ipaddress.py Fri Jan 16 11:36:54 2015 +0200 @@ -563,6 +563,9 @@ class _IPAddressBase(_TotalOrderingMixin except ValueError: cls._report_invalid_netmask(ip_str) + def __reduce__(self): + return self.__class__, (str(self),) + class _BaseAddress(_IPAddressBase): @@ -622,6 +625,9 @@ class _BaseAddress(_IPAddressBase): def _get_address_key(self): return (self._version, self) + def __reduce__(self): + return self.__class__, (self._ip,) + class _BaseNetwork(_IPAddressBase): @@ -1442,6 +1448,8 @@ class IPv4Interface(IPv4Address): def __hash__(self): return self._ip ^ self._prefixlen ^ int(self.network.network_address) + __reduce__ = _IPAddressBase.__reduce__ + @property def ip(self): return IPv4Address(self._ip) @@ -2130,6 +2138,8 @@ class IPv6Interface(IPv6Address): def __hash__(self): return self._ip ^ self._prefixlen ^ int(self.network.network_address) + __reduce__ = _IPAddressBase.__reduce__ + @property def ip(self): return IPv6Address(self._ip) diff -r 031fc0231f3d Lib/test/test_ipaddress.py --- a/Lib/test/test_ipaddress.py Thu Jan 15 22:53:21 2015 +0100 +++ b/Lib/test/test_ipaddress.py Fri Jan 16 11:36:54 2015 +0200 @@ -8,6 +8,7 @@ import unittest import re import contextlib import operator +import pickle import ipaddress @@ -82,6 +83,13 @@ class CommonTestMixin: self.assertRaises(TypeError, hex, self.factory(1)) self.assertRaises(TypeError, bytes, self.factory(1)) + def pickle_test(self, addr): + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + x = self.factory(addr) + y = pickle.loads(pickle.dumps(x, proto)) + self.assertEqual(y, x) + class CommonTestMixin_v4(CommonTestMixin): @@ -247,6 +255,9 @@ class AddressTestCase_v4(BaseTestCase, C assertBadOctet("257.0.0.0", 257) assertBadOctet("192.168.0.999", 999) + def test_pickle(self): + self.pickle_test('192.0.2.1') + class AddressTestCase_v6(BaseTestCase, CommonTestMixin_v6): factory = ipaddress.IPv6Address @@ -379,6 +390,9 @@ class AddressTestCase_v6(BaseTestCase, C assertBadPart("02001:db8::", "02001") assertBadPart('2001:888888::1', "888888") + def test_pickle(self): + self.pickle_test('2001:db8::') + class NetmaskTestMixin_v4(CommonTestMixin_v4): """Input validation on interfaces and networks is very similar""" @@ -446,6 +460,11 @@ class NetmaskTestMixin_v4(CommonTestMixi class InterfaceTestCase_v4(BaseTestCase, NetmaskTestMixin_v4): factory = ipaddress.IPv4Interface + def test_pickle(self): + self.pickle_test('192.0.2.0/27') + self.pickle_test('192.0.2.0/31') # IPV4LENGTH - 1 + self.pickle_test('192.0.2.0') # IPV4LENGTH + class NetworkTestCase_v4(BaseTestCase, NetmaskTestMixin_v4): factory = ipaddress.IPv4Network @@ -500,6 +519,11 @@ class NetmaskTestMixin_v6(CommonTestMixi assertBadNetmask("::1", "pudding") assertBadNetmask("::", "::") + def test_pickle(self): + self.pickle_test('2001:db8::1000/124') + self.pickle_test('2001:db8::1000/127') # IPV6LENGTH - 1 + self.pickle_test('2001:db8::1000') # IPV6LENGTH + class InterfaceTestCase_v6(BaseTestCase, NetmaskTestMixin_v6): factory = ipaddress.IPv6Interface