Coverage for python/lsst/utils/deprecated.py: 50%

20 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-17 07:53 +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. 

11 

12from __future__ import annotations 

13 

14__all__ = ["deprecate_pybind11", "suppress_deprecations"] 

15 

16import functools 

17import unittest.mock 

18import warnings 

19from collections.abc import Iterator 

20from contextlib import contextmanager 

21from typing import Any 

22 

23import deprecated.sphinx 

24 

25 

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. 

28 

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. 

32 

33 Note that this is not a decorator; its output must be assigned to 

34 replace the method being deprecated. 

35 

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` 

47 

48 Returns 

49 ------- 

50 obj : function, method, or class 

51 Wrapped function, method, or class 

52 

53 Examples 

54 -------- 

55 .. code-block:: python 

56 

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 """ 

61 

62 @functools.wraps(obj) 

63 def internal(*args: Any, **kwargs: Any) -> Any: 

64 return obj(*args, **kwargs) 

65 

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) 

76 

77 

78@contextmanager 

79def suppress_deprecations(category: type[Warning] = FutureWarning) -> Iterator[None]: 

80 """Suppress warnings generated by `deprecated.sphinx.deprecated`. 

81 

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. 

88 

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