1import warnings
2from functools import wraps
3
4from twisted.internet import defer, threads
5
6from scrapy.exceptions import ScrapyDeprecationWarning
7
8
9def deprecated(use_instead=None):
10    """This is a decorator which can be used to mark functions
11    as deprecated. It will result in a warning being emitted
12    when the function is used."""
13
14    def deco(func):
15        @wraps(func)
16        def wrapped(*args, **kwargs):
17            message = f"Call to deprecated function {func.__name__}."
18            if use_instead:
19                message += f" Use {use_instead} instead."
20            warnings.warn(message, category=ScrapyDeprecationWarning, stacklevel=2)
21            return func(*args, **kwargs)
22        return wrapped
23
24    if callable(use_instead):
25        deco = deco(use_instead)
26        use_instead = None
27    return deco
28
29
30def defers(func):
31    """Decorator to make sure a function always returns a deferred"""
32    @wraps(func)
33    def wrapped(*a, **kw):
34        return defer.maybeDeferred(func, *a, **kw)
35    return wrapped
36
37
38def inthread(func):
39    """Decorator to call a function in a thread and return a deferred with the
40    result
41    """
42    @wraps(func)
43    def wrapped(*a, **kw):
44        return threads.deferToThread(func, *a, **kw)
45    return wrapped
46