test_dok.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import warnings
  2. import pytest
  3. import numpy as np
  4. from numpy.testing import assert_equal
  5. import scipy as sp
  6. from scipy.sparse import dok_array, dok_matrix
  7. pytestmark = pytest.mark.thread_unsafe
  8. @pytest.fixture
  9. def d():
  10. return {(0, 1): 1, (0, 2): 2}
  11. @pytest.fixture
  12. def A():
  13. return np.array([[0, 1, 2], [0, 0, 0], [0, 0, 0]])
  14. @pytest.fixture(params=[dok_array, dok_matrix])
  15. def Asp(request):
  16. A = request.param((3, 3))
  17. A[(0, 1)] = 1
  18. A[(0, 2)] = 2
  19. yield A
  20. # Note: __iter__ and comparison dunders act like ndarrays for DOK, not dict.
  21. # Dunders reversed, or, ror, ior work as dict for dok_matrix, raise for dok_array
  22. # All other dict methods on DOK format act like dict methods (with extra checks).
  23. # Start of tests
  24. ################
  25. def test_dict_methods_covered(d, Asp):
  26. d_methods = set(dir(d)) - {"__class_getitem__"}
  27. asp_methods = set(dir(Asp))
  28. assert d_methods < asp_methods
  29. def test_clear(d, Asp):
  30. assert d.items() == Asp.items()
  31. d.clear()
  32. Asp.clear()
  33. assert d.items() == Asp.items()
  34. def test_copy(d, Asp):
  35. assert d.items() == Asp.items()
  36. dd = d.copy()
  37. asp = Asp.copy()
  38. assert dd.items() == asp.items()
  39. assert asp.items() == Asp.items()
  40. asp[(0, 1)] = 3
  41. assert Asp[(0, 1)] == 1
  42. def test_fromkeys_default():
  43. # test with default value
  44. edges = [(0, 2), (1, 0), (2, 1)]
  45. Xdok = dok_array.fromkeys(edges)
  46. X = [[0, 0, 1], [1, 0, 0], [0, 1, 0]]
  47. assert_equal(Xdok.toarray(), X)
  48. def test_fromkeys_positional():
  49. # test with positional value
  50. edges = [(0, 2), (1, 0), (2, 1)]
  51. Xdok = dok_array.fromkeys(edges, -1)
  52. X = [[0, 0, -1], [-1, 0, 0], [0, -1, 0]]
  53. assert_equal(Xdok.toarray(), X)
  54. def test_fromkeys_iterator():
  55. it = ((a, a % 2) for a in range(4))
  56. Xdok = dok_array.fromkeys(it)
  57. X = [[1, 0], [0, 1], [1, 0], [0, 1]]
  58. assert_equal(Xdok.toarray(), X)
  59. def test_get(d, Asp):
  60. assert Asp.get((0, 1)) == d.get((0, 1))
  61. assert Asp.get((0, 0), 99) == d.get((0, 0), 99)
  62. with pytest.raises(IndexError, match="out of bounds"):
  63. Asp.get((0, 4), 99)
  64. def test_items(d, Asp):
  65. assert Asp.items() == d.items()
  66. def test_keys(d, Asp):
  67. assert Asp.keys() == d.keys()
  68. def test_pop(d, Asp):
  69. assert d.pop((0, 1)) == 1
  70. assert Asp.pop((0, 1)) == 1
  71. assert d.items() == Asp.items()
  72. assert Asp.pop((22, 21), None) is None
  73. assert Asp.pop((22, 21), "other") == "other"
  74. with pytest.raises(KeyError, match="(22, 21)"):
  75. Asp.pop((22, 21))
  76. with pytest.raises(TypeError, match="got an unexpected keyword argument"):
  77. Asp.pop((22, 21), default=5)
  78. def test_popitem(d, Asp):
  79. assert d.popitem() == Asp.popitem()
  80. assert d.items() == Asp.items()
  81. def test_setdefault(d, Asp):
  82. assert Asp.setdefault((0, 1), 4) == 1
  83. assert Asp.setdefault((2, 2), 4) == 4
  84. d.setdefault((0, 1), 4)
  85. d.setdefault((2, 2), 4)
  86. assert d.items() == Asp.items()
  87. def test_update(d, Asp):
  88. for input in [Asp, Asp._dict, Asp._dict.items()]:
  89. Bsp = dok_array(Asp.shape)
  90. Bsp.update(input)
  91. assert_equal(Bsp.toarray(), Asp.toarray())
  92. with pytest.raises(ValueError, match="Inexact indices .* not allowed"):
  93. Asp.update(np.zeros((2,2)))
  94. with pytest.raises(IndexError, match="length needs to match self.shape"):
  95. Asp.update({(3, 2, 1, 0): 1.2})
  96. with pytest.raises(IndexError, match="integer keys required"):
  97. Asp.update({(0.2, 1): 1.2})
  98. with pytest.raises(IndexError, match="negative index"):
  99. Asp.update({(0, -1): 1.2})
  100. with pytest.raises(IndexError, match="index .* is too large"):
  101. Asp.update({(0, 3): 1.2})
  102. def test_values(d, Asp):
  103. # Note: dict.values are strange: d={1: 1}; d.values() == d.values() is False
  104. # Using list(d.values()) makes them comparable.
  105. assert list(Asp.values()) == list(d.values())
  106. def test_dunder_getitem(d, Asp):
  107. assert Asp[(0, 1)] == d[(0, 1)]
  108. def test_dunder_setitem(d, Asp):
  109. Asp[(1, 1)] = 5
  110. d[(1, 1)] = 5
  111. assert d.items() == Asp.items()
  112. def test_dunder_delitem(d, Asp):
  113. del Asp[(0, 1)]
  114. del d[(0, 1)]
  115. assert d.items() == Asp.items()
  116. def test_dunder_contains(d, Asp):
  117. assert ((0, 1) in d) == ((0, 1) in Asp)
  118. assert ((0, 0) in d) == ((0, 0) in Asp)
  119. def test_dunder_len(d, Asp):
  120. assert len(d) == len(Asp)
  121. # Note: dunders reversed, or, ror, ior work as dict for dok_matrix, raise for dok_array
  122. def test_dunder_reversed(d, Asp):
  123. if isinstance(Asp, dok_array):
  124. with pytest.raises(TypeError):
  125. list(reversed(Asp))
  126. else:
  127. assert list(reversed(Asp)) == list(reversed(d))
  128. def test_dunder_ior(d, Asp):
  129. if isinstance(Asp, dok_array):
  130. with pytest.raises(TypeError):
  131. Asp |= Asp
  132. else:
  133. dd = {(0, 0): 5}
  134. Asp |= dd
  135. assert Asp[(0, 0)] == 5
  136. d |= dd
  137. assert d.items() == Asp.items()
  138. dd |= Asp
  139. assert dd.items() == Asp.items()
  140. def test_dunder_or(d, Asp):
  141. if isinstance(Asp, dok_array):
  142. with pytest.raises(TypeError):
  143. Asp | Asp
  144. else:
  145. assert d | d == Asp | d
  146. assert d | d == Asp | Asp
  147. def test_dunder_ror(d, Asp):
  148. if isinstance(Asp, dok_array):
  149. with pytest.raises(TypeError):
  150. Asp | Asp
  151. with pytest.raises(TypeError):
  152. d | Asp
  153. else:
  154. assert Asp.__ror__(d) == Asp.__ror__(Asp)
  155. assert d.__ror__(d) == Asp.__ror__(d)
  156. assert d | Asp
  157. # Note: comparison dunders, e.g. ==, >=, etc follow np.array not dict
  158. def test_dunder_eq(A, Asp):
  159. with warnings.catch_warnings():
  160. warnings.simplefilter("ignore", sp.sparse.SparseEfficiencyWarning)
  161. assert (Asp == Asp).toarray().all()
  162. assert (A == Asp).all()
  163. def test_dunder_ne(A, Asp):
  164. assert not (Asp != Asp).toarray().any()
  165. assert not (A != Asp).any()
  166. def test_dunder_lt(A, Asp):
  167. assert not (Asp < Asp).toarray().any()
  168. assert not (A < Asp).any()
  169. def test_dunder_gt(A, Asp):
  170. assert not (Asp > Asp).toarray().any()
  171. assert not (A > Asp).any()
  172. def test_dunder_le(A, Asp):
  173. with warnings.catch_warnings():
  174. warnings.simplefilter("ignore", sp.sparse.SparseEfficiencyWarning)
  175. assert (Asp <= Asp).toarray().all()
  176. assert (A <= Asp).all()
  177. def test_dunder_ge(A, Asp):
  178. with warnings.catch_warnings():
  179. warnings.simplefilter("ignore", sp.sparse.SparseEfficiencyWarning)
  180. assert (Asp >= Asp).toarray().all()
  181. assert (A >= Asp).all()
  182. # Note: iter dunder follows np.array not dict
  183. def test_dunder_iter(A, Asp):
  184. assert all((a == asp).all() for a, asp in zip(A, Asp))