Aqui está outra solução:
Este decorador (uma fábrica de decoradores de fato) permite que você dê uma mensagem de razão . Também é mais útil ajudar o desenvolvedor a diagnosticar o problema, fornecendo o nome do arquivo de origem e o número da linha .
EDIT : este código usa a recomendação de Zero: ele substitui a warnings.warn_explicit
linha por warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
, que imprime o site de chamada de função em vez do site de definição de função. Isso facilita a depuração.
EDIT2 : Esta versão permite que o desenvolvedor especifique uma mensagem "motivo" opcional.
import functools
import inspect
import warnings
string_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)))
Você pode usar este decorador para funções , métodos e classes .
Aqui está um exemplo simples:
@deprecated("use another function")
def some_old_function(x, y):
return x + y
class SomeClass(object):
@deprecated("use another method")
def some_old_method(self, x, y):
return x + y
@deprecated("use another class")
class SomeOldClass(object):
pass
some_old_function(5, 3)
SomeClass().some_old_method(8, 9)
SomeOldClass()
Você terá:
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: Este decorador agora faz parte da biblioteca Reprovada:
Nova versão estável v1.2.10 🎉