test_api.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. from __future__ import annotations
  2. import re
  3. import typing
  4. from typing import Any, Callable, TypeVar
  5. import numpy as np
  6. import pytest
  7. import matplotlib as mpl
  8. from matplotlib import _api
  9. if typing.TYPE_CHECKING:
  10. from typing_extensions import Self
  11. T = TypeVar('T')
  12. @pytest.mark.parametrize('target,shape_repr,test_shape',
  13. [((None, ), "(N,)", (1, 3)),
  14. ((None, 3), "(N, 3)", (1,)),
  15. ((None, 3), "(N, 3)", (1, 2)),
  16. ((1, 5), "(1, 5)", (1, 9)),
  17. ((None, 2, None), "(M, 2, N)", (1, 3, 1))
  18. ])
  19. def test_check_shape(target: tuple[int | None, ...],
  20. shape_repr: str,
  21. test_shape: tuple[int, ...]) -> None:
  22. error_pattern = "^" + re.escape(
  23. f"'aardvark' must be {len(target)}D with shape {shape_repr}, but your input "
  24. f"has shape {test_shape}")
  25. data = np.zeros(test_shape)
  26. with pytest.raises(ValueError, match=error_pattern):
  27. _api.check_shape(target, aardvark=data)
  28. def test_classproperty_deprecation() -> None:
  29. class A:
  30. @_api.deprecated("0.0.0")
  31. @_api.classproperty
  32. def f(cls: Self) -> None:
  33. pass
  34. with pytest.warns(mpl.MatplotlibDeprecationWarning):
  35. A.f
  36. with pytest.warns(mpl.MatplotlibDeprecationWarning):
  37. a = A()
  38. a.f
  39. def test_deprecate_privatize_attribute() -> None:
  40. class C:
  41. def __init__(self) -> None: self._attr = 1
  42. def _meth(self, arg: T) -> T: return arg
  43. attr: int = _api.deprecate_privatize_attribute("0.0")
  44. meth: Callable = _api.deprecate_privatize_attribute("0.0")
  45. c = C()
  46. with pytest.warns(mpl.MatplotlibDeprecationWarning):
  47. assert c.attr == 1
  48. with pytest.warns(mpl.MatplotlibDeprecationWarning):
  49. c.attr = 2
  50. with pytest.warns(mpl.MatplotlibDeprecationWarning):
  51. assert c.attr == 2
  52. with pytest.warns(mpl.MatplotlibDeprecationWarning):
  53. assert c.meth(42) == 42
  54. def test_delete_parameter() -> None:
  55. @_api.delete_parameter("3.0", "foo")
  56. def func1(foo: Any = None) -> None:
  57. pass
  58. @_api.delete_parameter("3.0", "foo")
  59. def func2(**kwargs: Any) -> None:
  60. pass
  61. for func in [func1, func2]: # type: ignore[list-item]
  62. func() # No warning.
  63. with pytest.warns(mpl.MatplotlibDeprecationWarning):
  64. func(foo="bar")
  65. def pyplot_wrapper(foo: Any = _api.deprecation._deprecated_parameter) -> None:
  66. func1(foo)
  67. pyplot_wrapper() # No warning.
  68. with pytest.warns(mpl.MatplotlibDeprecationWarning):
  69. func(foo="bar")
  70. def test_make_keyword_only() -> None:
  71. @_api.make_keyword_only("3.0", "arg")
  72. def func(pre: Any, arg: Any, post: Any = None) -> None:
  73. pass
  74. func(1, arg=2) # Check that no warning is emitted.
  75. with pytest.warns(mpl.MatplotlibDeprecationWarning):
  76. func(1, 2)
  77. with pytest.warns(mpl.MatplotlibDeprecationWarning):
  78. func(1, 2, 3)
  79. def test_deprecation_alternative() -> None:
  80. alternative = "`.f1`, `f2`, `f3(x) <.f3>` or `f4(x)<f4>`"
  81. @_api.deprecated("1", alternative=alternative)
  82. def f() -> None:
  83. pass
  84. if f.__doc__ is None:
  85. pytest.skip('Documentation is disabled')
  86. assert alternative in f.__doc__
  87. def test_empty_check_in_list() -> None:
  88. with pytest.raises(TypeError, match="No argument to check!"):
  89. _api.check_in_list(["a"])