tantale / deprecated

Python @deprecated decorator to deprecate old python classes, functions or methods.
MIT License
298 stars 32 forks source link

`action="once"` not working #64

Closed eliasmistler closed 1 year ago

eliasmistler commented 1 year ago

Expected Behavior

When setting the action="once" option, the deprecation warning should only be logged once.

from deprecated import deprecated

@deprecated(action='once')
def my_func():
    print("running the old func")

if __name__ == "__main__":
    my_func()
    my_func()
    my_func()

Actual Behavior

The deprecation warning is displayed every time the function is called:

DeprecationWarning: Call to deprecated function (or staticmethod) my_func.
  my_func()
DeprecationWarning: Call to deprecated function (or staticmethod) my_func.
  my_func()
DeprecationWarning: Call to deprecated function (or staticmethod) my_func.
  my_func()
running the old func
running the old func
running the old func

Environment

tantale commented 1 year ago

I agree, it's a problem, but not unique to the Deprecated library.

The "action" parameter is used with the warnings.filterwarnings() function to define the behavior of warnings in a specific part of the Python code.

The value "once" indicates that the warning should only be reported the first time it is encountered. After that, the warning will no longer be signaled even if it occurs again later.

When specifying the action at the deprecated function level, we use a context manager that allows the warning behavior to be modified locally to the function and thus restored at the end of the function call. This is required so as not to modify the application's global context. Indeed, in the case of "once", this has the effect of restoring the internal call counter, so a warning message is issued each time.

One way around this problem is not to specify the parameter at all, as "once" is the default value.