test_utils.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import inspect
  2. import sys
  3. import pytest
  4. import numpy as np
  5. from numpy.core import arange
  6. from numpy.testing import assert_, assert_equal, assert_raises_regex
  7. from numpy.lib import deprecate, deprecate_with_doc
  8. import numpy.lib.utils as utils
  9. from io import StringIO
  10. @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO")
  11. @pytest.mark.skipif(
  12. sys.version_info == (3, 10, 0, "candidate", 1),
  13. reason="Broken as of bpo-44524",
  14. )
  15. def test_lookfor():
  16. out = StringIO()
  17. utils.lookfor('eigenvalue', module='numpy', output=out,
  18. import_modules=False)
  19. out = out.getvalue()
  20. assert_('numpy.linalg.eig' in out)
  21. @deprecate
  22. def old_func(self, x):
  23. return x
  24. @deprecate(message="Rather use new_func2")
  25. def old_func2(self, x):
  26. return x
  27. def old_func3(self, x):
  28. return x
  29. new_func3 = deprecate(old_func3, old_name="old_func3", new_name="new_func3")
  30. def old_func4(self, x):
  31. """Summary.
  32. Further info.
  33. """
  34. return x
  35. new_func4 = deprecate(old_func4)
  36. def old_func5(self, x):
  37. """Summary.
  38. Bizarre indentation.
  39. """
  40. return x
  41. new_func5 = deprecate(old_func5, message="This function is\ndeprecated.")
  42. def old_func6(self, x):
  43. """
  44. Also in PEP-257.
  45. """
  46. return x
  47. new_func6 = deprecate(old_func6)
  48. @deprecate_with_doc(msg="Rather use new_func7")
  49. def old_func7(self,x):
  50. return x
  51. def test_deprecate_decorator():
  52. assert_('deprecated' in old_func.__doc__)
  53. def test_deprecate_decorator_message():
  54. assert_('Rather use new_func2' in old_func2.__doc__)
  55. def test_deprecate_fn():
  56. assert_('old_func3' in new_func3.__doc__)
  57. assert_('new_func3' in new_func3.__doc__)
  58. def test_deprecate_with_doc_decorator_message():
  59. assert_('Rather use new_func7' in old_func7.__doc__)
  60. @pytest.mark.skipif(sys.flags.optimize == 2, reason="-OO discards docstrings")
  61. @pytest.mark.parametrize('old_func, new_func', [
  62. (old_func4, new_func4),
  63. (old_func5, new_func5),
  64. (old_func6, new_func6),
  65. ])
  66. def test_deprecate_help_indentation(old_func, new_func):
  67. _compare_docs(old_func, new_func)
  68. # Ensure we don't mess up the indentation
  69. for knd, func in (('old', old_func), ('new', new_func)):
  70. for li, line in enumerate(func.__doc__.split('\n')):
  71. if li == 0:
  72. assert line.startswith(' ') or not line.startswith(' '), knd
  73. elif line:
  74. assert line.startswith(' '), knd
  75. def _compare_docs(old_func, new_func):
  76. old_doc = inspect.getdoc(old_func)
  77. new_doc = inspect.getdoc(new_func)
  78. index = new_doc.index('\n\n') + 2
  79. assert_equal(new_doc[index:], old_doc)
  80. @pytest.mark.skipif(sys.flags.optimize == 2, reason="-OO discards docstrings")
  81. def test_deprecate_preserve_whitespace():
  82. assert_('\n Bizarre' in new_func5.__doc__)
  83. def test_deprecate_module():
  84. assert_(old_func.__module__ == __name__)
  85. def test_safe_eval_nameconstant():
  86. # Test if safe_eval supports Python 3.4 _ast.NameConstant
  87. utils.safe_eval('None')
  88. class TestByteBounds:
  89. def test_byte_bounds(self):
  90. # pointer difference matches size * itemsize
  91. # due to contiguity
  92. a = arange(12).reshape(3, 4)
  93. low, high = utils.byte_bounds(a)
  94. assert_equal(high - low, a.size * a.itemsize)
  95. def test_unusual_order_positive_stride(self):
  96. a = arange(12).reshape(3, 4)
  97. b = a.T
  98. low, high = utils.byte_bounds(b)
  99. assert_equal(high - low, b.size * b.itemsize)
  100. def test_unusual_order_negative_stride(self):
  101. a = arange(12).reshape(3, 4)
  102. b = a.T[::-1]
  103. low, high = utils.byte_bounds(b)
  104. assert_equal(high - low, b.size * b.itemsize)
  105. def test_strided(self):
  106. a = arange(12)
  107. b = a[::2]
  108. low, high = utils.byte_bounds(b)
  109. # the largest pointer address is lost (even numbers only in the
  110. # stride), and compensate addresses for striding by 2
  111. assert_equal(high - low, b.size * 2 * b.itemsize - b.itemsize)
  112. def test_assert_raises_regex_context_manager():
  113. with assert_raises_regex(ValueError, 'no deprecation warning'):
  114. raise ValueError('no deprecation warning')
  115. def test_info_method_heading():
  116. # info(class) should only print "Methods:" heading if methods exist
  117. class NoPublicMethods:
  118. pass
  119. class WithPublicMethods:
  120. def first_method():
  121. pass
  122. def _has_method_heading(cls):
  123. out = StringIO()
  124. utils.info(cls, output=out)
  125. return 'Methods:' in out.getvalue()
  126. assert _has_method_heading(WithPublicMethods)
  127. assert not _has_method_heading(NoPublicMethods)
  128. def test_drop_metadata():
  129. def _compare_dtypes(dt1, dt2):
  130. return np.can_cast(dt1, dt2, casting='no')
  131. # structured dtype
  132. dt = np.dtype([('l1', [('l2', np.dtype('S8', metadata={'msg': 'toto'}))])],
  133. metadata={'msg': 'titi'})
  134. dt_m = utils.drop_metadata(dt)
  135. assert _compare_dtypes(dt, dt_m) is True
  136. assert dt_m.metadata is None
  137. assert dt_m['l1'].metadata is None
  138. assert dt_m['l1']['l2'].metadata is None
  139. # alignement
  140. dt = np.dtype([('x', '<f8'), ('y', '<i4')],
  141. align=True,
  142. metadata={'msg': 'toto'})
  143. dt_m = utils.drop_metadata(dt)
  144. assert _compare_dtypes(dt, dt_m) is True
  145. assert dt_m.metadata is None
  146. # subdtype
  147. dt = np.dtype('8f',
  148. metadata={'msg': 'toto'})
  149. dt_m = utils.drop_metadata(dt)
  150. assert _compare_dtypes(dt, dt_m) is True
  151. assert dt_m.metadata is None
  152. # scalar
  153. dt = np.dtype('uint32',
  154. metadata={'msg': 'toto'})
  155. dt_m = utils.drop_metadata(dt)
  156. assert _compare_dtypes(dt, dt_m) is True
  157. assert dt_m.metadata is None
  158. @pytest.mark.parametrize("dtype",
  159. [np.dtype("i,i,i,i")[["f1", "f3"]],
  160. np.dtype("f8"),
  161. np.dtype("10i")])
  162. def test_drop_metadata_identity_and_copy(dtype):
  163. # If there is no metadata, the identity is preserved:
  164. assert utils.drop_metadata(dtype) is dtype
  165. # If there is any, it is dropped (subforms are checked above)
  166. dtype = np.dtype(dtype, metadata={1: 2})
  167. assert utils.drop_metadata(dtype).metadata is None