# Buggy code
def warning_decorator_factory(warning_type):
    def specific_warning(
        message, stacklevel=1, since=None, includedoc=None, extenddoc=False
    ):
        def decorator(func):
            func.__qualname__ = to_native_str("warning_decorator_factory")
            func.__annotations__ = dict()

            @wraps(func)
            def func_wrapper(*args, **kwargs):
                # we need to increment the stacklevel by one because otherwise we'll get the location of our
                # func_wrapper in the log, instead of our caller (which is the real caller of the wrapped function)
                warnings.warn(message, warning_type, stacklevel=stacklevel + 1)
                return func(*args, **kwargs)

            if includedoc is not None and since is not None:
                docstring = "\n.. deprecated:: {since}\n   {message}\n\n".format(
                    since=since, message=includedoc
                )
                if (
                    extenddoc
                    and hasattr(func_wrapper, "__doc__")
                    and func_wrapper.__doc__ is not None
                ):
                    docstring = func_wrapper.__doc__ + "\n" + docstring
                func_wrapper.__doc__ = docstring

            return func_wrapper

        return decorator

    return specific_warning


# Traceback (AttributeError)
2019-11-25 17:59:12,930 - octoprint.plugin - ERROR - Error while calling plugin fanspeedslider
Traceback (most recent call last):
File "/home/nas/OctoPrint/venv/local/lib/python2.7/site-packages/octoprint/plugin/__init__.py", line 224, in call_plugin
result = getattr(plugin, method)(*args, **kwargs)
File "/home/nas/OctoPrint/venv/local/lib/python2.7/site-packages/octoprint_fanspeedslider/__init__.py", line 19, in on_after_startup
self.get_settings_updates()
File "/home/nas/OctoPrint/venv/local/lib/python2.7/site-packages/octoprint_fanspeedslider/__init__.py", line 90, in get_settings_updates
self.defaultFanSpeed = self._settings.getInt(["defaultFanSpeed"])
File "/home/nas/OctoPrint/venv/local/lib/python2.7/site-packages/octoprint/plugin/__init__.py", line 521, in __getattr__
orig_func = decorator(orig_func)
File "/home/nas/OctoPrint/venv/local/lib/python2.7/site-packages/octoprint/util/__init__.py", line 134, in decorator
func.__qualname__ = to_native_str('warning_decorator_factory')
AttributeError: 'instancemethod' object has no attribute '__qualname__'

# Fixed code
def warning_decorator_factory(warning_type):
    def specific_warning(
        message, stacklevel=1, since=None, includedoc=None, extenddoc=False
    ):
        def decorator(func):
            @wraps(func)
            def func_wrapper(*args, **kwargs):
                # we need to increment the stacklevel by one because otherwise we'll get the location of our
                # func_wrapper in the log, instead of our caller (which is the real caller of the wrapped function)
                warnings.warn(message, warning_type, stacklevel=stacklevel + 1)
                return func(*args, **kwargs)

            if includedoc is not None and since is not None:
                docstring = "\n.. deprecated:: {since}\n   {message}\n\n".format(
                    since=since, message=includedoc
                )
                if (
                    extenddoc
                    and hasattr(func_wrapper, "__doc__")
                    and func_wrapper.__doc__ is not None
                ):
                    docstring = func_wrapper.__doc__ + "\n" + docstring
                func_wrapper.__doc__ = docstring

            return func_wrapper

        return decorator

    return specific_warning