We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Deprecation warnings should be printed for dev versions
### Description

`sopel.logger.get_logger` is [marked](https://github.com/sopel-irc/sopel/blob/eac71b07d60d3bea68fe3f1242e88654594a7df5/sopel/logger.py#L164) as [deprecated](https://sopel.chat/docs/api.html#sopel.logger.get_logger), but no deprecation warning is raised when it's used.

### Reproduction steps

1. Create a Sopel plugin with `from sopel.logger import get_logger; LOGGER=get_logger(__name__)`
2. Start Sopel with that plugin
3. No deprecation warnings are produced

### Expected behavior

A deprecation warning is produced

### Relevant logs

```shell
Tested by replacing the logger in admin.py.

[2022-06-11 13:00:50,089] sopel.bot            INFO     - Plugin loaded: ping
[2022-06-11 13:00:50,090] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.join []>
[2022-06-11 13:00:50,090] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.tmpjoin []>
[2022-06-11 13:00:50,091] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.part []>
[2022-06-11 13:00:50,091] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.tmppart []>
[2022-06-11 13:00:50,092] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.chanlist [channels]>
[2022-06-11 13:00:50,092] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.restart []>
[2022-06-11 13:00:50,093] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.quit []>
[2022-06-11 13:00:50,093] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.raw []>
[2022-06-11 13:00:50,094] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.say [msg]>
[2022-06-11 13:00:50,094] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.me []>
[2022-06-11 13:00:50,094] sopel.plugins.rules  DEBUG    - Rule registered: <Rule admin.invite_join (1)>
[2022-06-11 13:00:50,094] sopel.plugins.rules  DEBUG    - Rule registered: <Rule admin.hold_ground (1)>
[2022-06-11 13:00:50,095] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.mode []>
[2022-06-11 13:00:50,095] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.set []>
[2022-06-11 13:00:50,096] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.unset []>
[2022-06-11 13:00:50,096] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.save []>
[2022-06-11 13:00:50,096] sopel.bot            INFO     - Plugin loaded: admin
```


### Notes

_No response_

### Sopel version

eac71b07d60d3bea68fe3f1242e88654594a7df5

### Installation method

`pip install`

### Python version

3.10.4

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sopel/lifecycle.py`
Content:
```
1 """Deprecation module for Sopel developers and plugin authors.
2 
3 .. versionadded:: 8.0
4 
5     Previously in :mod:`sopel.tools`, the :func:`deprecated` function has been
6     moved to this newly created module, as it can be used in every part of the
7     Sopel codebase, including :mod:`sopel.tools` itself.
8 
9 """
10 from __future__ import annotations
11 
12 import functools
13 import inspect
14 import logging
15 import traceback
16 from typing import Callable, Optional
17 
18 from packaging.version import parse as parse_version
19 
20 from sopel import __version__
21 
22 
23 def deprecated(
24     reason: Optional[str] = None,
25     version: Optional[str] = None,
26     removed_in: Optional[str] = None,
27     warning_in: Optional[str] = None,
28     stack_frame: int = -1,
29     func: Optional[Callable] = None,
30 ):
31     """Decorator to mark deprecated functions in Sopel's API
32 
33     :param reason: optional text added to the deprecation warning
34     :param version: optional version number when the decorated function
35                     is deprecated
36     :param removed_in: optional version number when the deprecated function
37                        will be removed
38     :param warning_in: optional version number when the decorated function
39                        should start emitting a warning when called
40     :param stack_frame: optional stack frame to output; defaults to
41                         ``-1``; should almost always be negative
42     :param func: deprecated function
43     :return: a callable that depends on how the decorator is called; either
44              the decorated function, or a decorator with the appropriate
45              parameters
46 
47     Any time the decorated ``func`` is called, a deprecation warning will be
48     logged, with the last frame of the traceback. The optional ``warning_in``
49     argument suppresses the warning on Sopel versions older than that, allowing
50     for multi-stage deprecation timelines.
51 
52     The decorator can be used with or without arguments::
53 
54         from sopel.lifecycle import deprecated
55 
56         @deprecated
57         def func1():
58             print('func 1')
59 
60         @deprecated()
61         def func2():
62             print('func 2')
63 
64         @deprecated(reason='obsolete', version='7.0', removed_in='8.0')
65         def func3():
66             print('func 3')
67 
68     which will output the following in a console::
69 
70         >>> func1()
71         Deprecated: func1
72         File "<stdin>", line 1, in <module>
73         func 1
74         >>> func2()
75         Deprecated: func2
76         File "<stdin>", line 1, in <module>
77         func 2
78         >>> func3()
79         Deprecated since 7.0, will be removed in 8.0: obsolete
80         File "<stdin>", line 1, in <module>
81         func 3
82 
83     The ``stack_frame`` argument can be used to choose which stack frame is
84     logged along with the message text. By default, this decorator logs the
85     most recent stack frame (the last entry in the list, ``-1``), corresponding
86     to where the decorated function itself was called. However, in certain
87     cases such as deprecating conditional behavior within an object
88     constructor, it can be useful to show a less recent stack frame instead.
89 
90     .. note::
91 
92         This decorator can be also used on callables that are not functions,
93         such as classes and callable objects.
94 
95     .. versionadded:: 7.0
96         Parameters ``reason``, ``version``, and ``removed_in``.
97 
98     .. versionadded:: 7.1
99         The ``warning_in`` and ``stack_frame`` parameters.
100 
101     .. versionchanged:: 8.0
102         Moved out of :mod:`sopel.tools` to resolve circular dependency issues.
103 
104     """
105     if not any([reason, version, removed_in, warning_in, func]):
106         # common usage: @deprecated()
107         return deprecated
108 
109     if callable(reason):
110         # common usage: @deprecated
111         return deprecated(func=reason)
112 
113     if func is None:
114         # common usage: @deprecated(message, version, removed_in)
115         def decorator(func):
116             return deprecated(
117                 reason, version, removed_in, warning_in, stack_frame, func)
118         return decorator
119 
120     # now, we have everything we need to have:
121     # - message is not a callable (could be None)
122     # - func is not None
123     # - version and removed_in can be None but that's OK
124     # so now we can return the actual decorated function
125 
126     message = reason or getattr(func, '__name__', '<anonymous-function>')
127 
128     template = 'Deprecated: {message}'
129     if version and removed_in:
130         template = (
131             'Deprecated since {version}, '
132             'will be removed in {removed_in}: '
133             '{message}')
134     elif version:
135         template = 'Deprecated since {version}: {message}'
136     elif removed_in:
137         template = 'Deprecated, will be removed in {removed_in}: {message}'
138 
139     text = template.format(
140         message=message, version=version, removed_in=removed_in)
141 
142     @functools.wraps(func)
143     def deprecated_func(*args, **kwargs):
144         if not (warning_in and
145                 parse_version(warning_in) >= parse_version(__version__)):
146             original_frame = inspect.stack()[-stack_frame]
147             mod = inspect.getmodule(original_frame[0])
148             module_name = None
149             if mod:
150                 module_name = mod.__name__
151             if module_name:
152                 if module_name.startswith('sopel.'):
153                     # core, or core plugin
154                     logger = logging.getLogger(module_name)
155                 else:
156                     # probably a plugin; try to handle most cases sanely
157                     if module_name.startswith('sopel_modules.'):
158                         # namespace package plugins have a prefix, obviously
159                         # they will use Sopel's namespace; other won't
160                         module_name = module_name.replace(
161                             'sopel_modules.',
162                             'sopel.externals.',
163                             1,
164                         )
165                     logger = logging.getLogger(module_name)
166             else:
167                 # don't know the module/plugin name, but we want to make sure
168                 # the log line is still output, so just get *something*
169                 logger = logging.getLogger(__name__)
170 
171             # Format only the desired stack frame
172             trace = traceback.extract_stack()
173             trace_frame = traceback.format_list(trace[:-1])[stack_frame][:-1]
174 
175             # Warn the user
176             logger.warning(text + "\n" + trace_frame)
177 
178         return func(*args, **kwargs)
179 
180     return deprecated_func
181
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sopel/lifecycle.py b/sopel/lifecycle.py
--- a/sopel/lifecycle.py
+++ b/sopel/lifecycle.py
@@ -141,8 +141,10 @@
 
     @functools.wraps(func)
     def deprecated_func(*args, **kwargs):
-        if not (warning_in and
-                parse_version(warning_in) >= parse_version(__version__)):
+        warn_ver = warning_in and parse_version(warning_in).release
+        this_ver = parse_version(__version__).release
+
+        if not (warn_ver and warn_ver >= this_ver):
             original_frame = inspect.stack()[-stack_frame]
             mod = inspect.getmodule(original_frame[0])
             module_name = None

{"golden_diff": "diff --git a/sopel/lifecycle.py b/sopel/lifecycle.py\n--- a/sopel/lifecycle.py\n+++ b/sopel/lifecycle.py\n@@ -141,8 +141,10 @@\n \n     @functools.wraps(func)\n     def deprecated_func(*args, **kwargs):\n-        if not (warning_in and\n-                parse_version(warning_in) >= parse_version(__version__)):\n+        warn_ver = warning_in and parse_version(warning_in).release\n+        this_ver = parse_version(__version__).release\n+\n+        if not (warn_ver and warn_ver >= this_ver):\n             original_frame = inspect.stack()[-stack_frame]\n             mod = inspect.getmodule(original_frame[0])\n             module_name = None\n", "issue": "Deprecation warnings should be printed for dev versions\n### Description\r\n\r\n`sopel.logger.get_logger` is [marked](https://github.com/sopel-irc/sopel/blob/eac71b07d60d3bea68fe3f1242e88654594a7df5/sopel/logger.py#L164) as [deprecated](https://sopel.chat/docs/api.html#sopel.logger.get_logger), but no deprecation warning is raised when it's used.\r\n\r\n### Reproduction steps\r\n\r\n1. Create a Sopel plugin with `from sopel.logger import get_logger; LOGGER=get_logger(__name__)`\r\n2. Start Sopel with that plugin\r\n3. No deprecation warnings are produced\r\n\r\n### Expected behavior\r\n\r\nA deprecation warning is produced\r\n\r\n### Relevant logs\r\n\r\n```shell\r\nTested by replacing the logger in admin.py.\r\n\r\n[2022-06-11 13:00:50,089] sopel.bot            INFO     - Plugin loaded: ping\r\n[2022-06-11 13:00:50,090] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.join []>\r\n[2022-06-11 13:00:50,090] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.tmpjoin []>\r\n[2022-06-11 13:00:50,091] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.part []>\r\n[2022-06-11 13:00:50,091] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.tmppart []>\r\n[2022-06-11 13:00:50,092] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.chanlist [channels]>\r\n[2022-06-11 13:00:50,092] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.restart []>\r\n[2022-06-11 13:00:50,093] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.quit []>\r\n[2022-06-11 13:00:50,093] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.raw []>\r\n[2022-06-11 13:00:50,094] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.say [msg]>\r\n[2022-06-11 13:00:50,094] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.me []>\r\n[2022-06-11 13:00:50,094] sopel.plugins.rules  DEBUG    - Rule registered: <Rule admin.invite_join (1)>\r\n[2022-06-11 13:00:50,094] sopel.plugins.rules  DEBUG    - Rule registered: <Rule admin.hold_ground (1)>\r\n[2022-06-11 13:00:50,095] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.mode []>\r\n[2022-06-11 13:00:50,095] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.set []>\r\n[2022-06-11 13:00:50,096] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.unset []>\r\n[2022-06-11 13:00:50,096] sopel.plugins.rules  DEBUG    - Command registered: <Command admin.save []>\r\n[2022-06-11 13:00:50,096] sopel.bot            INFO     - Plugin loaded: admin\r\n```\r\n\r\n\r\n### Notes\r\n\r\n_No response_\r\n\r\n### Sopel version\r\n\r\neac71b07d60d3bea68fe3f1242e88654594a7df5\r\n\r\n### Installation method\r\n\r\n`pip install`\r\n\r\n### Python version\r\n\r\n3.10.4\n", "before_files": [{"content": "\"\"\"Deprecation module for Sopel developers and plugin authors.\n\n.. versionadded:: 8.0\n\n    Previously in :mod:`sopel.tools`, the :func:`deprecated` function has been\n    moved to this newly created module, as it can be used in every part of the\n    Sopel codebase, including :mod:`sopel.tools` itself.\n\n\"\"\"\nfrom __future__ import annotations\n\nimport functools\nimport inspect\nimport logging\nimport traceback\nfrom typing import Callable, Optional\n\nfrom packaging.version import parse as parse_version\n\nfrom sopel import __version__\n\n\ndef deprecated(\n    reason: Optional[str] = None,\n    version: Optional[str] = None,\n    removed_in: Optional[str] = None,\n    warning_in: Optional[str] = None,\n    stack_frame: int = -1,\n    func: Optional[Callable] = None,\n):\n    \"\"\"Decorator to mark deprecated functions in Sopel's API\n\n    :param reason: optional text added to the deprecation warning\n    :param version: optional version number when the decorated function\n                    is deprecated\n    :param removed_in: optional version number when the deprecated function\n                       will be removed\n    :param warning_in: optional version number when the decorated function\n                       should start emitting a warning when called\n    :param stack_frame: optional stack frame to output; defaults to\n                        ``-1``; should almost always be negative\n    :param func: deprecated function\n    :return: a callable that depends on how the decorator is called; either\n             the decorated function, or a decorator with the appropriate\n             parameters\n\n    Any time the decorated ``func`` is called, a deprecation warning will be\n    logged, with the last frame of the traceback. The optional ``warning_in``\n    argument suppresses the warning on Sopel versions older than that, allowing\n    for multi-stage deprecation timelines.\n\n    The decorator can be used with or without arguments::\n\n        from sopel.lifecycle import deprecated\n\n        @deprecated\n        def func1():\n            print('func 1')\n\n        @deprecated()\n        def func2():\n            print('func 2')\n\n        @deprecated(reason='obsolete', version='7.0', removed_in='8.0')\n        def func3():\n            print('func 3')\n\n    which will output the following in a console::\n\n        >>> func1()\n        Deprecated: func1\n        File \"<stdin>\", line 1, in <module>\n        func 1\n        >>> func2()\n        Deprecated: func2\n        File \"<stdin>\", line 1, in <module>\n        func 2\n        >>> func3()\n        Deprecated since 7.0, will be removed in 8.0: obsolete\n        File \"<stdin>\", line 1, in <module>\n        func 3\n\n    The ``stack_frame`` argument can be used to choose which stack frame is\n    logged along with the message text. By default, this decorator logs the\n    most recent stack frame (the last entry in the list, ``-1``), corresponding\n    to where the decorated function itself was called. However, in certain\n    cases such as deprecating conditional behavior within an object\n    constructor, it can be useful to show a less recent stack frame instead.\n\n    .. note::\n\n        This decorator can be also used on callables that are not functions,\n        such as classes and callable objects.\n\n    .. versionadded:: 7.0\n        Parameters ``reason``, ``version``, and ``removed_in``.\n\n    .. versionadded:: 7.1\n        The ``warning_in`` and ``stack_frame`` parameters.\n\n    .. versionchanged:: 8.0\n        Moved out of :mod:`sopel.tools` to resolve circular dependency issues.\n\n    \"\"\"\n    if not any([reason, version, removed_in, warning_in, func]):\n        # common usage: @deprecated()\n        return deprecated\n\n    if callable(reason):\n        # common usage: @deprecated\n        return deprecated(func=reason)\n\n    if func is None:\n        # common usage: @deprecated(message, version, removed_in)\n        def decorator(func):\n            return deprecated(\n                reason, version, removed_in, warning_in, stack_frame, func)\n        return decorator\n\n    # now, we have everything we need to have:\n    # - message is not a callable (could be None)\n    # - func is not None\n    # - version and removed_in can be None but that's OK\n    # so now we can return the actual decorated function\n\n    message = reason or getattr(func, '__name__', '<anonymous-function>')\n\n    template = 'Deprecated: {message}'\n    if version and removed_in:\n        template = (\n            'Deprecated since {version}, '\n            'will be removed in {removed_in}: '\n            '{message}')\n    elif version:\n        template = 'Deprecated since {version}: {message}'\n    elif removed_in:\n        template = 'Deprecated, will be removed in {removed_in}: {message}'\n\n    text = template.format(\n        message=message, version=version, removed_in=removed_in)\n\n    @functools.wraps(func)\n    def deprecated_func(*args, **kwargs):\n        if not (warning_in and\n                parse_version(warning_in) >= parse_version(__version__)):\n            original_frame = inspect.stack()[-stack_frame]\n            mod = inspect.getmodule(original_frame[0])\n            module_name = None\n            if mod:\n                module_name = mod.__name__\n            if module_name:\n                if module_name.startswith('sopel.'):\n                    # core, or core plugin\n                    logger = logging.getLogger(module_name)\n                else:\n                    # probably a plugin; try to handle most cases sanely\n                    if module_name.startswith('sopel_modules.'):\n                        # namespace package plugins have a prefix, obviously\n                        # they will use Sopel's namespace; other won't\n                        module_name = module_name.replace(\n                            'sopel_modules.',\n                            'sopel.externals.',\n                            1,\n                        )\n                    logger = logging.getLogger(module_name)\n            else:\n                # don't know the module/plugin name, but we want to make sure\n                # the log line is still output, so just get *something*\n                logger = logging.getLogger(__name__)\n\n            # Format only the desired stack frame\n            trace = traceback.extract_stack()\n            trace_frame = traceback.format_list(trace[:-1])[stack_frame][:-1]\n\n            # Warn the user\n            logger.warning(text + \"\\n\" + trace_frame)\n\n        return func(*args, **kwargs)\n\n    return deprecated_func\n", "path": "sopel/lifecycle.py"}], "after_files": [{"content": "\"\"\"Deprecation module for Sopel developers and plugin authors.\n\n.. versionadded:: 8.0\n\n    Previously in :mod:`sopel.tools`, the :func:`deprecated` function has been\n    moved to this newly created module, as it can be used in every part of the\n    Sopel codebase, including :mod:`sopel.tools` itself.\n\n\"\"\"\nfrom __future__ import annotations\n\nimport functools\nimport inspect\nimport logging\nimport traceback\nfrom typing import Callable, Optional\n\nfrom packaging.version import parse as parse_version\n\nfrom sopel import __version__\n\n\ndef deprecated(\n    reason: Optional[str] = None,\n    version: Optional[str] = None,\n    removed_in: Optional[str] = None,\n    warning_in: Optional[str] = None,\n    stack_frame: int = -1,\n    func: Optional[Callable] = None,\n):\n    \"\"\"Decorator to mark deprecated functions in Sopel's API\n\n    :param reason: optional text added to the deprecation warning\n    :param version: optional version number when the decorated function\n                    is deprecated\n    :param removed_in: optional version number when the deprecated function\n                       will be removed\n    :param warning_in: optional version number when the decorated function\n                       should start emitting a warning when called\n    :param stack_frame: optional stack frame to output; defaults to\n                        ``-1``; should almost always be negative\n    :param func: deprecated function\n    :return: a callable that depends on how the decorator is called; either\n             the decorated function, or a decorator with the appropriate\n             parameters\n\n    Any time the decorated ``func`` is called, a deprecation warning will be\n    logged, with the last frame of the traceback. The optional ``warning_in``\n    argument suppresses the warning on Sopel versions older than that, allowing\n    for multi-stage deprecation timelines.\n\n    The decorator can be used with or without arguments::\n\n        from sopel.lifecycle import deprecated\n\n        @deprecated\n        def func1():\n            print('func 1')\n\n        @deprecated()\n        def func2():\n            print('func 2')\n\n        @deprecated(reason='obsolete', version='7.0', removed_in='8.0')\n        def func3():\n            print('func 3')\n\n    which will output the following in a console::\n\n        >>> func1()\n        Deprecated: func1\n        File \"<stdin>\", line 1, in <module>\n        func 1\n        >>> func2()\n        Deprecated: func2\n        File \"<stdin>\", line 1, in <module>\n        func 2\n        >>> func3()\n        Deprecated since 7.0, will be removed in 8.0: obsolete\n        File \"<stdin>\", line 1, in <module>\n        func 3\n\n    The ``stack_frame`` argument can be used to choose which stack frame is\n    logged along with the message text. By default, this decorator logs the\n    most recent stack frame (the last entry in the list, ``-1``), corresponding\n    to where the decorated function itself was called. However, in certain\n    cases such as deprecating conditional behavior within an object\n    constructor, it can be useful to show a less recent stack frame instead.\n\n    .. note::\n\n        This decorator can be also used on callables that are not functions,\n        such as classes and callable objects.\n\n    .. versionadded:: 7.0\n        Parameters ``reason``, ``version``, and ``removed_in``.\n\n    .. versionadded:: 7.1\n        The ``warning_in`` and ``stack_frame`` parameters.\n\n    .. versionchanged:: 8.0\n        Moved out of :mod:`sopel.tools` to resolve circular dependency issues.\n\n    \"\"\"\n    if not any([reason, version, removed_in, warning_in, func]):\n        # common usage: @deprecated()\n        return deprecated\n\n    if callable(reason):\n        # common usage: @deprecated\n        return deprecated(func=reason)\n\n    if func is None:\n        # common usage: @deprecated(message, version, removed_in)\n        def decorator(func):\n            return deprecated(\n                reason, version, removed_in, warning_in, stack_frame, func)\n        return decorator\n\n    # now, we have everything we need to have:\n    # - message is not a callable (could be None)\n    # - func is not None\n    # - version and removed_in can be None but that's OK\n    # so now we can return the actual decorated function\n\n    message = reason or getattr(func, '__name__', '<anonymous-function>')\n\n    template = 'Deprecated: {message}'\n    if version and removed_in:\n        template = (\n            'Deprecated since {version}, '\n            'will be removed in {removed_in}: '\n            '{message}')\n    elif version:\n        template = 'Deprecated since {version}: {message}'\n    elif removed_in:\n        template = 'Deprecated, will be removed in {removed_in}: {message}'\n\n    text = template.format(\n        message=message, version=version, removed_in=removed_in)\n\n    @functools.wraps(func)\n    def deprecated_func(*args, **kwargs):\n        warn_ver = warning_in and parse_version(warning_in).release\n        this_ver = parse_version(__version__).release\n\n        if not (warn_ver and warn_ver >= this_ver):\n            original_frame = inspect.stack()[-stack_frame]\n            mod = inspect.getmodule(original_frame[0])\n            module_name = None\n            if mod:\n                module_name = mod.__name__\n            if module_name:\n                if module_name.startswith('sopel.'):\n                    # core, or core plugin\n                    logger = logging.getLogger(module_name)\n                else:\n                    # probably a plugin; try to handle most cases sanely\n                    if module_name.startswith('sopel_modules.'):\n                        # namespace package plugins have a prefix, obviously\n                        # they will use Sopel's namespace; other won't\n                        module_name = module_name.replace(\n                            'sopel_modules.',\n                            'sopel.externals.',\n                            1,\n                        )\n                    logger = logging.getLogger(module_name)\n            else:\n                # don't know the module/plugin name, but we want to make sure\n                # the log line is still output, so just get *something*\n                logger = logging.getLogger(__name__)\n\n            # Format only the desired stack frame\n            trace = traceback.extract_stack()\n            trace_frame = traceback.format_list(trace[:-1])[stack_frame][:-1]\n\n            # Warn the user\n            logger.warning(text + \"\\n\" + trace_frame)\n\n        return func(*args, **kwargs)\n\n    return deprecated_func\n", "path": "sopel/lifecycle.py"}]}