Wrapping `warnings.deprecated`?

Hi all!

We have a series of decorators in our internal codebase for issuing DeprecationWarnings which pre-date PEP 702. Have learned about PEP 702, I think it would be nice for us to use warnings.deprecated (and get that sweet IDE integration).

The main problem is that our existing decorators have a different function signature and more logic (for instance, our decorator requires a Github issue parameter that tracks the deprecation process, and we also emit logging information to track who is still using the deprecated functionality). It would be very easy for us to rewrite our internal decorator to just call warnings.deprecated, like:

from warnings import deprecated

def our_deprecated_decorator(msg, issue, **kwargs):
    url = issue_to_url(issue)
    log_to_db(...)
    return deprecated(message=f"{msg}\nSee {url} for more info", **kwargs)

but I think this loses the type-checking support. Does anyone know if there’s a supported way to “wrap” warnings.deprecated in a way that the type-checker can understand?

Not that I’m aware of.

If you had the same function signature, I think you could lie to the type checkers:

if TYPE_CHECKING:
    from warnings import deprecated as deprecated
else:
    def deprecated(...): ...
2 Likes

A while ago, I suggested a generic version of this, that would allow user-defined decorators to have the same semantics than @classmethod/@property etc. This could also work for decorators having the same effect as @warnings.deprecated, although as @hauntsaninja mentioned the signature needs to be compatible (and most of the time it isn’t, e.g. extra parameters are commonly available – like since, until, etc).

1 Like