test_dtype.py 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. import sys
  2. import operator
  3. import pytest
  4. import ctypes
  5. import gc
  6. import numpy as np
  7. from numpy.core._rational_tests import rational
  8. from numpy.testing import (
  9. assert_, assert_equal, assert_array_equal, assert_raises, HAS_REFCOUNT)
  10. from numpy.compat import pickle
  11. from itertools import permutations
  12. def assert_dtype_equal(a, b):
  13. assert_equal(a, b)
  14. assert_equal(hash(a), hash(b),
  15. "two equivalent types do not hash to the same value !")
  16. def assert_dtype_not_equal(a, b):
  17. assert_(a != b)
  18. assert_(hash(a) != hash(b),
  19. "two different types hash to the same value !")
  20. class TestBuiltin:
  21. @pytest.mark.parametrize('t', [int, float, complex, np.int32, str, object,
  22. np.compat.unicode])
  23. def test_run(self, t):
  24. """Only test hash runs at all."""
  25. dt = np.dtype(t)
  26. hash(dt)
  27. @pytest.mark.parametrize('t', [int, float])
  28. def test_dtype(self, t):
  29. # Make sure equivalent byte order char hash the same (e.g. < and = on
  30. # little endian)
  31. dt = np.dtype(t)
  32. dt2 = dt.newbyteorder("<")
  33. dt3 = dt.newbyteorder(">")
  34. if dt == dt2:
  35. assert_(dt.byteorder != dt2.byteorder, "bogus test")
  36. assert_dtype_equal(dt, dt2)
  37. else:
  38. assert_(dt.byteorder != dt3.byteorder, "bogus test")
  39. assert_dtype_equal(dt, dt3)
  40. def test_equivalent_dtype_hashing(self):
  41. # Make sure equivalent dtypes with different type num hash equal
  42. uintp = np.dtype(np.uintp)
  43. if uintp.itemsize == 4:
  44. left = uintp
  45. right = np.dtype(np.uint32)
  46. else:
  47. left = uintp
  48. right = np.dtype(np.ulonglong)
  49. assert_(left == right)
  50. assert_(hash(left) == hash(right))
  51. def test_invalid_types(self):
  52. # Make sure invalid type strings raise an error
  53. assert_raises(TypeError, np.dtype, 'O3')
  54. assert_raises(TypeError, np.dtype, 'O5')
  55. assert_raises(TypeError, np.dtype, 'O7')
  56. assert_raises(TypeError, np.dtype, 'b3')
  57. assert_raises(TypeError, np.dtype, 'h4')
  58. assert_raises(TypeError, np.dtype, 'I5')
  59. assert_raises(TypeError, np.dtype, 'e3')
  60. assert_raises(TypeError, np.dtype, 'f5')
  61. if np.dtype('g').itemsize == 8 or np.dtype('g').itemsize == 16:
  62. assert_raises(TypeError, np.dtype, 'g12')
  63. elif np.dtype('g').itemsize == 12:
  64. assert_raises(TypeError, np.dtype, 'g16')
  65. if np.dtype('l').itemsize == 8:
  66. assert_raises(TypeError, np.dtype, 'l4')
  67. assert_raises(TypeError, np.dtype, 'L4')
  68. else:
  69. assert_raises(TypeError, np.dtype, 'l8')
  70. assert_raises(TypeError, np.dtype, 'L8')
  71. if np.dtype('q').itemsize == 8:
  72. assert_raises(TypeError, np.dtype, 'q4')
  73. assert_raises(TypeError, np.dtype, 'Q4')
  74. else:
  75. assert_raises(TypeError, np.dtype, 'q8')
  76. assert_raises(TypeError, np.dtype, 'Q8')
  77. @pytest.mark.parametrize(
  78. 'value',
  79. ['m8', 'M8', 'datetime64', 'timedelta64',
  80. 'i4, (2,3)f8, f4', 'a3, 3u8, (3,4)a10',
  81. '>f', '<f', '=f', '|f',
  82. ])
  83. def test_dtype_bytes_str_equivalence(self, value):
  84. bytes_value = value.encode('ascii')
  85. from_bytes = np.dtype(bytes_value)
  86. from_str = np.dtype(value)
  87. assert_dtype_equal(from_bytes, from_str)
  88. def test_dtype_from_bytes(self):
  89. # Empty bytes object
  90. assert_raises(TypeError, np.dtype, b'')
  91. # Byte order indicator, but no type
  92. assert_raises(TypeError, np.dtype, b'|')
  93. # Single character with ordinal < NPY_NTYPES returns
  94. # type by index into _builtin_descrs
  95. assert_dtype_equal(np.dtype(bytes([0])), np.dtype('bool'))
  96. assert_dtype_equal(np.dtype(bytes([17])), np.dtype(object))
  97. # Single character where value is a valid type code
  98. assert_dtype_equal(np.dtype(b'f'), np.dtype('float32'))
  99. # Bytes with non-ascii values raise errors
  100. assert_raises(TypeError, np.dtype, b'\xff')
  101. assert_raises(TypeError, np.dtype, b's\xff')
  102. def test_bad_param(self):
  103. # Can't give a size that's too small
  104. assert_raises(ValueError, np.dtype,
  105. {'names':['f0', 'f1'],
  106. 'formats':['i4', 'i1'],
  107. 'offsets':[0, 4],
  108. 'itemsize':4})
  109. # If alignment is enabled, the alignment (4) must divide the itemsize
  110. assert_raises(ValueError, np.dtype,
  111. {'names':['f0', 'f1'],
  112. 'formats':['i4', 'i1'],
  113. 'offsets':[0, 4],
  114. 'itemsize':9}, align=True)
  115. # If alignment is enabled, the individual fields must be aligned
  116. assert_raises(ValueError, np.dtype,
  117. {'names':['f0', 'f1'],
  118. 'formats':['i1', 'f4'],
  119. 'offsets':[0, 2]}, align=True)
  120. def test_field_order_equality(self):
  121. x = np.dtype({'names': ['A', 'B'],
  122. 'formats': ['i4', 'f4'],
  123. 'offsets': [0, 4]})
  124. y = np.dtype({'names': ['B', 'A'],
  125. 'formats': ['f4', 'i4'],
  126. 'offsets': [4, 0]})
  127. assert_equal(x == y, False)
  128. class TestRecord:
  129. def test_equivalent_record(self):
  130. """Test whether equivalent record dtypes hash the same."""
  131. a = np.dtype([('yo', int)])
  132. b = np.dtype([('yo', int)])
  133. assert_dtype_equal(a, b)
  134. def test_different_names(self):
  135. # In theory, they may hash the same (collision) ?
  136. a = np.dtype([('yo', int)])
  137. b = np.dtype([('ye', int)])
  138. assert_dtype_not_equal(a, b)
  139. def test_different_titles(self):
  140. # In theory, they may hash the same (collision) ?
  141. a = np.dtype({'names': ['r', 'b'],
  142. 'formats': ['u1', 'u1'],
  143. 'titles': ['Red pixel', 'Blue pixel']})
  144. b = np.dtype({'names': ['r', 'b'],
  145. 'formats': ['u1', 'u1'],
  146. 'titles': ['RRed pixel', 'Blue pixel']})
  147. assert_dtype_not_equal(a, b)
  148. @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
  149. def test_refcount_dictionary_setting(self):
  150. names = ["name1"]
  151. formats = ["f8"]
  152. titles = ["t1"]
  153. offsets = [0]
  154. d = dict(names=names, formats=formats, titles=titles, offsets=offsets)
  155. refcounts = {k: sys.getrefcount(i) for k, i in d.items()}
  156. np.dtype(d)
  157. refcounts_new = {k: sys.getrefcount(i) for k, i in d.items()}
  158. assert refcounts == refcounts_new
  159. def test_mutate(self):
  160. # Mutating a dtype should reset the cached hash value
  161. a = np.dtype([('yo', int)])
  162. b = np.dtype([('yo', int)])
  163. c = np.dtype([('ye', int)])
  164. assert_dtype_equal(a, b)
  165. assert_dtype_not_equal(a, c)
  166. a.names = ['ye']
  167. assert_dtype_equal(a, c)
  168. assert_dtype_not_equal(a, b)
  169. state = b.__reduce__()[2]
  170. a.__setstate__(state)
  171. assert_dtype_equal(a, b)
  172. assert_dtype_not_equal(a, c)
  173. def test_not_lists(self):
  174. """Test if an appropriate exception is raised when passing bad values to
  175. the dtype constructor.
  176. """
  177. assert_raises(TypeError, np.dtype,
  178. dict(names={'A', 'B'}, formats=['f8', 'i4']))
  179. assert_raises(TypeError, np.dtype,
  180. dict(names=['A', 'B'], formats={'f8', 'i4'}))
  181. def test_aligned_size(self):
  182. # Check that structured dtypes get padded to an aligned size
  183. dt = np.dtype('i4, i1', align=True)
  184. assert_equal(dt.itemsize, 8)
  185. dt = np.dtype([('f0', 'i4'), ('f1', 'i1')], align=True)
  186. assert_equal(dt.itemsize, 8)
  187. dt = np.dtype({'names':['f0', 'f1'],
  188. 'formats':['i4', 'u1'],
  189. 'offsets':[0, 4]}, align=True)
  190. assert_equal(dt.itemsize, 8)
  191. dt = np.dtype({'f0': ('i4', 0), 'f1':('u1', 4)}, align=True)
  192. assert_equal(dt.itemsize, 8)
  193. # Nesting should preserve that alignment
  194. dt1 = np.dtype([('f0', 'i4'),
  195. ('f1', [('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')]),
  196. ('f2', 'i1')], align=True)
  197. assert_equal(dt1.itemsize, 20)
  198. dt2 = np.dtype({'names':['f0', 'f1', 'f2'],
  199. 'formats':['i4',
  200. [('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')],
  201. 'i1'],
  202. 'offsets':[0, 4, 16]}, align=True)
  203. assert_equal(dt2.itemsize, 20)
  204. dt3 = np.dtype({'f0': ('i4', 0),
  205. 'f1': ([('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')], 4),
  206. 'f2': ('i1', 16)}, align=True)
  207. assert_equal(dt3.itemsize, 20)
  208. assert_equal(dt1, dt2)
  209. assert_equal(dt2, dt3)
  210. # Nesting should preserve packing
  211. dt1 = np.dtype([('f0', 'i4'),
  212. ('f1', [('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')]),
  213. ('f2', 'i1')], align=False)
  214. assert_equal(dt1.itemsize, 11)
  215. dt2 = np.dtype({'names':['f0', 'f1', 'f2'],
  216. 'formats':['i4',
  217. [('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')],
  218. 'i1'],
  219. 'offsets':[0, 4, 10]}, align=False)
  220. assert_equal(dt2.itemsize, 11)
  221. dt3 = np.dtype({'f0': ('i4', 0),
  222. 'f1': ([('f1', 'i1'), ('f2', 'i4'), ('f3', 'i1')], 4),
  223. 'f2': ('i1', 10)}, align=False)
  224. assert_equal(dt3.itemsize, 11)
  225. assert_equal(dt1, dt2)
  226. assert_equal(dt2, dt3)
  227. # Array of subtype should preserve alignment
  228. dt1 = np.dtype([('a', '|i1'),
  229. ('b', [('f0', '<i2'),
  230. ('f1', '<f4')], 2)], align=True)
  231. assert_equal(dt1.descr, [('a', '|i1'), ('', '|V3'),
  232. ('b', [('f0', '<i2'), ('', '|V2'),
  233. ('f1', '<f4')], (2,))])
  234. def test_union_struct(self):
  235. # Should be able to create union dtypes
  236. dt = np.dtype({'names':['f0', 'f1', 'f2'], 'formats':['<u4', '<u2', '<u2'],
  237. 'offsets':[0, 0, 2]}, align=True)
  238. assert_equal(dt.itemsize, 4)
  239. a = np.array([3], dtype='<u4').view(dt)
  240. a['f1'] = 10
  241. a['f2'] = 36
  242. assert_equal(a['f0'], 10 + 36*256*256)
  243. # Should be able to specify fields out of order
  244. dt = np.dtype({'names':['f0', 'f1', 'f2'], 'formats':['<u4', '<u2', '<u2'],
  245. 'offsets':[4, 0, 2]}, align=True)
  246. assert_equal(dt.itemsize, 8)
  247. # field name should not matter: assignment is by position
  248. dt2 = np.dtype({'names':['f2', 'f0', 'f1'],
  249. 'formats':['<u4', '<u2', '<u2'],
  250. 'offsets':[4, 0, 2]}, align=True)
  251. vals = [(0, 1, 2), (3, -1, 4)]
  252. vals2 = [(0, 1, 2), (3, -1, 4)]
  253. a = np.array(vals, dt)
  254. b = np.array(vals2, dt2)
  255. assert_equal(a.astype(dt2), b)
  256. assert_equal(b.astype(dt), a)
  257. assert_equal(a.view(dt2), b)
  258. assert_equal(b.view(dt), a)
  259. # Should not be able to overlap objects with other types
  260. assert_raises(TypeError, np.dtype,
  261. {'names':['f0', 'f1'],
  262. 'formats':['O', 'i1'],
  263. 'offsets':[0, 2]})
  264. assert_raises(TypeError, np.dtype,
  265. {'names':['f0', 'f1'],
  266. 'formats':['i4', 'O'],
  267. 'offsets':[0, 3]})
  268. assert_raises(TypeError, np.dtype,
  269. {'names':['f0', 'f1'],
  270. 'formats':[[('a', 'O')], 'i1'],
  271. 'offsets':[0, 2]})
  272. assert_raises(TypeError, np.dtype,
  273. {'names':['f0', 'f1'],
  274. 'formats':['i4', [('a', 'O')]],
  275. 'offsets':[0, 3]})
  276. # Out of order should still be ok, however
  277. dt = np.dtype({'names':['f0', 'f1'],
  278. 'formats':['i1', 'O'],
  279. 'offsets':[np.dtype('intp').itemsize, 0]})
  280. def test_comma_datetime(self):
  281. dt = np.dtype('M8[D],datetime64[Y],i8')
  282. assert_equal(dt, np.dtype([('f0', 'M8[D]'),
  283. ('f1', 'datetime64[Y]'),
  284. ('f2', 'i8')]))
  285. def test_from_dictproxy(self):
  286. # Tests for PR #5920
  287. dt = np.dtype({'names': ['a', 'b'], 'formats': ['i4', 'f4']})
  288. assert_dtype_equal(dt, np.dtype(dt.fields))
  289. dt2 = np.dtype((np.void, dt.fields))
  290. assert_equal(dt2.fields, dt.fields)
  291. def test_from_dict_with_zero_width_field(self):
  292. # Regression test for #6430 / #2196
  293. dt = np.dtype([('val1', np.float32, (0,)), ('val2', int)])
  294. dt2 = np.dtype({'names': ['val1', 'val2'],
  295. 'formats': [(np.float32, (0,)), int]})
  296. assert_dtype_equal(dt, dt2)
  297. assert_equal(dt.fields['val1'][0].itemsize, 0)
  298. assert_equal(dt.itemsize, dt.fields['val2'][0].itemsize)
  299. def test_bool_commastring(self):
  300. d = np.dtype('?,?,?') # raises?
  301. assert_equal(len(d.names), 3)
  302. for n in d.names:
  303. assert_equal(d.fields[n][0], np.dtype('?'))
  304. def test_nonint_offsets(self):
  305. # gh-8059
  306. def make_dtype(off):
  307. return np.dtype({'names': ['A'], 'formats': ['i4'],
  308. 'offsets': [off]})
  309. assert_raises(TypeError, make_dtype, 'ASD')
  310. assert_raises(OverflowError, make_dtype, 2**70)
  311. assert_raises(TypeError, make_dtype, 2.3)
  312. assert_raises(ValueError, make_dtype, -10)
  313. # no errors here:
  314. dt = make_dtype(np.uint32(0))
  315. np.zeros(1, dtype=dt)[0].item()
  316. def test_fields_by_index(self):
  317. dt = np.dtype([('a', np.int8), ('b', np.float32, 3)])
  318. assert_dtype_equal(dt[0], np.dtype(np.int8))
  319. assert_dtype_equal(dt[1], np.dtype((np.float32, 3)))
  320. assert_dtype_equal(dt[-1], dt[1])
  321. assert_dtype_equal(dt[-2], dt[0])
  322. assert_raises(IndexError, lambda: dt[-3])
  323. assert_raises(TypeError, operator.getitem, dt, 3.0)
  324. assert_equal(dt[1], dt[np.int8(1)])
  325. @pytest.mark.parametrize('align_flag',[False, True])
  326. def test_multifield_index(self, align_flag):
  327. # indexing with a list produces subfields
  328. # the align flag should be preserved
  329. dt = np.dtype([
  330. (('title', 'col1'), '<U20'), ('A', '<f8'), ('B', '<f8')
  331. ], align=align_flag)
  332. dt_sub = dt[['B', 'col1']]
  333. assert_equal(
  334. dt_sub,
  335. np.dtype({
  336. 'names': ['B', 'col1'],
  337. 'formats': ['<f8', '<U20'],
  338. 'offsets': [88, 0],
  339. 'titles': [None, 'title'],
  340. 'itemsize': 96
  341. })
  342. )
  343. assert_equal(dt_sub.isalignedstruct, align_flag)
  344. dt_sub = dt[['B']]
  345. assert_equal(
  346. dt_sub,
  347. np.dtype({
  348. 'names': ['B'],
  349. 'formats': ['<f8'],
  350. 'offsets': [88],
  351. 'itemsize': 96
  352. })
  353. )
  354. assert_equal(dt_sub.isalignedstruct, align_flag)
  355. dt_sub = dt[[]]
  356. assert_equal(
  357. dt_sub,
  358. np.dtype({
  359. 'names': [],
  360. 'formats': [],
  361. 'offsets': [],
  362. 'itemsize': 96
  363. })
  364. )
  365. assert_equal(dt_sub.isalignedstruct, align_flag)
  366. assert_raises(TypeError, operator.getitem, dt, ())
  367. assert_raises(TypeError, operator.getitem, dt, [1, 2, 3])
  368. assert_raises(TypeError, operator.getitem, dt, ['col1', 2])
  369. assert_raises(KeyError, operator.getitem, dt, ['fake'])
  370. assert_raises(KeyError, operator.getitem, dt, ['title'])
  371. assert_raises(ValueError, operator.getitem, dt, ['col1', 'col1'])
  372. def test_partial_dict(self):
  373. # 'names' is missing
  374. assert_raises(ValueError, np.dtype,
  375. {'formats': ['i4', 'i4'], 'f0': ('i4', 0), 'f1':('i4', 4)})
  376. def test_fieldless_views(self):
  377. a = np.zeros(2, dtype={'names':[], 'formats':[], 'offsets':[],
  378. 'itemsize':8})
  379. assert_raises(ValueError, a.view, np.dtype([]))
  380. d = np.dtype((np.dtype([]), 10))
  381. assert_equal(d.shape, (10,))
  382. assert_equal(d.itemsize, 0)
  383. assert_equal(d.base, np.dtype([]))
  384. arr = np.fromiter((() for i in range(10)), [])
  385. assert_equal(arr.dtype, np.dtype([]))
  386. assert_raises(ValueError, np.frombuffer, b'', dtype=[])
  387. assert_equal(np.frombuffer(b'', dtype=[], count=2),
  388. np.empty(2, dtype=[]))
  389. assert_raises(ValueError, np.dtype, ([], 'f8'))
  390. assert_raises(ValueError, np.zeros(1, dtype='i4').view, [])
  391. assert_equal(np.zeros(2, dtype=[]) == np.zeros(2, dtype=[]),
  392. np.ones(2, dtype=bool))
  393. assert_equal(np.zeros((1, 2), dtype=[]) == a,
  394. np.ones((1, 2), dtype=bool))
  395. class TestSubarray:
  396. def test_single_subarray(self):
  397. a = np.dtype((int, (2)))
  398. b = np.dtype((int, (2,)))
  399. assert_dtype_equal(a, b)
  400. assert_equal(type(a.subdtype[1]), tuple)
  401. assert_equal(type(b.subdtype[1]), tuple)
  402. def test_equivalent_record(self):
  403. """Test whether equivalent subarray dtypes hash the same."""
  404. a = np.dtype((int, (2, 3)))
  405. b = np.dtype((int, (2, 3)))
  406. assert_dtype_equal(a, b)
  407. def test_nonequivalent_record(self):
  408. """Test whether different subarray dtypes hash differently."""
  409. a = np.dtype((int, (2, 3)))
  410. b = np.dtype((int, (3, 2)))
  411. assert_dtype_not_equal(a, b)
  412. a = np.dtype((int, (2, 3)))
  413. b = np.dtype((int, (2, 2)))
  414. assert_dtype_not_equal(a, b)
  415. a = np.dtype((int, (1, 2, 3)))
  416. b = np.dtype((int, (1, 2)))
  417. assert_dtype_not_equal(a, b)
  418. def test_shape_equal(self):
  419. """Test some data types that are equal"""
  420. assert_dtype_equal(np.dtype('f8'), np.dtype(('f8', tuple())))
  421. # FutureWarning during deprecation period; after it is passed this
  422. # should instead check that "(1)f8" == "1f8" == ("f8", 1).
  423. with pytest.warns(FutureWarning):
  424. assert_dtype_equal(np.dtype('f8'), np.dtype(('f8', 1)))
  425. assert_dtype_equal(np.dtype((int, 2)), np.dtype((int, (2,))))
  426. assert_dtype_equal(np.dtype(('<f4', (3, 2))), np.dtype(('<f4', (3, 2))))
  427. d = ([('a', 'f4', (1, 2)), ('b', 'f8', (3, 1))], (3, 2))
  428. assert_dtype_equal(np.dtype(d), np.dtype(d))
  429. def test_shape_simple(self):
  430. """Test some simple cases that shouldn't be equal"""
  431. assert_dtype_not_equal(np.dtype('f8'), np.dtype(('f8', (1,))))
  432. assert_dtype_not_equal(np.dtype(('f8', (1,))), np.dtype(('f8', (1, 1))))
  433. assert_dtype_not_equal(np.dtype(('f4', (3, 2))), np.dtype(('f4', (2, 3))))
  434. def test_shape_monster(self):
  435. """Test some more complicated cases that shouldn't be equal"""
  436. assert_dtype_not_equal(
  437. np.dtype(([('a', 'f4', (2, 1)), ('b', 'f8', (1, 3))], (2, 2))),
  438. np.dtype(([('a', 'f4', (1, 2)), ('b', 'f8', (1, 3))], (2, 2))))
  439. assert_dtype_not_equal(
  440. np.dtype(([('a', 'f4', (2, 1)), ('b', 'f8', (1, 3))], (2, 2))),
  441. np.dtype(([('a', 'f4', (2, 1)), ('b', 'i8', (1, 3))], (2, 2))))
  442. assert_dtype_not_equal(
  443. np.dtype(([('a', 'f4', (2, 1)), ('b', 'f8', (1, 3))], (2, 2))),
  444. np.dtype(([('e', 'f8', (1, 3)), ('d', 'f4', (2, 1))], (2, 2))))
  445. assert_dtype_not_equal(
  446. np.dtype(([('a', [('a', 'i4', 6)], (2, 1)), ('b', 'f8', (1, 3))], (2, 2))),
  447. np.dtype(([('a', [('a', 'u4', 6)], (2, 1)), ('b', 'f8', (1, 3))], (2, 2))))
  448. def test_shape_sequence(self):
  449. # Any sequence of integers should work as shape, but the result
  450. # should be a tuple (immutable) of base type integers.
  451. a = np.array([1, 2, 3], dtype=np.int16)
  452. l = [1, 2, 3]
  453. # Array gets converted
  454. dt = np.dtype([('a', 'f4', a)])
  455. assert_(isinstance(dt['a'].shape, tuple))
  456. assert_(isinstance(dt['a'].shape[0], int))
  457. # List gets converted
  458. dt = np.dtype([('a', 'f4', l)])
  459. assert_(isinstance(dt['a'].shape, tuple))
  460. #
  461. class IntLike:
  462. def __index__(self):
  463. return 3
  464. def __int__(self):
  465. # (a PyNumber_Check fails without __int__)
  466. return 3
  467. dt = np.dtype([('a', 'f4', IntLike())])
  468. assert_(isinstance(dt['a'].shape, tuple))
  469. assert_(isinstance(dt['a'].shape[0], int))
  470. dt = np.dtype([('a', 'f4', (IntLike(),))])
  471. assert_(isinstance(dt['a'].shape, tuple))
  472. assert_(isinstance(dt['a'].shape[0], int))
  473. def test_shape_matches_ndim(self):
  474. dt = np.dtype([('a', 'f4', ())])
  475. assert_equal(dt['a'].shape, ())
  476. assert_equal(dt['a'].ndim, 0)
  477. dt = np.dtype([('a', 'f4')])
  478. assert_equal(dt['a'].shape, ())
  479. assert_equal(dt['a'].ndim, 0)
  480. dt = np.dtype([('a', 'f4', 4)])
  481. assert_equal(dt['a'].shape, (4,))
  482. assert_equal(dt['a'].ndim, 1)
  483. dt = np.dtype([('a', 'f4', (1, 2, 3))])
  484. assert_equal(dt['a'].shape, (1, 2, 3))
  485. assert_equal(dt['a'].ndim, 3)
  486. def test_shape_invalid(self):
  487. # Check that the shape is valid.
  488. max_int = np.iinfo(np.intc).max
  489. max_intp = np.iinfo(np.intp).max
  490. # Too large values (the datatype is part of this)
  491. assert_raises(ValueError, np.dtype, [('a', 'f4', max_int // 4 + 1)])
  492. assert_raises(ValueError, np.dtype, [('a', 'f4', max_int + 1)])
  493. assert_raises(ValueError, np.dtype, [('a', 'f4', (max_int, 2))])
  494. # Takes a different code path (fails earlier:
  495. assert_raises(ValueError, np.dtype, [('a', 'f4', max_intp + 1)])
  496. # Negative values
  497. assert_raises(ValueError, np.dtype, [('a', 'f4', -1)])
  498. assert_raises(ValueError, np.dtype, [('a', 'f4', (-1, -1))])
  499. def test_alignment(self):
  500. #Check that subarrays are aligned
  501. t1 = np.dtype('(1,)i4', align=True)
  502. t2 = np.dtype('2i4', align=True)
  503. assert_equal(t1.alignment, t2.alignment)
  504. def iter_struct_object_dtypes():
  505. """
  506. Iterates over a few complex dtypes and object pattern which
  507. fill the array with a given object (defaults to a singleton).
  508. Yields
  509. ------
  510. dtype : dtype
  511. pattern : tuple
  512. Structured tuple for use with `np.array`.
  513. count : int
  514. Number of objects stored in the dtype.
  515. singleton : object
  516. A singleton object. The returned pattern is constructed so that
  517. all objects inside the datatype are set to the singleton.
  518. """
  519. obj = object()
  520. dt = np.dtype([('b', 'O', (2, 3))])
  521. p = ([[obj] * 3] * 2,)
  522. yield pytest.param(dt, p, 6, obj, id="<subarray>")
  523. dt = np.dtype([('a', 'i4'), ('b', 'O', (2, 3))])
  524. p = (0, [[obj] * 3] * 2)
  525. yield pytest.param(dt, p, 6, obj, id="<subarray in field>")
  526. dt = np.dtype([('a', 'i4'),
  527. ('b', [('ba', 'O'), ('bb', 'i1')], (2, 3))])
  528. p = (0, [[(obj, 0)] * 3] * 2)
  529. yield pytest.param(dt, p, 6, obj, id="<structured subarray 1>")
  530. dt = np.dtype([('a', 'i4'),
  531. ('b', [('ba', 'O'), ('bb', 'O')], (2, 3))])
  532. p = (0, [[(obj, obj)] * 3] * 2)
  533. yield pytest.param(dt, p, 12, obj, id="<structured subarray 2>")
  534. @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
  535. class TestStructuredObjectRefcounting:
  536. """These tests cover various uses of complicated structured types which
  537. include objects and thus require reference counting.
  538. """
  539. @pytest.mark.parametrize(['dt', 'pat', 'count', 'singleton'],
  540. iter_struct_object_dtypes())
  541. @pytest.mark.parametrize(["creation_func", "creation_obj"], [
  542. pytest.param(np.empty, None,
  543. # None is probably used for too many things
  544. marks=pytest.mark.skip("unreliable due to python's behaviour")),
  545. (np.ones, 1),
  546. (np.zeros, 0)])
  547. def test_structured_object_create_delete(self, dt, pat, count, singleton,
  548. creation_func, creation_obj):
  549. """Structured object reference counting in creation and deletion"""
  550. # The test assumes that 0, 1, and None are singletons.
  551. gc.collect()
  552. before = sys.getrefcount(creation_obj)
  553. arr = creation_func(3, dt)
  554. now = sys.getrefcount(creation_obj)
  555. assert now - before == count * 3
  556. del arr
  557. now = sys.getrefcount(creation_obj)
  558. assert now == before
  559. @pytest.mark.parametrize(['dt', 'pat', 'count', 'singleton'],
  560. iter_struct_object_dtypes())
  561. def test_structured_object_item_setting(self, dt, pat, count, singleton):
  562. """Structured object reference counting for simple item setting"""
  563. one = 1
  564. gc.collect()
  565. before = sys.getrefcount(singleton)
  566. arr = np.array([pat] * 3, dt)
  567. assert sys.getrefcount(singleton) - before == count * 3
  568. # Fill with `1` and check that it was replaced correctly:
  569. before2 = sys.getrefcount(one)
  570. arr[...] = one
  571. after2 = sys.getrefcount(one)
  572. assert after2 - before2 == count * 3
  573. del arr
  574. gc.collect()
  575. assert sys.getrefcount(one) == before2
  576. assert sys.getrefcount(singleton) == before
  577. @pytest.mark.parametrize(['dt', 'pat', 'count', 'singleton'],
  578. iter_struct_object_dtypes())
  579. @pytest.mark.parametrize(
  580. ['shape', 'index', 'items_changed'],
  581. [((3,), ([0, 2],), 2),
  582. ((3, 2), ([0, 2], slice(None)), 4),
  583. ((3, 2), ([0, 2], [1]), 2),
  584. ((3,), ([True, False, True]), 2)])
  585. def test_structured_object_indexing(self, shape, index, items_changed,
  586. dt, pat, count, singleton):
  587. """Structured object reference counting for advanced indexing."""
  588. zero = 0
  589. one = 1
  590. arr = np.zeros(shape, dt)
  591. gc.collect()
  592. before_zero = sys.getrefcount(zero)
  593. before_one = sys.getrefcount(one)
  594. # Test item getting:
  595. part = arr[index]
  596. after_zero = sys.getrefcount(zero)
  597. assert after_zero - before_zero == count * items_changed
  598. del part
  599. # Test item setting:
  600. arr[index] = one
  601. gc.collect()
  602. after_zero = sys.getrefcount(zero)
  603. after_one = sys.getrefcount(one)
  604. assert before_zero - after_zero == count * items_changed
  605. assert after_one - before_one == count * items_changed
  606. @pytest.mark.parametrize(['dt', 'pat', 'count', 'singleton'],
  607. iter_struct_object_dtypes())
  608. def test_structured_object_take_and_repeat(self, dt, pat, count, singleton):
  609. """Structured object reference counting for specialized functions.
  610. The older functions such as take and repeat use different code paths
  611. then item setting (when writing this).
  612. """
  613. indices = [0, 1]
  614. arr = np.array([pat] * 3, dt)
  615. gc.collect()
  616. before = sys.getrefcount(singleton)
  617. res = arr.take(indices)
  618. after = sys.getrefcount(singleton)
  619. assert after - before == count * 2
  620. new = res.repeat(10)
  621. gc.collect()
  622. after_repeat = sys.getrefcount(singleton)
  623. assert after_repeat - after == count * 2 * 10
  624. class TestStructuredDtypeSparseFields:
  625. """Tests subarray fields which contain sparse dtypes so that
  626. not all memory is used by the dtype work. Such dtype's should
  627. leave the underlying memory unchanged.
  628. """
  629. dtype = np.dtype([('a', {'names':['aa', 'ab'], 'formats':['f', 'f'],
  630. 'offsets':[0, 4]}, (2, 3))])
  631. sparse_dtype = np.dtype([('a', {'names':['ab'], 'formats':['f'],
  632. 'offsets':[4]}, (2, 3))])
  633. @pytest.mark.xfail(reason="inaccessible data is changed see gh-12686.")
  634. @pytest.mark.valgrind_error(reason="reads from uninitialized buffers.")
  635. def test_sparse_field_assignment(self):
  636. arr = np.zeros(3, self.dtype)
  637. sparse_arr = arr.view(self.sparse_dtype)
  638. sparse_arr[...] = np.finfo(np.float32).max
  639. # dtype is reduced when accessing the field, so shape is (3, 2, 3):
  640. assert_array_equal(arr["a"]["aa"], np.zeros((3, 2, 3)))
  641. def test_sparse_field_assignment_fancy(self):
  642. # Fancy assignment goes to the copyswap function for complex types:
  643. arr = np.zeros(3, self.dtype)
  644. sparse_arr = arr.view(self.sparse_dtype)
  645. sparse_arr[[0, 1, 2]] = np.finfo(np.float32).max
  646. # dtype is reduced when accessing the field, so shape is (3, 2, 3):
  647. assert_array_equal(arr["a"]["aa"], np.zeros((3, 2, 3)))
  648. class TestMonsterType:
  649. """Test deeply nested subtypes."""
  650. def test1(self):
  651. simple1 = np.dtype({'names': ['r', 'b'], 'formats': ['u1', 'u1'],
  652. 'titles': ['Red pixel', 'Blue pixel']})
  653. a = np.dtype([('yo', int), ('ye', simple1),
  654. ('yi', np.dtype((int, (3, 2))))])
  655. b = np.dtype([('yo', int), ('ye', simple1),
  656. ('yi', np.dtype((int, (3, 2))))])
  657. assert_dtype_equal(a, b)
  658. c = np.dtype([('yo', int), ('ye', simple1),
  659. ('yi', np.dtype((a, (3, 2))))])
  660. d = np.dtype([('yo', int), ('ye', simple1),
  661. ('yi', np.dtype((a, (3, 2))))])
  662. assert_dtype_equal(c, d)
  663. class TestMetadata:
  664. def test_no_metadata(self):
  665. d = np.dtype(int)
  666. assert_(d.metadata is None)
  667. def test_metadata_takes_dict(self):
  668. d = np.dtype(int, metadata={'datum': 1})
  669. assert_(d.metadata == {'datum': 1})
  670. def test_metadata_rejects_nondict(self):
  671. assert_raises(TypeError, np.dtype, int, metadata='datum')
  672. assert_raises(TypeError, np.dtype, int, metadata=1)
  673. assert_raises(TypeError, np.dtype, int, metadata=None)
  674. def test_nested_metadata(self):
  675. d = np.dtype([('a', np.dtype(int, metadata={'datum': 1}))])
  676. assert_(d['a'].metadata == {'datum': 1})
  677. def test_base_metadata_copied(self):
  678. d = np.dtype((np.void, np.dtype('i4,i4', metadata={'datum': 1})))
  679. assert_(d.metadata == {'datum': 1})
  680. class TestString:
  681. def test_complex_dtype_str(self):
  682. dt = np.dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)),
  683. ('rtile', '>f4', (64, 36))], (3,)),
  684. ('bottom', [('bleft', ('>f4', (8, 64)), (1,)),
  685. ('bright', '>f4', (8, 36))])])
  686. assert_equal(str(dt),
  687. "[('top', [('tiles', ('>f4', (64, 64)), (1,)), "
  688. "('rtile', '>f4', (64, 36))], (3,)), "
  689. "('bottom', [('bleft', ('>f4', (8, 64)), (1,)), "
  690. "('bright', '>f4', (8, 36))])]")
  691. # If the sticky aligned flag is set to True, it makes the
  692. # str() function use a dict representation with an 'aligned' flag
  693. dt = np.dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)),
  694. ('rtile', '>f4', (64, 36))],
  695. (3,)),
  696. ('bottom', [('bleft', ('>f4', (8, 64)), (1,)),
  697. ('bright', '>f4', (8, 36))])],
  698. align=True)
  699. assert_equal(str(dt),
  700. "{'names':['top','bottom'], "
  701. "'formats':[([('tiles', ('>f4', (64, 64)), (1,)), "
  702. "('rtile', '>f4', (64, 36))], (3,)),"
  703. "[('bleft', ('>f4', (8, 64)), (1,)), "
  704. "('bright', '>f4', (8, 36))]], "
  705. "'offsets':[0,76800], "
  706. "'itemsize':80000, "
  707. "'aligned':True}")
  708. assert_equal(np.dtype(eval(str(dt))), dt)
  709. dt = np.dtype({'names': ['r', 'g', 'b'], 'formats': ['u1', 'u1', 'u1'],
  710. 'offsets': [0, 1, 2],
  711. 'titles': ['Red pixel', 'Green pixel', 'Blue pixel']})
  712. assert_equal(str(dt),
  713. "[(('Red pixel', 'r'), 'u1'), "
  714. "(('Green pixel', 'g'), 'u1'), "
  715. "(('Blue pixel', 'b'), 'u1')]")
  716. dt = np.dtype({'names': ['rgba', 'r', 'g', 'b'],
  717. 'formats': ['<u4', 'u1', 'u1', 'u1'],
  718. 'offsets': [0, 0, 1, 2],
  719. 'titles': ['Color', 'Red pixel',
  720. 'Green pixel', 'Blue pixel']})
  721. assert_equal(str(dt),
  722. "{'names':['rgba','r','g','b'],"
  723. " 'formats':['<u4','u1','u1','u1'],"
  724. " 'offsets':[0,0,1,2],"
  725. " 'titles':['Color','Red pixel',"
  726. "'Green pixel','Blue pixel'],"
  727. " 'itemsize':4}")
  728. dt = np.dtype({'names': ['r', 'b'], 'formats': ['u1', 'u1'],
  729. 'offsets': [0, 2],
  730. 'titles': ['Red pixel', 'Blue pixel']})
  731. assert_equal(str(dt),
  732. "{'names':['r','b'],"
  733. " 'formats':['u1','u1'],"
  734. " 'offsets':[0,2],"
  735. " 'titles':['Red pixel','Blue pixel'],"
  736. " 'itemsize':3}")
  737. dt = np.dtype([('a', '<m8[D]'), ('b', '<M8[us]')])
  738. assert_equal(str(dt),
  739. "[('a', '<m8[D]'), ('b', '<M8[us]')]")
  740. def test_repr_structured(self):
  741. dt = np.dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)),
  742. ('rtile', '>f4', (64, 36))], (3,)),
  743. ('bottom', [('bleft', ('>f4', (8, 64)), (1,)),
  744. ('bright', '>f4', (8, 36))])])
  745. assert_equal(repr(dt),
  746. "dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)), "
  747. "('rtile', '>f4', (64, 36))], (3,)), "
  748. "('bottom', [('bleft', ('>f4', (8, 64)), (1,)), "
  749. "('bright', '>f4', (8, 36))])])")
  750. dt = np.dtype({'names': ['r', 'g', 'b'], 'formats': ['u1', 'u1', 'u1'],
  751. 'offsets': [0, 1, 2],
  752. 'titles': ['Red pixel', 'Green pixel', 'Blue pixel']},
  753. align=True)
  754. assert_equal(repr(dt),
  755. "dtype([(('Red pixel', 'r'), 'u1'), "
  756. "(('Green pixel', 'g'), 'u1'), "
  757. "(('Blue pixel', 'b'), 'u1')], align=True)")
  758. def test_repr_structured_not_packed(self):
  759. dt = np.dtype({'names': ['rgba', 'r', 'g', 'b'],
  760. 'formats': ['<u4', 'u1', 'u1', 'u1'],
  761. 'offsets': [0, 0, 1, 2],
  762. 'titles': ['Color', 'Red pixel',
  763. 'Green pixel', 'Blue pixel']}, align=True)
  764. assert_equal(repr(dt),
  765. "dtype({'names':['rgba','r','g','b'],"
  766. " 'formats':['<u4','u1','u1','u1'],"
  767. " 'offsets':[0,0,1,2],"
  768. " 'titles':['Color','Red pixel',"
  769. "'Green pixel','Blue pixel'],"
  770. " 'itemsize':4}, align=True)")
  771. dt = np.dtype({'names': ['r', 'b'], 'formats': ['u1', 'u1'],
  772. 'offsets': [0, 2],
  773. 'titles': ['Red pixel', 'Blue pixel'],
  774. 'itemsize': 4})
  775. assert_equal(repr(dt),
  776. "dtype({'names':['r','b'], "
  777. "'formats':['u1','u1'], "
  778. "'offsets':[0,2], "
  779. "'titles':['Red pixel','Blue pixel'], "
  780. "'itemsize':4})")
  781. def test_repr_structured_datetime(self):
  782. dt = np.dtype([('a', '<M8[D]'), ('b', '<m8[us]')])
  783. assert_equal(repr(dt),
  784. "dtype([('a', '<M8[D]'), ('b', '<m8[us]')])")
  785. def test_repr_str_subarray(self):
  786. dt = np.dtype(('<i2', (1,)))
  787. assert_equal(repr(dt), "dtype(('<i2', (1,)))")
  788. assert_equal(str(dt), "('<i2', (1,))")
  789. def test_base_dtype_with_object_type(self):
  790. # Issue gh-2798, should not error.
  791. np.array(['a'], dtype="O").astype(("O", [("name", "O")]))
  792. def test_empty_string_to_object(self):
  793. # Pull request #4722
  794. np.array(["", ""]).astype(object)
  795. def test_void_subclass_unsized(self):
  796. dt = np.dtype(np.record)
  797. assert_equal(repr(dt), "dtype('V')")
  798. assert_equal(str(dt), '|V0')
  799. assert_equal(dt.name, 'record')
  800. def test_void_subclass_sized(self):
  801. dt = np.dtype((np.record, 2))
  802. assert_equal(repr(dt), "dtype('V2')")
  803. assert_equal(str(dt), '|V2')
  804. assert_equal(dt.name, 'record16')
  805. def test_void_subclass_fields(self):
  806. dt = np.dtype((np.record, [('a', '<u2')]))
  807. assert_equal(repr(dt), "dtype((numpy.record, [('a', '<u2')]))")
  808. assert_equal(str(dt), "(numpy.record, [('a', '<u2')])")
  809. assert_equal(dt.name, 'record16')
  810. class TestDtypeAttributeDeletion:
  811. def test_dtype_non_writable_attributes_deletion(self):
  812. dt = np.dtype(np.double)
  813. attr = ["subdtype", "descr", "str", "name", "base", "shape",
  814. "isbuiltin", "isnative", "isalignedstruct", "fields",
  815. "metadata", "hasobject"]
  816. for s in attr:
  817. assert_raises(AttributeError, delattr, dt, s)
  818. def test_dtype_writable_attributes_deletion(self):
  819. dt = np.dtype(np.double)
  820. attr = ["names"]
  821. for s in attr:
  822. assert_raises(AttributeError, delattr, dt, s)
  823. class TestDtypeAttributes:
  824. def test_descr_has_trailing_void(self):
  825. # see gh-6359
  826. dtype = np.dtype({
  827. 'names': ['A', 'B'],
  828. 'formats': ['f4', 'f4'],
  829. 'offsets': [0, 8],
  830. 'itemsize': 16})
  831. new_dtype = np.dtype(dtype.descr)
  832. assert_equal(new_dtype.itemsize, 16)
  833. def test_name_dtype_subclass(self):
  834. # Ticket #4357
  835. class user_def_subcls(np.void):
  836. pass
  837. assert_equal(np.dtype(user_def_subcls).name, 'user_def_subcls')
  838. class TestPickling:
  839. def check_pickling(self, dtype):
  840. for proto in range(pickle.HIGHEST_PROTOCOL + 1):
  841. pickled = pickle.loads(pickle.dumps(dtype, proto))
  842. assert_equal(pickled, dtype)
  843. assert_equal(pickled.descr, dtype.descr)
  844. if dtype.metadata is not None:
  845. assert_equal(pickled.metadata, dtype.metadata)
  846. # Check the reconstructed dtype is functional
  847. x = np.zeros(3, dtype=dtype)
  848. y = np.zeros(3, dtype=pickled)
  849. assert_equal(x, y)
  850. assert_equal(x[0], y[0])
  851. @pytest.mark.parametrize('t', [int, float, complex, np.int32, str, object,
  852. np.compat.unicode, bool])
  853. def test_builtin(self, t):
  854. self.check_pickling(np.dtype(t))
  855. def test_structured(self):
  856. dt = np.dtype(([('a', '>f4', (2, 1)), ('b', '<f8', (1, 3))], (2, 2)))
  857. self.check_pickling(dt)
  858. def test_structured_aligned(self):
  859. dt = np.dtype('i4, i1', align=True)
  860. self.check_pickling(dt)
  861. def test_structured_unaligned(self):
  862. dt = np.dtype('i4, i1', align=False)
  863. self.check_pickling(dt)
  864. def test_structured_padded(self):
  865. dt = np.dtype({
  866. 'names': ['A', 'B'],
  867. 'formats': ['f4', 'f4'],
  868. 'offsets': [0, 8],
  869. 'itemsize': 16})
  870. self.check_pickling(dt)
  871. def test_structured_titles(self):
  872. dt = np.dtype({'names': ['r', 'b'],
  873. 'formats': ['u1', 'u1'],
  874. 'titles': ['Red pixel', 'Blue pixel']})
  875. self.check_pickling(dt)
  876. @pytest.mark.parametrize('base', ['m8', 'M8'])
  877. @pytest.mark.parametrize('unit', ['', 'Y', 'M', 'W', 'D', 'h', 'm', 's',
  878. 'ms', 'us', 'ns', 'ps', 'fs', 'as'])
  879. def test_datetime(self, base, unit):
  880. dt = np.dtype('%s[%s]' % (base, unit) if unit else base)
  881. self.check_pickling(dt)
  882. if unit:
  883. dt = np.dtype('%s[7%s]' % (base, unit))
  884. self.check_pickling(dt)
  885. def test_metadata(self):
  886. dt = np.dtype(int, metadata={'datum': 1})
  887. self.check_pickling(dt)
  888. def test_rational_dtype():
  889. # test for bug gh-5719
  890. a = np.array([1111], dtype=rational).astype
  891. assert_raises(OverflowError, a, 'int8')
  892. # test that dtype detection finds user-defined types
  893. x = rational(1)
  894. assert_equal(np.array([x,x]).dtype, np.dtype(rational))
  895. def test_dtypes_are_true():
  896. # test for gh-6294
  897. assert bool(np.dtype('f8'))
  898. assert bool(np.dtype('i8'))
  899. assert bool(np.dtype([('a', 'i8'), ('b', 'f4')]))
  900. def test_invalid_dtype_string():
  901. # test for gh-10440
  902. assert_raises(TypeError, np.dtype, 'f8,i8,[f8,i8]')
  903. assert_raises(TypeError, np.dtype, u'Fl\xfcgel')
  904. class TestFromDTypeAttribute:
  905. def test_simple(self):
  906. class dt:
  907. dtype = "f8"
  908. assert np.dtype(dt) == np.float64
  909. assert np.dtype(dt()) == np.float64
  910. def test_recursion(self):
  911. class dt:
  912. pass
  913. dt.dtype = dt
  914. with pytest.raises(RecursionError):
  915. np.dtype(dt)
  916. dt_instance = dt()
  917. dt_instance.dtype = dt
  918. with pytest.raises(RecursionError):
  919. np.dtype(dt_instance)
  920. def test_void_subtype(self):
  921. class dt(np.void):
  922. # This code path is fully untested before, so it is unclear
  923. # what this should be useful for. Note that if np.void is used
  924. # numpy will think we are deallocating a base type [1.17, 2019-02].
  925. dtype = np.dtype("f,f")
  926. pass
  927. np.dtype(dt)
  928. np.dtype(dt(1))
  929. def test_void_subtype_recursion(self):
  930. class dt(np.void):
  931. pass
  932. dt.dtype = dt
  933. with pytest.raises(RecursionError):
  934. np.dtype(dt)
  935. with pytest.raises(RecursionError):
  936. np.dtype(dt(1))
  937. class TestFromCTypes:
  938. @staticmethod
  939. def check(ctype, dtype):
  940. dtype = np.dtype(dtype)
  941. assert_equal(np.dtype(ctype), dtype)
  942. assert_equal(np.dtype(ctype()), dtype)
  943. def test_array(self):
  944. c8 = ctypes.c_uint8
  945. self.check( 3 * c8, (np.uint8, (3,)))
  946. self.check( 1 * c8, (np.uint8, (1,)))
  947. self.check( 0 * c8, (np.uint8, (0,)))
  948. self.check(1 * (3 * c8), ((np.uint8, (3,)), (1,)))
  949. self.check(3 * (1 * c8), ((np.uint8, (1,)), (3,)))
  950. def test_padded_structure(self):
  951. class PaddedStruct(ctypes.Structure):
  952. _fields_ = [
  953. ('a', ctypes.c_uint8),
  954. ('b', ctypes.c_uint16)
  955. ]
  956. expected = np.dtype([
  957. ('a', np.uint8),
  958. ('b', np.uint16)
  959. ], align=True)
  960. self.check(PaddedStruct, expected)
  961. def test_bit_fields(self):
  962. class BitfieldStruct(ctypes.Structure):
  963. _fields_ = [
  964. ('a', ctypes.c_uint8, 7),
  965. ('b', ctypes.c_uint8, 1)
  966. ]
  967. assert_raises(TypeError, np.dtype, BitfieldStruct)
  968. assert_raises(TypeError, np.dtype, BitfieldStruct())
  969. def test_pointer(self):
  970. p_uint8 = ctypes.POINTER(ctypes.c_uint8)
  971. assert_raises(TypeError, np.dtype, p_uint8)
  972. def test_void_pointer(self):
  973. self.check(ctypes.c_void_p, np.uintp)
  974. def test_union(self):
  975. class Union(ctypes.Union):
  976. _fields_ = [
  977. ('a', ctypes.c_uint8),
  978. ('b', ctypes.c_uint16),
  979. ]
  980. expected = np.dtype(dict(
  981. names=['a', 'b'],
  982. formats=[np.uint8, np.uint16],
  983. offsets=[0, 0],
  984. itemsize=2
  985. ))
  986. self.check(Union, expected)
  987. def test_union_with_struct_packed(self):
  988. class Struct(ctypes.Structure):
  989. _pack_ = 1
  990. _fields_ = [
  991. ('one', ctypes.c_uint8),
  992. ('two', ctypes.c_uint32)
  993. ]
  994. class Union(ctypes.Union):
  995. _fields_ = [
  996. ('a', ctypes.c_uint8),
  997. ('b', ctypes.c_uint16),
  998. ('c', ctypes.c_uint32),
  999. ('d', Struct),
  1000. ]
  1001. expected = np.dtype(dict(
  1002. names=['a', 'b', 'c', 'd'],
  1003. formats=['u1', np.uint16, np.uint32, [('one', 'u1'), ('two', np.uint32)]],
  1004. offsets=[0, 0, 0, 0],
  1005. itemsize=ctypes.sizeof(Union)
  1006. ))
  1007. self.check(Union, expected)
  1008. def test_union_packed(self):
  1009. class Struct(ctypes.Structure):
  1010. _fields_ = [
  1011. ('one', ctypes.c_uint8),
  1012. ('two', ctypes.c_uint32)
  1013. ]
  1014. _pack_ = 1
  1015. class Union(ctypes.Union):
  1016. _pack_ = 1
  1017. _fields_ = [
  1018. ('a', ctypes.c_uint8),
  1019. ('b', ctypes.c_uint16),
  1020. ('c', ctypes.c_uint32),
  1021. ('d', Struct),
  1022. ]
  1023. expected = np.dtype(dict(
  1024. names=['a', 'b', 'c', 'd'],
  1025. formats=['u1', np.uint16, np.uint32, [('one', 'u1'), ('two', np.uint32)]],
  1026. offsets=[0, 0, 0, 0],
  1027. itemsize=ctypes.sizeof(Union)
  1028. ))
  1029. self.check(Union, expected)
  1030. def test_packed_structure(self):
  1031. class PackedStructure(ctypes.Structure):
  1032. _pack_ = 1
  1033. _fields_ = [
  1034. ('a', ctypes.c_uint8),
  1035. ('b', ctypes.c_uint16)
  1036. ]
  1037. expected = np.dtype([
  1038. ('a', np.uint8),
  1039. ('b', np.uint16)
  1040. ])
  1041. self.check(PackedStructure, expected)
  1042. def test_large_packed_structure(self):
  1043. class PackedStructure(ctypes.Structure):
  1044. _pack_ = 2
  1045. _fields_ = [
  1046. ('a', ctypes.c_uint8),
  1047. ('b', ctypes.c_uint16),
  1048. ('c', ctypes.c_uint8),
  1049. ('d', ctypes.c_uint16),
  1050. ('e', ctypes.c_uint32),
  1051. ('f', ctypes.c_uint32),
  1052. ('g', ctypes.c_uint8)
  1053. ]
  1054. expected = np.dtype(dict(
  1055. formats=[np.uint8, np.uint16, np.uint8, np.uint16, np.uint32, np.uint32, np.uint8 ],
  1056. offsets=[0, 2, 4, 6, 8, 12, 16],
  1057. names=['a', 'b', 'c', 'd', 'e', 'f', 'g'],
  1058. itemsize=18))
  1059. self.check(PackedStructure, expected)
  1060. def test_big_endian_structure_packed(self):
  1061. class BigEndStruct(ctypes.BigEndianStructure):
  1062. _fields_ = [
  1063. ('one', ctypes.c_uint8),
  1064. ('two', ctypes.c_uint32)
  1065. ]
  1066. _pack_ = 1
  1067. expected = np.dtype([('one', 'u1'), ('two', '>u4')])
  1068. self.check(BigEndStruct, expected)
  1069. def test_little_endian_structure_packed(self):
  1070. class LittleEndStruct(ctypes.LittleEndianStructure):
  1071. _fields_ = [
  1072. ('one', ctypes.c_uint8),
  1073. ('two', ctypes.c_uint32)
  1074. ]
  1075. _pack_ = 1
  1076. expected = np.dtype([('one', 'u1'), ('two', '<u4')])
  1077. self.check(LittleEndStruct, expected)
  1078. def test_little_endian_structure(self):
  1079. class PaddedStruct(ctypes.LittleEndianStructure):
  1080. _fields_ = [
  1081. ('a', ctypes.c_uint8),
  1082. ('b', ctypes.c_uint16)
  1083. ]
  1084. expected = np.dtype([
  1085. ('a', '<B'),
  1086. ('b', '<H')
  1087. ], align=True)
  1088. self.check(PaddedStruct, expected)
  1089. def test_big_endian_structure(self):
  1090. class PaddedStruct(ctypes.BigEndianStructure):
  1091. _fields_ = [
  1092. ('a', ctypes.c_uint8),
  1093. ('b', ctypes.c_uint16)
  1094. ]
  1095. expected = np.dtype([
  1096. ('a', '>B'),
  1097. ('b', '>H')
  1098. ], align=True)
  1099. self.check(PaddedStruct, expected)
  1100. def test_simple_endian_types(self):
  1101. self.check(ctypes.c_uint16.__ctype_le__, np.dtype('<u2'))
  1102. self.check(ctypes.c_uint16.__ctype_be__, np.dtype('>u2'))
  1103. self.check(ctypes.c_uint8.__ctype_le__, np.dtype('u1'))
  1104. self.check(ctypes.c_uint8.__ctype_be__, np.dtype('u1'))
  1105. all_types = set(np.typecodes['All'])
  1106. all_pairs = permutations(all_types, 2)
  1107. @pytest.mark.parametrize("pair", all_pairs)
  1108. def test_pairs(self, pair):
  1109. """
  1110. Check that np.dtype('x,y') matches [np.dtype('x'), np.dtype('y')]
  1111. Example: np.dtype('d,I') -> dtype([('f0', '<f8'), ('f1', '<u4')])
  1112. """
  1113. # gh-5645: check that np.dtype('i,L') can be used
  1114. pair_type = np.dtype('{},{}'.format(*pair))
  1115. expected = np.dtype([('f0', pair[0]), ('f1', pair[1])])
  1116. assert_equal(pair_type, expected)