Lifecycle Management#
As Sopel grows and evolves, sometimes it needs to say goodbye to obsolete code and replace it. The solution can be new (and hopefully better) code, switching to an external library, or maybe putting the feature into an external plugin.
In any case, Sopel will always try to mark as deprecated what will be removed, indicating when it was deprecated, and when it should be removed. The goal is to help Sopel developers and plugin authors understand what must be done to adapt their code to a future version of Sopel:
Deprecated since 8.0, will be removed in 9.0: sopel.module has been
replaced by sopel.plugin
File "/home/exirel/dev/sopel/sopel/module.py", line 46, in <module>
deprecated(
This example above shows a deprecation warning for the sopel.module
module
that is deprecated: it shows when it was deprecated (Sopel 8.0), when it will
be removed (Sopel 9.0), and how to fix that warning (use sopel.plugin
).
Although this feature is primarily for use by Sopel developers, plugin authors
can also take advantage of it with the sopel.lifecycle.deprecated()
function documented below.
sopel.lifecycle#
Deprecation module for Sopel developers and plugin authors.
New in version 8.0: Previously in sopel.tools
, the deprecated()
function has been
moved to this newly created module, as it can be used in every part of the
Sopel codebase, including sopel.tools
itself.
- sopel.lifecycle.deprecated(
- reason: str | Callable | None = None,
- version: str | None = None,
- removed_in: str | None = None,
- warning_in: str | None = None,
- stack_frame: int = -1,
- func: Callable | None = None,
Decorator to mark deprecated functions in Sopel’s API
- Parameters:
reason – optional text added to the deprecation warning
version – optional version number when the decorated function is deprecated
removed_in – optional version number when the deprecated function will be removed
warning_in – optional version number when the decorated function should start emitting a warning when called
stack_frame – optional stack frame to output; defaults to
-1
; should almost always be negativefunc – deprecated function
- Returns:
a callable that depends on how the decorator is called; either the decorated function, or a decorator with the appropriate parameters
Any time the decorated
func
is called, a deprecation warning will be logged, with the last frame of the traceback. The optionalwarning_in
argument suppresses the warning on Sopel versions older than that, allowing for multi-stage deprecation timelines.The decorator can be used with or without arguments:
from sopel.lifecycle import deprecated @deprecated def func1(): print('func 1') @deprecated() def func2(): print('func 2') @deprecated(reason='obsolete', version='7.0', removed_in='8.0') def func3(): print('func 3')
which will output the following in a console:
>>> func1() Deprecated: func1 File "<stdin>", line 1, in <module> func 1 >>> func2() Deprecated: func2 File "<stdin>", line 1, in <module> func 2 >>> func3() Deprecated since 7.0, will be removed in 8.0: obsolete File "<stdin>", line 1, in <module> func 3
The
stack_frame
argument can be used to choose which stack frame is logged along with the message text. By default, this decorator logs the most recent stack frame (the last entry in the list,-1
), corresponding to where the decorated function itself was called. However, in certain cases such as deprecating conditional behavior within an object constructor, it can be useful to show a less recent stack frame instead.Note
This decorator can be also used on callables that are not functions, such as classes and callable objects.
New in version 7.0: Parameters
reason
,version
, andremoved_in
.New in version 7.1: The
warning_in
andstack_frame
parameters.Changed in version 8.0: Moved out of
sopel.tools
to resolve circular dependency issues.