decorators in the python standard lib (@deprecated specifically)
Here's some snippet, modified from those cited by Leandro:
import warningsimport functoolsdef deprecated(func): """This is a decorator which can be used to mark functions as deprecated. It will result in a warning being emitted when the function is used.""" @functools.wraps(func) def new_func(*args, **kwargs): warnings.simplefilter('always', DeprecationWarning) # turn off filter warnings.warn("Call to deprecated function {}.".format(func.__name__), category=DeprecationWarning, stacklevel=2) warnings.simplefilter('default', DeprecationWarning) # reset filter return func(*args, **kwargs) return new_func# Examples@deprecateddef some_old_function(x, y): return x + yclass SomeClass: @deprecated def some_old_method(self, x, y): return x + y
Because in some interpreters the first solution exposed (without filter handling) may result in a warning suppression.
Here is another solution:
This decorator (a decorator factory in fact) allow you to give a reason message. It is also more useful to help the developer to diagnose the problem by giving the source filename and line number.
EDIT: This code use Zero's recommendation: it replace warnings.warn_explicit
line by warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
,which prints the function call site rather than the function definition site. It makes debugging easier.
EDIT2: This version allow the developper to specify an optional "reason" message.
import functoolsimport inspectimport warningsstring_types = (type(b''), type(u''))def deprecated(reason): """ This is a decorator which can be used to mark functions as deprecated. It will result in a warning being emitted when the function is used. """ if isinstance(reason, string_types): # The @deprecated is used with a 'reason'. # # .. code-block:: python # # @deprecated("please, use another function") # def old_function(x, y): # pass def decorator(func1): if inspect.isclass(func1): fmt1 = "Call to deprecated class {name} ({reason})." else: fmt1 = "Call to deprecated function {name} ({reason})." @functools.wraps(func1) def new_func1(*args, **kwargs): warnings.simplefilter('always', DeprecationWarning) warnings.warn( fmt1.format(name=func1.__name__, reason=reason), category=DeprecationWarning, stacklevel=2 ) warnings.simplefilter('default', DeprecationWarning) return func1(*args, **kwargs) return new_func1 return decorator elif inspect.isclass(reason) or inspect.isfunction(reason): # The @deprecated is used without any 'reason'. # # .. code-block:: python # # @deprecated # def old_function(x, y): # pass func2 = reason if inspect.isclass(func2): fmt2 = "Call to deprecated class {name}." else: fmt2 = "Call to deprecated function {name}." @functools.wraps(func2) def new_func2(*args, **kwargs): warnings.simplefilter('always', DeprecationWarning) warnings.warn( fmt2.format(name=func2.__name__), category=DeprecationWarning, stacklevel=2 ) warnings.simplefilter('default', DeprecationWarning) return func2(*args, **kwargs) return new_func2 else: raise TypeError(repr(type(reason)))
You can use this decorator for functions, methods and classes.
Here is a simple example:
@deprecated("use another function")def some_old_function(x, y): return x + yclass SomeClass(object): @deprecated("use another method") def some_old_method(self, x, y): return x + y@deprecated("use another class")class SomeOldClass(object): passsome_old_function(5, 3)SomeClass().some_old_method(8, 9)SomeOldClass()
You'll get:
deprecated_example.py:59: DeprecationWarning: Call to deprecated function or method some_old_function (use another function). some_old_function(5, 3)deprecated_example.py:60: DeprecationWarning: Call to deprecated function or method some_old_method (use another method). SomeClass().some_old_method(8, 9)deprecated_example.py:61: DeprecationWarning: Call to deprecated class SomeOldClass (use another class). SomeOldClass()
EDIT3: This decorator is now part of the Deprecated library:
New stable release v1.2.13 🎉
As muon suggested, you can install the deprecation
package for this.
The
deprecation
library provides adeprecated
decorator and afail_if_not_removed
decorator for your tests.
Installation
pip install deprecation
Example Usage
import deprecation@deprecation.deprecated(deprecated_in="1.0", removed_in="2.0", current_version=__version__, details="Use the bar function instead")def foo(): """Do some stuff""" return 1
See http://deprecation.readthedocs.io/ for the full documentation.