Coverage for python/lsst/utils/deprecated.py: 50%
20 statements
« prev ^ index » next coverage.py v7.4.3, created at 2024-03-01 11:57 +0000
« prev ^ index » next coverage.py v7.4.3, created at 2024-03-01 11:57 +0000
1# This file is part of utils.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# Use of this source code is governed by a 3-clause BSD-style
10# license that can be found in the LICENSE file.
12from __future__ import annotations
14__all__ = ["deprecate_pybind11", "suppress_deprecations"]
16import functools
17import unittest.mock
18import warnings
19from collections.abc import Iterator
20from contextlib import contextmanager
21from typing import Any
23import deprecated.sphinx
26def deprecate_pybind11(obj: Any, reason: str, version: str, category: type[Warning] = FutureWarning) -> Any:
27 """Deprecate a pybind11-wrapped C++ interface function, method or class.
29 This needs to use a pass-through Python wrapper so that
30 `~deprecated.sphinx.deprecated` can update its docstring; pybind11
31 docstrings are native and cannot be modified.
33 Note that this is not a decorator; its output must be assigned to
34 replace the method being deprecated.
36 Parameters
37 ----------
38 obj : function, method, or class
39 The function, method, or class to deprecate.
40 reason : `str`
41 Reason for deprecation, passed to `~deprecated.sphinx.deprecated`.
42 version : 'str'
43 Next major version in which the interface will be deprecated,
44 passed to `~deprecated.sphinx.deprecated`.
45 category : `Warning`
46 Warning category, passed to `~deprecated.sphinx.deprecated`.
48 Returns
49 -------
50 obj : function, method, or class
51 Wrapped function, method, or class.
53 Examples
54 --------
55 .. code-block:: python
57 ExposureF.getCalib = deprecate_pybind11(ExposureF.getCalib,
58 reason="Replaced by getPhotoCalib. (Will be removed in 18.0)",
59 version="17.0", category=FutureWarning))
60 """
62 @functools.wraps(obj)
63 def internal(*args: Any, **kwargs: Any) -> Any:
64 return obj(*args, **kwargs)
66 # Typeshed seems to have an incorrect definition for the deprecated
67 # function and believes the category should be
68 # Optional[Type[DeprecationWarning]] but this is wrong on two counts:
69 # 1. None is not actually allowed.
70 # 2. FutureWarning is explicitly allowed but that is not a subclass
71 # of DeprecationWarning.
72 # This has been fixed upstream at
73 # https://github.com/python/typeshed/pull/593
74 # and will pass once that is released.
75 return deprecated.sphinx.deprecated(reason=reason, version=version, category=category)(internal)
78@contextmanager
79def suppress_deprecations(category: type[Warning] = FutureWarning) -> Iterator[None]:
80 """Suppress warnings generated by `deprecated.sphinx.deprecated`.
82 Naively, one might attempt to suppress these warnings by using
83 `~warnings.catch_warnings`. However, `~deprecated.sphinx.deprecated`
84 attempts to install its own filter, overriding that. This convenience
85 method works around this and properly suppresses the warnings by providing
86 a mock `~warnings.simplefilter` for `~deprecated.sphinx.deprecated` to
87 call.
89 Parameters
90 ----------
91 category : `Warning` or subclass
92 The category of warning to suppress.
93 """
94 with warnings.catch_warnings():
95 warnings.simplefilter("ignore", category)
96 with unittest.mock.patch.object(warnings, "simplefilter"):
97 yield