Ticket #4804: deprecate-methods.patch

File deprecate-methods.patch, 5.1 KB (added by Julian Berman, 6 years ago)
  • twisted/python/deprecate.py

    diff --git a/twisted/python/deprecate.py b/twisted/python/deprecate.py
    index 7d71b2a..fb1400b 100644
    a b __all__ = [ 
    5858import sys, inspect
    5959from warnings import warn, warn_explicit
    6060from dis import findlinestarts
    61 from functools import wraps
     61from functools import update_wrapper
    6262
    6363from twisted.python.versions import getVersionString
    6464
    def _fullyQualifiedName(obj): 
    7575
    7676    @rtype: C{str}.
    7777    """
     78
     79    if isinstance(obj, _Deprecated):
     80        obj = obj.callable
     81
    7882    try:
    7983        name = obj.__qualname__
    8084    except AttributeError:
    def _appendToDocstring(thingWithDoc, textToAppend): 
    237241
    238242
    239243
     244class _Deprecated(object):
     245    """
     246    A deprecated callable.
     247
     248    """
     249
     250    def __init__(self, version, callable, replacement=None):
     251        self.callable = callable
     252        self.replacement = replacement
     253        self.deprecatedVersion = version
     254
     255        update_wrapper(self, callable)
     256        _appendToDocstring(
     257            self, _getDeprecationDocstring(version, replacement))
     258
     259
     260    def __call__(self, *args, **kwargs):
     261        warningString = getDeprecationWarningString(
     262            self.callable, self.deprecatedVersion, None, self.replacement)
     263        warn(
     264            warningString,
     265            DeprecationWarning,
     266            stacklevel=2)
     267        return self.callable(*args, **kwargs)
     268
     269
     270    def __get__(self, *args, **kwargs):
     271        callableDescriptor = getattr(self.callable, "__get__", None)
     272        if callableDescriptor is None:
     273            return self.callable
     274        return self.__class__(
     275            version=self.deprecatedVersion,
     276            replacement=self.replacement,
     277            callable=callableDescriptor(*args, **kwargs))
     278
     279
     280
    240281def deprecated(version, replacement=None):
    241282    """
    242283    Return a decorator that marks callables as deprecated.
    def deprecated(version, replacement=None): 
    259300        """
    260301        Decorator that marks C{function} as deprecated.
    261302        """
    262         warningString = getDeprecationWarningString(
    263             function, version, None, replacement)
    264 
    265         @wraps(function)
    266         def deprecatedFunction(*args, **kwargs):
    267             warn(
    268                 warningString,
    269                 DeprecationWarning,
    270                 stacklevel=2)
    271             return function(*args, **kwargs)
    272 
    273         _appendToDocstring(deprecatedFunction,
    274                            _getDeprecationDocstring(version, replacement))
    275         deprecatedFunction.deprecatedVersion = version
    276         return deprecatedFunction
    277303
     304        return _Deprecated(
     305            callable=function, version=version, replacement=replacement)
    278306    return deprecationDecorator
    279307
    280308
  • twisted/python/test/test_deprecate.py

    diff --git a/twisted/python/test/test_deprecate.py b/twisted/python/test/test_deprecate.py
    index 1b4ebd1..e869ad8 100644
    a b class TestDeprecationWarnings(SynchronousTestCase): 
    587587            simplefilter("always")
    588588            addStackLevel()
    589589            self.assertEqual(caught[0].category, DeprecationWarning)
    590             self.assertEqual(str(caught[0].message), getDeprecationWarningString(dummyCallable, version))
     590            self.assertEqual(
     591                str(caught[0].message),
     592                getDeprecationWarningString(dummyCallable, version))
    591593            # rstrip in case .pyc/.pyo
    592             self.assertEqual(caught[0].filename.rstrip('co'), __file__.rstrip('co'))
     594            self.assertEqual(
     595                caught[0].filename.rstrip('co'), __file__.rstrip('co'))
    593596
    594597
    595598    def test_deprecatedPreservesName(self):
    class TestDeprecationWarnings(SynchronousTestCase): 
    722725            "    " % (__name__,))
    723726
    724727
     728    def test_deprecatedMethod(self):
     729        """
     730        L{deprecated} can deprecate descriptors, including functions within
     731        class bodies, and will reflect the proper qualified name of the
     732        descriptor when it is accessed on an instance.
     733        """
     734        version = Version('Twisted', 8, 0, 0)
     735
     736        class SomeClassWithADeprecatedMethod(object):
     737            """
     738            I have a method that has been deprecated.
     739            """
     740            @deprecated(version)
     741            def deprecatedMethod(self):
     742                """
     743                I am a method that has been deprecated.
     744                """
     745                return 12
     746
     747        instance = SomeClassWithADeprecatedMethod()
     748        with catch_warnings(record=True) as caught:
     749            simplefilter("always")
     750            self.assertEqual(instance.deprecatedMethod(), 12)
     751            self.assertEqual(caught[0].category, DeprecationWarning)
     752            self.assertEqual(
     753                str(caught[0].message),
     754                getDeprecationWarningString(instance.deprecatedMethod, version))
     755            # rstrip in case .pyc/.pyo
     756            self.assertEqual(
     757                caught[0].filename.rstrip('co'), __file__.rstrip('co'))
     758
     759
     760    def test_deprecatedMethodWithReplacement(self):
     761        pass
     762
     763
    725764
    726765class TestAppendToDocstring(SynchronousTestCase):
    727766    """