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

18 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-11-09 05:52 +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 

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

13 

14import functools 

15import unittest.mock 

16import warnings 

17from contextlib import contextmanager 

18from typing import Any, Iterator, Type 

19 

20import deprecated.sphinx 

21 

22 

23def deprecate_pybind11(obj: Any, reason: str, version: str, category: Type[Warning] = FutureWarning) -> Any: 

24 """Deprecate a pybind11-wrapped C++ interface function, method or class. 

25 

26 This needs to use a pass-through Python wrapper so that 

27 `~deprecated.sphinx.deprecated` can update its docstring; pybind11 

28 docstrings are native and cannot be modified. 

29 

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

31 replace the method being deprecated. 

32 

33 Parameters 

34 ---------- 

35 obj : function, method, or class 

36 The function, method, or class to deprecate. 

37 reason : `str` 

38 Reason for deprecation, passed to `~deprecated.sphinx.deprecated` 

39 version : 'str' 

40 Next major version in which the interface will be deprecated, 

41 passed to `~deprecated.sphinx.deprecated` 

42 category : `Warning` 

43 Warning category, passed to `~deprecated.sphinx.deprecated` 

44 

45 Returns 

46 ------- 

47 obj : function, method, or class 

48 Wrapped function, method, or class 

49 

50 Examples 

51 -------- 

52 .. code-block:: python 

53 

54 ExposureF.getCalib = deprecate_pybind11(ExposureF.getCalib, 

55 reason="Replaced by getPhotoCalib. (Will be removed in 18.0)", 

56 version="17.0", category=FutureWarning)) 

57 """ 

58 

59 @functools.wraps(obj) 

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

61 return obj(*args, **kwargs) 

62 

63 # Typeshed seems to have an incorrect definition for the deprecated 

64 # function and believes the category should be 

65 # Optional[Type[DeprecationWarning]] but this is wrong on two counts: 

66 # 1. None is not actually allowed. 

67 # 2. FutureWarning is explicitly allowed but that is not a subclass 

68 # of DeprecationWarning. 

69 # This has been fixed upstream at 

70 # https://github.com/python/typeshed/pull/593 

71 # and will pass once that is released. 

72 return deprecated.sphinx.deprecated(reason=reason, version=version, category=category)(internal) 

73 

74 

75@contextmanager 

76def suppress_deprecations(category: Type[Warning] = FutureWarning) -> Iterator[None]: 

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

78 

79 Naively, one might attempt to suppress these warnings by using 

80 `~warnings.catch_warnings`. However, `~deprecated.sphinx.deprecated` 

81 attempts to install its own filter, overriding that. This convenience 

82 method works around this and properly suppresses the warnings by providing 

83 a mock `~warnings.simplefilter` for `~deprecated.sphinx.deprecated` to 

84 call. 

85 

86 Parameters 

87 ---------- 

88 category : `Warning` or subclass 

89 The category of warning to suppress. 

90 """ 

91 with warnings.catch_warnings(): 

92 warnings.simplefilter("ignore", category) 

93 with unittest.mock.patch.object(warnings, "simplefilter"): 

94 yield