Index: twisted/python/compat.py =================================================================== --- twisted/python/compat.py (revision 38074) +++ twisted/python/compat.py (working copy) @@ -30,108 +30,8 @@ -def inet_pton(af, addr): - if af == socket.AF_INET: - return socket.inet_aton(addr) - elif af == getattr(socket, 'AF_INET6', 'AF_INET6'): - if [x for x in addr if x not in string.hexdigits + ':.']: - raise ValueError("Illegal characters: %r" % (''.join(x),)) - parts = addr.split(':') - elided = parts.count('') - ipv4Component = '.' in parts[-1] - if len(parts) > (8 - ipv4Component) or elided > 3: - raise ValueError("Syntactically invalid address") - - if elided == 3: - return '\x00' * 16 - - if elided: - zeros = ['0'] * (8 - len(parts) - ipv4Component + elided) - - if addr.startswith('::'): - parts[:2] = zeros - elif addr.endswith('::'): - parts[-2:] = zeros - else: - idx = parts.index('') - parts[idx:idx+1] = zeros - - if len(parts) != 8 - ipv4Component: - raise ValueError("Syntactically invalid address") - else: - if len(parts) != (8 - ipv4Component): - raise ValueError("Syntactically invalid address") - - if ipv4Component: - if parts[-1].count('.') != 3: - raise ValueError("Syntactically invalid address") - rawipv4 = socket.inet_aton(parts[-1]) - unpackedipv4 = struct.unpack('!HH', rawipv4) - parts[-1:] = [hex(x)[2:] for x in unpackedipv4] - - parts = [int(x, 16) for x in parts] - return struct.pack('!8H', *parts) - else: - raise socket.error(97, 'Address family not supported by protocol') - -def inet_ntop(af, addr): - if af == socket.AF_INET: - return socket.inet_ntoa(addr) - elif af == socket.AF_INET6: - if len(addr) != 16: - raise ValueError("address length incorrect") - parts = struct.unpack('!8H', addr) - curBase = bestBase = None - for i in range(8): - if not parts[i]: - if curBase is None: - curBase = i - curLen = 0 - curLen += 1 - else: - if curBase is not None: - if bestBase is None or curLen > bestLen: - bestBase = curBase - bestLen = curLen - curBase = None - if curBase is not None and (bestBase is None or curLen > bestLen): - bestBase = curBase - bestLen = curLen - parts = [hex(x)[2:] for x in parts] - if bestBase is not None: - parts[bestBase:bestBase + bestLen] = [''] - if parts[0] == '': - parts.insert(0, '') - if parts[-1] == '': - parts.insert(len(parts) - 1, '') - return ':'.join(parts) - else: - raise socket.error(97, 'Address family not supported by protocol') - -try: - socket.AF_INET6 -except AttributeError: - socket.AF_INET6 = 'AF_INET6' - -try: - socket.inet_pton(socket.AF_INET6, "::") -except (AttributeError, NameError, socket.error): - socket.inet_pton = inet_pton - socket.inet_ntop = inet_ntop - - -adict = dict - - - -if _PY3: - # These are actually useless in Python 2 as well, but we need to go - # through deprecation process there (ticket #5895): - del adict, inet_pton, inet_ntop - - set = set frozenset = frozenset @@ -404,7 +304,111 @@ @rtype: C{bytes} """ +# These import are here because of the circular dependency +# between compat and the Version module +from twisted.python.deprecate import deprecated, deprecatedModuleAttribute +from twisted.python.versions import Version +@deprecated(Version("Twisted", 13, 1, 0), socket.inet_pton) +def inet_pton(af, addr): + if af == socket.AF_INET: + return socket.inet_aton(addr) + elif af == getattr(socket, 'AF_INET6', 'AF_INET6'): + if [x for x in addr if x not in string.hexdigits + ':.']: + raise ValueError("Illegal characters: %r" % (''.join(x),)) + + parts = addr.split(':') + elided = parts.count('') + ipv4Component = '.' in parts[-1] + + if len(parts) > (8 - ipv4Component) or elided > 3: + raise ValueError("Syntactically invalid address") + + if elided == 3: + return '\x00' * 16 + + if elided: + zeros = ['0'] * (8 - len(parts) - ipv4Component + elided) + + if addr.startswith('::'): + parts[:2] = zeros + elif addr.endswith('::'): + parts[-2:] = zeros + else: + idx = parts.index('') + parts[idx:idx+1] = zeros + + if len(parts) != 8 - ipv4Component: + raise ValueError("Syntactically invalid address") + else: + if len(parts) != (8 - ipv4Component): + raise ValueError("Syntactically invalid address") + + if ipv4Component: + if parts[-1].count('.') != 3: + raise ValueError("Syntactically invalid address") + rawipv4 = socket.inet_aton(parts[-1]) + unpackedipv4 = struct.unpack('!HH', rawipv4) + parts[-1:] = [hex(x)[2:] for x in unpackedipv4] + + parts = [int(x, 16) for x in parts] + return struct.pack('!8H', *parts) + else: + raise socket.error(97, 'Address family not supported by protocol') + +@deprecated(Version("Twisted", 13, 1, 0), socket.inet_ntop) +def inet_ntop(af, addr): + if af == socket.AF_INET: + return socket.inet_ntoa(addr) + elif af == socket.AF_INET6: + if len(addr) != 16: + raise ValueError("address length incorrect") + parts = struct.unpack('!8H', addr) + curBase = bestBase = None + for i in range(8): + if not parts[i]: + if curBase is None: + curBase = i + curLen = 0 + curLen += 1 + else: + if curBase is not None: + if bestBase is None or curLen > bestLen: + bestBase = curBase + bestLen = curLen + curBase = None + if curBase is not None and (bestBase is None or curLen > bestLen): + bestBase = curBase + bestLen = curLen + parts = [hex(x)[2:] for x in parts] + if bestBase is not None: + parts[bestBase:bestBase + bestLen] = [''] + if parts[0] == '': + parts.insert(0, '') + if parts[-1] == '': + parts.insert(len(parts) - 1, '') + return ':'.join(parts) + else: + raise socket.error(97, 'Address family not supported by protocol') + +try: + socket.AF_INET6 +except AttributeError: + socket.AF_INET6 = 'AF_INET6' + +try: + socket.inet_pton(socket.AF_INET6, "::") +except (AttributeError, NameError, socket.error): + socket.inet_pton = inet_pton + socket.inet_ntop = inet_ntop + + +adict = dict +deprecatedModuleAttribute( + Version("Twisted", 13, 1, 0), + "adict is useless in Python 2.", __name__, "adict") + + __all__ = [ "reraise", "execfile", Index: twisted/test/test_compat.py =================================================================== --- twisted/test/test_compat.py (revision 38074) +++ twisted/test/test_compat.py (working copy) @@ -8,14 +8,18 @@ from __future__ import division, absolute_import -import socket, sys, traceback +import socket +import sys +import traceback from twisted.trial import unittest +from twisted.python import compat from twisted.python.compat import reduce, execfile, _PY3 from twisted.python.compat import comparable, cmp, nativeString, networkString from twisted.python.compat import unicode as unicodeCompat, lazyByteSlice from twisted.python.compat import reraise, NativeStringIO, iterbytes, intToBytes +from twisted.python.versions import Version from twisted.python.filepath import FilePath @@ -621,3 +625,62 @@ """ data = b'123XYZ' self.assertEqual(bytes(lazyByteSlice(data, 2, 3)), data[2:5]) + + +class DeprecationTestCase(unittest.TestCase): + """ + Test deprecations in twisted.python.compat + """ + + def test_inet_ntop(self): + """ + Test deprecation of L{compat.inet_ntop}. + """ + self.callDeprecated( + (Version("Twisted", 13, 1, 0), socket.inet_ntop), + compat.inet_ntop, socket.AF_INET, "\x01\x00\x01\x00") + + def test_inet_pton(self): + """ + Test deprecation of L{compat.inet_pton}. + """ + self.callDeprecated( + (Version("Twisted", 13, 1, 0), socket.inet_pton), + compat.inet_pton, socket.AF_INET, "0.0.0.0") + + + def lookForDeprecationWarning(self, testMethod, attributeName, warningMsg): + """ + Test deprecation of attribute 'compat.attributeName' by calling + 'compat.testMethod' and verifying the warning message + 'compat.warningMsg' + + @param testMethod: Name of the offending function to be used with + flushWarnings + @type testmethod: C{str} + + @param attributeName: Name of attribute to be checked for deprecation + @type attributeName: C{str} + + @param warningMsg: Deprecation warning message + @type warningMsg: C{str} + """ + warningsShown = self.flushWarnings([testMethod]) + self.assertEqual(len(warningsShown), 1) + self.assertIdentical(warningsShown[0]['category'], DeprecationWarning) + self.assertEqual( + warningsShown[0]['message'], + "twisted.python.compat." + attributeName + " " + "was deprecated in Twisted 13.1.0: " + warningMsg + ".") + + + def test_adict(self): + """ + Test deprecation of L{compat.adict}. + """ + a = compat.adict + del a + self.lookForDeprecationWarning( + self.test_adict, "adict", + "adict is useless in Python 2") + Index: twisted/topfiles/5895.removal =================================================================== --- twisted/topfiles/5895.removal (revision 0) +++ twisted/topfiles/5895.removal (working copy) @@ -0,0 +1,4 @@ +twisted.python.compat.adict is now deprecated. +twisted.python.compat.inet_pton is now deprecated in favor of socket.inet_pton from the standard library. +twisted.python.compat.inet_ntop is now deprecated in favor of socket.inet_ntop from the standard library. +