Add a moved function helper
This is useful for moving functions to newer names or newer modules/locations and retaining the old function so that the old function proxies to the new function and emits a deprecation warning when it is called. Also fixes how the 'get_callable_name' needs to filter for none, as it appears that when ran under sphinx the '__module__' attribute is set to none and this causes issues when joining into a string. Change-Id: I290f1b71c141c6647da1750aec348ea590a8d9bd
This commit is contained in:
parent
f6d19baf86
commit
f0f1fce2a2
@ -164,4 +164,10 @@ def get_callable_name(function):
|
||||
parts = (im_class.__module__, im_class.__qualname__)
|
||||
except AttributeError:
|
||||
parts = (im_class.__module__, im_class.__name__)
|
||||
return '.'.join(parts)
|
||||
# When running under sphinx it appears this can be none? if so just
|
||||
# don't include it...
|
||||
mod, rest = (parts[0], parts[1:])
|
||||
if not mod:
|
||||
return '.'.join(rest)
|
||||
else:
|
||||
return '.'.join(parts)
|
||||
|
@ -22,7 +22,8 @@ from debtcollector import _utils
|
||||
|
||||
_KIND_MOVED_PREFIX_TPL = "%s '%s' has moved to '%s'"
|
||||
_CLASS_MOVED_PREFIX_TPL = "Class '%s' has moved to '%s'"
|
||||
_MOVED_METHOD_POSTFIX = "()"
|
||||
_MOVED_CALLABLE_POSTFIX = "()"
|
||||
_FUNC_MOVED_PREFIX_TPL = "Function '%s' has moved to '%s'"
|
||||
|
||||
|
||||
def _moved_decorator(kind, new_attribute_name, message=None,
|
||||
@ -56,23 +57,52 @@ def _moved_decorator(kind, new_attribute_name, message=None,
|
||||
return decorator
|
||||
|
||||
|
||||
def moved_function(new_func, old_func_name, old_module_name,
|
||||
message=None, version=None, removal_version=None,
|
||||
stacklevel=3, category=None):
|
||||
"""Deprecates a function that was moved to another location.
|
||||
|
||||
This generates a wrapper around ``new_func`` that will emit a deprecation
|
||||
warning when called. The warning message will include the new location
|
||||
to obtain the function from.
|
||||
"""
|
||||
new_func_full_name = _utils.get_callable_name(new_func)
|
||||
new_func_full_name += _MOVED_CALLABLE_POSTFIX
|
||||
old_func_full_name = ".".join([old_module_name, old_func_name])
|
||||
old_func_full_name += _MOVED_CALLABLE_POSTFIX
|
||||
prefix = _FUNC_MOVED_PREFIX_TPL % (old_func_full_name, new_func_full_name)
|
||||
out_message = _utils.generate_message(prefix,
|
||||
message=message, version=version,
|
||||
removal_version=removal_version)
|
||||
|
||||
@six.wraps(new_func)
|
||||
def old_new_func(*args, **kwargs):
|
||||
_utils.deprecation(out_message, stacklevel=stacklevel,
|
||||
category=category)
|
||||
return new_func(*args, **kwargs)
|
||||
|
||||
old_new_func.__name__ = old_func_name
|
||||
old_new_func.__module__ = old_module_name
|
||||
return old_new_func
|
||||
|
||||
|
||||
def moved_method(new_method_name, message=None,
|
||||
version=None, removal_version=None, stacklevel=3,
|
||||
category=None):
|
||||
"""Decorates a *instance* method that was moved to another location."""
|
||||
if not new_method_name.endswith(_MOVED_METHOD_POSTFIX):
|
||||
new_method_name += _MOVED_METHOD_POSTFIX
|
||||
"""Decorates an *instance* method that was moved to another location."""
|
||||
if not new_method_name.endswith(_MOVED_CALLABLE_POSTFIX):
|
||||
new_method_name += _MOVED_CALLABLE_POSTFIX
|
||||
return _moved_decorator('Method', new_method_name, message=message,
|
||||
version=version, removal_version=removal_version,
|
||||
stacklevel=stacklevel,
|
||||
attr_postfix=_MOVED_METHOD_POSTFIX,
|
||||
attr_postfix=_MOVED_CALLABLE_POSTFIX,
|
||||
category=category)
|
||||
|
||||
|
||||
def moved_property(new_attribute_name, message=None,
|
||||
version=None, removal_version=None, stacklevel=3,
|
||||
category=None):
|
||||
"""Decorates a *instance* property that was moved to another location."""
|
||||
"""Decorates an *instance* property that was moved to another location."""
|
||||
return _moved_decorator('Property', new_attribute_name, message=message,
|
||||
version=version, removal_version=removal_version,
|
||||
stacklevel=stacklevel, category=category)
|
||||
|
@ -91,6 +91,14 @@ def blue_comet():
|
||||
return True
|
||||
|
||||
|
||||
def yellow_sun():
|
||||
"""Yellow."""
|
||||
return True
|
||||
|
||||
|
||||
yellowish_sun = moves.moved_function(yellow_sun, 'yellowish_sun', __name__)
|
||||
|
||||
|
||||
@removals.remove()
|
||||
class EFSF(object):
|
||||
pass
|
||||
@ -217,6 +225,21 @@ class MovedPropertyTest(test_base.TestCase):
|
||||
self.assertEqual(0, len(capture))
|
||||
|
||||
|
||||
class MovedFunctionTest(test_base.TestCase):
|
||||
def test_basics(self):
|
||||
self.assertTrue(yellowish_sun())
|
||||
self.assertTrue(yellow_sun())
|
||||
self.assertEqual("Yellow.", yellowish_sun.__doc__)
|
||||
|
||||
def test_warnings_emitted(self):
|
||||
with warnings.catch_warnings(record=True) as capture:
|
||||
warnings.simplefilter("always")
|
||||
self.assertTrue(yellowish_sun())
|
||||
self.assertEqual(1, len(capture))
|
||||
w = capture[0]
|
||||
self.assertEqual(DeprecationWarning, w.category)
|
||||
|
||||
|
||||
class MovedMethodTest(test_base.TestCase):
|
||||
def test_basics(self):
|
||||
c = KittyKat()
|
||||
|
@ -113,6 +113,32 @@ A basic example to do just this (on a ``__init__`` method):
|
||||
|
||||
__main__:1: DeprecationWarning: Using the 'bleep' argument is deprecated
|
||||
|
||||
Moving a function
|
||||
-----------------
|
||||
|
||||
To change the name or location of a regular function use the
|
||||
:py:func:`~debtcollector.moves.moved_function` function:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> from debtcollector import moves
|
||||
>>> import warnings
|
||||
>>> warnings.simplefilter('always')
|
||||
>>> def new_thing():
|
||||
... return "new thing"
|
||||
...
|
||||
>>> old_thing = moves.moved_function(new_thing, 'old_thing', __name__)
|
||||
>>> new_thing()
|
||||
'new thing'
|
||||
>>> old_thing()
|
||||
'new thing'
|
||||
|
||||
**Expected output:**
|
||||
|
||||
.. testoutput::
|
||||
|
||||
__main__:1: DeprecationWarning: Function '__main__.old_thing()' has moved to '__main__.new_thing()'
|
||||
|
||||
Moving a method
|
||||
---------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user