test_format.py 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. # doctest
  2. r''' Test the .npy file format.
  3. Set up:
  4. >>> import sys
  5. >>> from io import BytesIO
  6. >>> from numpy.lib import format
  7. >>>
  8. >>> scalars = [
  9. ... np.uint8,
  10. ... np.int8,
  11. ... np.uint16,
  12. ... np.int16,
  13. ... np.uint32,
  14. ... np.int32,
  15. ... np.uint64,
  16. ... np.int64,
  17. ... np.float32,
  18. ... np.float64,
  19. ... np.complex64,
  20. ... np.complex128,
  21. ... object,
  22. ... ]
  23. >>>
  24. >>> basic_arrays = []
  25. >>>
  26. >>> for scalar in scalars:
  27. ... for endian in '<>':
  28. ... dtype = np.dtype(scalar).newbyteorder(endian)
  29. ... basic = np.arange(15).astype(dtype)
  30. ... basic_arrays.extend([
  31. ... np.array([], dtype=dtype),
  32. ... np.array(10, dtype=dtype),
  33. ... basic,
  34. ... basic.reshape((3,5)),
  35. ... basic.reshape((3,5)).T,
  36. ... basic.reshape((3,5))[::-1,::2],
  37. ... ])
  38. ...
  39. >>>
  40. >>> Pdescr = [
  41. ... ('x', 'i4', (2,)),
  42. ... ('y', 'f8', (2, 2)),
  43. ... ('z', 'u1')]
  44. >>>
  45. >>>
  46. >>> PbufferT = [
  47. ... ([3,2], [[6.,4.],[6.,4.]], 8),
  48. ... ([4,3], [[7.,5.],[7.,5.]], 9),
  49. ... ]
  50. >>>
  51. >>>
  52. >>> Ndescr = [
  53. ... ('x', 'i4', (2,)),
  54. ... ('Info', [
  55. ... ('value', 'c16'),
  56. ... ('y2', 'f8'),
  57. ... ('Info2', [
  58. ... ('name', 'S2'),
  59. ... ('value', 'c16', (2,)),
  60. ... ('y3', 'f8', (2,)),
  61. ... ('z3', 'u4', (2,))]),
  62. ... ('name', 'S2'),
  63. ... ('z2', 'b1')]),
  64. ... ('color', 'S2'),
  65. ... ('info', [
  66. ... ('Name', 'U8'),
  67. ... ('Value', 'c16')]),
  68. ... ('y', 'f8', (2, 2)),
  69. ... ('z', 'u1')]
  70. >>>
  71. >>>
  72. >>> NbufferT = [
  73. ... ([3,2], (6j, 6., ('nn', [6j,4j], [6.,4.], [1,2]), 'NN', True), 'cc', ('NN', 6j), [[6.,4.],[6.,4.]], 8),
  74. ... ([4,3], (7j, 7., ('oo', [7j,5j], [7.,5.], [2,1]), 'OO', False), 'dd', ('OO', 7j), [[7.,5.],[7.,5.]], 9),
  75. ... ]
  76. >>>
  77. >>>
  78. >>> record_arrays = [
  79. ... np.array(PbufferT, dtype=np.dtype(Pdescr).newbyteorder('<')),
  80. ... np.array(NbufferT, dtype=np.dtype(Ndescr).newbyteorder('<')),
  81. ... np.array(PbufferT, dtype=np.dtype(Pdescr).newbyteorder('>')),
  82. ... np.array(NbufferT, dtype=np.dtype(Ndescr).newbyteorder('>')),
  83. ... ]
  84. Test the magic string writing.
  85. >>> format.magic(1, 0)
  86. '\x93NUMPY\x01\x00'
  87. >>> format.magic(0, 0)
  88. '\x93NUMPY\x00\x00'
  89. >>> format.magic(255, 255)
  90. '\x93NUMPY\xff\xff'
  91. >>> format.magic(2, 5)
  92. '\x93NUMPY\x02\x05'
  93. Test the magic string reading.
  94. >>> format.read_magic(BytesIO(format.magic(1, 0)))
  95. (1, 0)
  96. >>> format.read_magic(BytesIO(format.magic(0, 0)))
  97. (0, 0)
  98. >>> format.read_magic(BytesIO(format.magic(255, 255)))
  99. (255, 255)
  100. >>> format.read_magic(BytesIO(format.magic(2, 5)))
  101. (2, 5)
  102. Test the header writing.
  103. >>> for arr in basic_arrays + record_arrays:
  104. ... f = BytesIO()
  105. ... format.write_array_header_1_0(f, arr) # XXX: arr is not a dict, items gets called on it
  106. ... print(repr(f.getvalue()))
  107. ...
  108. "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': (0,)} \n"
  109. "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': ()} \n"
  110. "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': (15,)} \n"
  111. "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': (3, 5)} \n"
  112. "F\x00{'descr': '|u1', 'fortran_order': True, 'shape': (5, 3)} \n"
  113. "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': (3, 3)} \n"
  114. "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': (0,)} \n"
  115. "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': ()} \n"
  116. "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': (15,)} \n"
  117. "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': (3, 5)} \n"
  118. "F\x00{'descr': '|u1', 'fortran_order': True, 'shape': (5, 3)} \n"
  119. "F\x00{'descr': '|u1', 'fortran_order': False, 'shape': (3, 3)} \n"
  120. "F\x00{'descr': '|i1', 'fortran_order': False, 'shape': (0,)} \n"
  121. "F\x00{'descr': '|i1', 'fortran_order': False, 'shape': ()} \n"
  122. "F\x00{'descr': '|i1', 'fortran_order': False, 'shape': (15,)} \n"
  123. "F\x00{'descr': '|i1', 'fortran_order': False, 'shape': (3, 5)} \n"
  124. "F\x00{'descr': '|i1', 'fortran_order': True, 'shape': (5, 3)} \n"
  125. "F\x00{'descr': '|i1', 'fortran_order': False, 'shape': (3, 3)} \n"
  126. "F\x00{'descr': '|i1', 'fortran_order': False, 'shape': (0,)} \n"
  127. "F\x00{'descr': '|i1', 'fortran_order': False, 'shape': ()} \n"
  128. "F\x00{'descr': '|i1', 'fortran_order': False, 'shape': (15,)} \n"
  129. "F\x00{'descr': '|i1', 'fortran_order': False, 'shape': (3, 5)} \n"
  130. "F\x00{'descr': '|i1', 'fortran_order': True, 'shape': (5, 3)} \n"
  131. "F\x00{'descr': '|i1', 'fortran_order': False, 'shape': (3, 3)} \n"
  132. "F\x00{'descr': '<u2', 'fortran_order': False, 'shape': (0,)} \n"
  133. "F\x00{'descr': '<u2', 'fortran_order': False, 'shape': ()} \n"
  134. "F\x00{'descr': '<u2', 'fortran_order': False, 'shape': (15,)} \n"
  135. "F\x00{'descr': '<u2', 'fortran_order': False, 'shape': (3, 5)} \n"
  136. "F\x00{'descr': '<u2', 'fortran_order': True, 'shape': (5, 3)} \n"
  137. "F\x00{'descr': '<u2', 'fortran_order': False, 'shape': (3, 3)} \n"
  138. "F\x00{'descr': '>u2', 'fortran_order': False, 'shape': (0,)} \n"
  139. "F\x00{'descr': '>u2', 'fortran_order': False, 'shape': ()} \n"
  140. "F\x00{'descr': '>u2', 'fortran_order': False, 'shape': (15,)} \n"
  141. "F\x00{'descr': '>u2', 'fortran_order': False, 'shape': (3, 5)} \n"
  142. "F\x00{'descr': '>u2', 'fortran_order': True, 'shape': (5, 3)} \n"
  143. "F\x00{'descr': '>u2', 'fortran_order': False, 'shape': (3, 3)} \n"
  144. "F\x00{'descr': '<i2', 'fortran_order': False, 'shape': (0,)} \n"
  145. "F\x00{'descr': '<i2', 'fortran_order': False, 'shape': ()} \n"
  146. "F\x00{'descr': '<i2', 'fortran_order': False, 'shape': (15,)} \n"
  147. "F\x00{'descr': '<i2', 'fortran_order': False, 'shape': (3, 5)} \n"
  148. "F\x00{'descr': '<i2', 'fortran_order': True, 'shape': (5, 3)} \n"
  149. "F\x00{'descr': '<i2', 'fortran_order': False, 'shape': (3, 3)} \n"
  150. "F\x00{'descr': '>i2', 'fortran_order': False, 'shape': (0,)} \n"
  151. "F\x00{'descr': '>i2', 'fortran_order': False, 'shape': ()} \n"
  152. "F\x00{'descr': '>i2', 'fortran_order': False, 'shape': (15,)} \n"
  153. "F\x00{'descr': '>i2', 'fortran_order': False, 'shape': (3, 5)} \n"
  154. "F\x00{'descr': '>i2', 'fortran_order': True, 'shape': (5, 3)} \n"
  155. "F\x00{'descr': '>i2', 'fortran_order': False, 'shape': (3, 3)} \n"
  156. "F\x00{'descr': '<u4', 'fortran_order': False, 'shape': (0,)} \n"
  157. "F\x00{'descr': '<u4', 'fortran_order': False, 'shape': ()} \n"
  158. "F\x00{'descr': '<u4', 'fortran_order': False, 'shape': (15,)} \n"
  159. "F\x00{'descr': '<u4', 'fortran_order': False, 'shape': (3, 5)} \n"
  160. "F\x00{'descr': '<u4', 'fortran_order': True, 'shape': (5, 3)} \n"
  161. "F\x00{'descr': '<u4', 'fortran_order': False, 'shape': (3, 3)} \n"
  162. "F\x00{'descr': '>u4', 'fortran_order': False, 'shape': (0,)} \n"
  163. "F\x00{'descr': '>u4', 'fortran_order': False, 'shape': ()} \n"
  164. "F\x00{'descr': '>u4', 'fortran_order': False, 'shape': (15,)} \n"
  165. "F\x00{'descr': '>u4', 'fortran_order': False, 'shape': (3, 5)} \n"
  166. "F\x00{'descr': '>u4', 'fortran_order': True, 'shape': (5, 3)} \n"
  167. "F\x00{'descr': '>u4', 'fortran_order': False, 'shape': (3, 3)} \n"
  168. "F\x00{'descr': '<i4', 'fortran_order': False, 'shape': (0,)} \n"
  169. "F\x00{'descr': '<i4', 'fortran_order': False, 'shape': ()} \n"
  170. "F\x00{'descr': '<i4', 'fortran_order': False, 'shape': (15,)} \n"
  171. "F\x00{'descr': '<i4', 'fortran_order': False, 'shape': (3, 5)} \n"
  172. "F\x00{'descr': '<i4', 'fortran_order': True, 'shape': (5, 3)} \n"
  173. "F\x00{'descr': '<i4', 'fortran_order': False, 'shape': (3, 3)} \n"
  174. "F\x00{'descr': '>i4', 'fortran_order': False, 'shape': (0,)} \n"
  175. "F\x00{'descr': '>i4', 'fortran_order': False, 'shape': ()} \n"
  176. "F\x00{'descr': '>i4', 'fortran_order': False, 'shape': (15,)} \n"
  177. "F\x00{'descr': '>i4', 'fortran_order': False, 'shape': (3, 5)} \n"
  178. "F\x00{'descr': '>i4', 'fortran_order': True, 'shape': (5, 3)} \n"
  179. "F\x00{'descr': '>i4', 'fortran_order': False, 'shape': (3, 3)} \n"
  180. "F\x00{'descr': '<u8', 'fortran_order': False, 'shape': (0,)} \n"
  181. "F\x00{'descr': '<u8', 'fortran_order': False, 'shape': ()} \n"
  182. "F\x00{'descr': '<u8', 'fortran_order': False, 'shape': (15,)} \n"
  183. "F\x00{'descr': '<u8', 'fortran_order': False, 'shape': (3, 5)} \n"
  184. "F\x00{'descr': '<u8', 'fortran_order': True, 'shape': (5, 3)} \n"
  185. "F\x00{'descr': '<u8', 'fortran_order': False, 'shape': (3, 3)} \n"
  186. "F\x00{'descr': '>u8', 'fortran_order': False, 'shape': (0,)} \n"
  187. "F\x00{'descr': '>u8', 'fortran_order': False, 'shape': ()} \n"
  188. "F\x00{'descr': '>u8', 'fortran_order': False, 'shape': (15,)} \n"
  189. "F\x00{'descr': '>u8', 'fortran_order': False, 'shape': (3, 5)} \n"
  190. "F\x00{'descr': '>u8', 'fortran_order': True, 'shape': (5, 3)} \n"
  191. "F\x00{'descr': '>u8', 'fortran_order': False, 'shape': (3, 3)} \n"
  192. "F\x00{'descr': '<i8', 'fortran_order': False, 'shape': (0,)} \n"
  193. "F\x00{'descr': '<i8', 'fortran_order': False, 'shape': ()} \n"
  194. "F\x00{'descr': '<i8', 'fortran_order': False, 'shape': (15,)} \n"
  195. "F\x00{'descr': '<i8', 'fortran_order': False, 'shape': (3, 5)} \n"
  196. "F\x00{'descr': '<i8', 'fortran_order': True, 'shape': (5, 3)} \n"
  197. "F\x00{'descr': '<i8', 'fortran_order': False, 'shape': (3, 3)} \n"
  198. "F\x00{'descr': '>i8', 'fortran_order': False, 'shape': (0,)} \n"
  199. "F\x00{'descr': '>i8', 'fortran_order': False, 'shape': ()} \n"
  200. "F\x00{'descr': '>i8', 'fortran_order': False, 'shape': (15,)} \n"
  201. "F\x00{'descr': '>i8', 'fortran_order': False, 'shape': (3, 5)} \n"
  202. "F\x00{'descr': '>i8', 'fortran_order': True, 'shape': (5, 3)} \n"
  203. "F\x00{'descr': '>i8', 'fortran_order': False, 'shape': (3, 3)} \n"
  204. "F\x00{'descr': '<f4', 'fortran_order': False, 'shape': (0,)} \n"
  205. "F\x00{'descr': '<f4', 'fortran_order': False, 'shape': ()} \n"
  206. "F\x00{'descr': '<f4', 'fortran_order': False, 'shape': (15,)} \n"
  207. "F\x00{'descr': '<f4', 'fortran_order': False, 'shape': (3, 5)} \n"
  208. "F\x00{'descr': '<f4', 'fortran_order': True, 'shape': (5, 3)} \n"
  209. "F\x00{'descr': '<f4', 'fortran_order': False, 'shape': (3, 3)} \n"
  210. "F\x00{'descr': '>f4', 'fortran_order': False, 'shape': (0,)} \n"
  211. "F\x00{'descr': '>f4', 'fortran_order': False, 'shape': ()} \n"
  212. "F\x00{'descr': '>f4', 'fortran_order': False, 'shape': (15,)} \n"
  213. "F\x00{'descr': '>f4', 'fortran_order': False, 'shape': (3, 5)} \n"
  214. "F\x00{'descr': '>f4', 'fortran_order': True, 'shape': (5, 3)} \n"
  215. "F\x00{'descr': '>f4', 'fortran_order': False, 'shape': (3, 3)} \n"
  216. "F\x00{'descr': '<f8', 'fortran_order': False, 'shape': (0,)} \n"
  217. "F\x00{'descr': '<f8', 'fortran_order': False, 'shape': ()} \n"
  218. "F\x00{'descr': '<f8', 'fortran_order': False, 'shape': (15,)} \n"
  219. "F\x00{'descr': '<f8', 'fortran_order': False, 'shape': (3, 5)} \n"
  220. "F\x00{'descr': '<f8', 'fortran_order': True, 'shape': (5, 3)} \n"
  221. "F\x00{'descr': '<f8', 'fortran_order': False, 'shape': (3, 3)} \n"
  222. "F\x00{'descr': '>f8', 'fortran_order': False, 'shape': (0,)} \n"
  223. "F\x00{'descr': '>f8', 'fortran_order': False, 'shape': ()} \n"
  224. "F\x00{'descr': '>f8', 'fortran_order': False, 'shape': (15,)} \n"
  225. "F\x00{'descr': '>f8', 'fortran_order': False, 'shape': (3, 5)} \n"
  226. "F\x00{'descr': '>f8', 'fortran_order': True, 'shape': (5, 3)} \n"
  227. "F\x00{'descr': '>f8', 'fortran_order': False, 'shape': (3, 3)} \n"
  228. "F\x00{'descr': '<c8', 'fortran_order': False, 'shape': (0,)} \n"
  229. "F\x00{'descr': '<c8', 'fortran_order': False, 'shape': ()} \n"
  230. "F\x00{'descr': '<c8', 'fortran_order': False, 'shape': (15,)} \n"
  231. "F\x00{'descr': '<c8', 'fortran_order': False, 'shape': (3, 5)} \n"
  232. "F\x00{'descr': '<c8', 'fortran_order': True, 'shape': (5, 3)} \n"
  233. "F\x00{'descr': '<c8', 'fortran_order': False, 'shape': (3, 3)} \n"
  234. "F\x00{'descr': '>c8', 'fortran_order': False, 'shape': (0,)} \n"
  235. "F\x00{'descr': '>c8', 'fortran_order': False, 'shape': ()} \n"
  236. "F\x00{'descr': '>c8', 'fortran_order': False, 'shape': (15,)} \n"
  237. "F\x00{'descr': '>c8', 'fortran_order': False, 'shape': (3, 5)} \n"
  238. "F\x00{'descr': '>c8', 'fortran_order': True, 'shape': (5, 3)} \n"
  239. "F\x00{'descr': '>c8', 'fortran_order': False, 'shape': (3, 3)} \n"
  240. "F\x00{'descr': '<c16', 'fortran_order': False, 'shape': (0,)} \n"
  241. "F\x00{'descr': '<c16', 'fortran_order': False, 'shape': ()} \n"
  242. "F\x00{'descr': '<c16', 'fortran_order': False, 'shape': (15,)} \n"
  243. "F\x00{'descr': '<c16', 'fortran_order': False, 'shape': (3, 5)} \n"
  244. "F\x00{'descr': '<c16', 'fortran_order': True, 'shape': (5, 3)} \n"
  245. "F\x00{'descr': '<c16', 'fortran_order': False, 'shape': (3, 3)} \n"
  246. "F\x00{'descr': '>c16', 'fortran_order': False, 'shape': (0,)} \n"
  247. "F\x00{'descr': '>c16', 'fortran_order': False, 'shape': ()} \n"
  248. "F\x00{'descr': '>c16', 'fortran_order': False, 'shape': (15,)} \n"
  249. "F\x00{'descr': '>c16', 'fortran_order': False, 'shape': (3, 5)} \n"
  250. "F\x00{'descr': '>c16', 'fortran_order': True, 'shape': (5, 3)} \n"
  251. "F\x00{'descr': '>c16', 'fortran_order': False, 'shape': (3, 3)} \n"
  252. "F\x00{'descr': 'O', 'fortran_order': False, 'shape': (0,)} \n"
  253. "F\x00{'descr': 'O', 'fortran_order': False, 'shape': ()} \n"
  254. "F\x00{'descr': 'O', 'fortran_order': False, 'shape': (15,)} \n"
  255. "F\x00{'descr': 'O', 'fortran_order': False, 'shape': (3, 5)} \n"
  256. "F\x00{'descr': 'O', 'fortran_order': True, 'shape': (5, 3)} \n"
  257. "F\x00{'descr': 'O', 'fortran_order': False, 'shape': (3, 3)} \n"
  258. "F\x00{'descr': 'O', 'fortran_order': False, 'shape': (0,)} \n"
  259. "F\x00{'descr': 'O', 'fortran_order': False, 'shape': ()} \n"
  260. "F\x00{'descr': 'O', 'fortran_order': False, 'shape': (15,)} \n"
  261. "F\x00{'descr': 'O', 'fortran_order': False, 'shape': (3, 5)} \n"
  262. "F\x00{'descr': 'O', 'fortran_order': True, 'shape': (5, 3)} \n"
  263. "F\x00{'descr': 'O', 'fortran_order': False, 'shape': (3, 3)} \n"
  264. "v\x00{'descr': [('x', '<i4', (2,)), ('y', '<f8', (2, 2)), ('z', '|u1')],\n 'fortran_order': False,\n 'shape': (2,)} \n"
  265. "\x16\x02{'descr': [('x', '<i4', (2,)),\n ('Info',\n [('value', '<c16'),\n ('y2', '<f8'),\n ('Info2',\n [('name', '|S2'),\n ('value', '<c16', (2,)),\n ('y3', '<f8', (2,)),\n ('z3', '<u4', (2,))]),\n ('name', '|S2'),\n ('z2', '|b1')]),\n ('color', '|S2'),\n ('info', [('Name', '<U8'), ('Value', '<c16')]),\n ('y', '<f8', (2, 2)),\n ('z', '|u1')],\n 'fortran_order': False,\n 'shape': (2,)} \n"
  266. "v\x00{'descr': [('x', '>i4', (2,)), ('y', '>f8', (2, 2)), ('z', '|u1')],\n 'fortran_order': False,\n 'shape': (2,)} \n"
  267. "\x16\x02{'descr': [('x', '>i4', (2,)),\n ('Info',\n [('value', '>c16'),\n ('y2', '>f8'),\n ('Info2',\n [('name', '|S2'),\n ('value', '>c16', (2,)),\n ('y3', '>f8', (2,)),\n ('z3', '>u4', (2,))]),\n ('name', '|S2'),\n ('z2', '|b1')]),\n ('color', '|S2'),\n ('info', [('Name', '>U8'), ('Value', '>c16')]),\n ('y', '>f8', (2, 2)),\n ('z', '|u1')],\n 'fortran_order': False,\n 'shape': (2,)} \n"
  268. '''
  269. import sys
  270. import os
  271. import warnings
  272. import pytest
  273. from io import BytesIO
  274. import numpy as np
  275. from numpy.testing import (
  276. assert_, assert_array_equal, assert_raises, assert_raises_regex,
  277. assert_warns, IS_PYPY, IS_WASM
  278. )
  279. from numpy.testing._private.utils import requires_memory
  280. from numpy.lib import format
  281. # Generate some basic arrays to test with.
  282. scalars = [
  283. np.uint8,
  284. np.int8,
  285. np.uint16,
  286. np.int16,
  287. np.uint32,
  288. np.int32,
  289. np.uint64,
  290. np.int64,
  291. np.float32,
  292. np.float64,
  293. np.complex64,
  294. np.complex128,
  295. object,
  296. ]
  297. basic_arrays = []
  298. for scalar in scalars:
  299. for endian in '<>':
  300. dtype = np.dtype(scalar).newbyteorder(endian)
  301. basic = np.arange(1500).astype(dtype)
  302. basic_arrays.extend([
  303. # Empty
  304. np.array([], dtype=dtype),
  305. # Rank-0
  306. np.array(10, dtype=dtype),
  307. # 1-D
  308. basic,
  309. # 2-D C-contiguous
  310. basic.reshape((30, 50)),
  311. # 2-D F-contiguous
  312. basic.reshape((30, 50)).T,
  313. # 2-D non-contiguous
  314. basic.reshape((30, 50))[::-1, ::2],
  315. ])
  316. # More complicated record arrays.
  317. # This is the structure of the table used for plain objects:
  318. #
  319. # +-+-+-+
  320. # |x|y|z|
  321. # +-+-+-+
  322. # Structure of a plain array description:
  323. Pdescr = [
  324. ('x', 'i4', (2,)),
  325. ('y', 'f8', (2, 2)),
  326. ('z', 'u1')]
  327. # A plain list of tuples with values for testing:
  328. PbufferT = [
  329. # x y z
  330. ([3, 2], [[6., 4.], [6., 4.]], 8),
  331. ([4, 3], [[7., 5.], [7., 5.]], 9),
  332. ]
  333. # This is the structure of the table used for nested objects (DON'T PANIC!):
  334. #
  335. # +-+---------------------------------+-----+----------+-+-+
  336. # |x|Info |color|info |y|z|
  337. # | +-----+--+----------------+----+--+ +----+-----+ | |
  338. # | |value|y2|Info2 |name|z2| |Name|Value| | |
  339. # | | | +----+-----+--+--+ | | | | | | |
  340. # | | | |name|value|y3|z3| | | | | | | |
  341. # +-+-----+--+----+-----+--+--+----+--+-----+----+-----+-+-+
  342. #
  343. # The corresponding nested array description:
  344. Ndescr = [
  345. ('x', 'i4', (2,)),
  346. ('Info', [
  347. ('value', 'c16'),
  348. ('y2', 'f8'),
  349. ('Info2', [
  350. ('name', 'S2'),
  351. ('value', 'c16', (2,)),
  352. ('y3', 'f8', (2,)),
  353. ('z3', 'u4', (2,))]),
  354. ('name', 'S2'),
  355. ('z2', 'b1')]),
  356. ('color', 'S2'),
  357. ('info', [
  358. ('Name', 'U8'),
  359. ('Value', 'c16')]),
  360. ('y', 'f8', (2, 2)),
  361. ('z', 'u1')]
  362. NbufferT = [
  363. # x Info color info y z
  364. # value y2 Info2 name z2 Name Value
  365. # name value y3 z3
  366. ([3, 2], (6j, 6., ('nn', [6j, 4j], [6., 4.], [1, 2]), 'NN', True),
  367. 'cc', ('NN', 6j), [[6., 4.], [6., 4.]], 8),
  368. ([4, 3], (7j, 7., ('oo', [7j, 5j], [7., 5.], [2, 1]), 'OO', False),
  369. 'dd', ('OO', 7j), [[7., 5.], [7., 5.]], 9),
  370. ]
  371. record_arrays = [
  372. np.array(PbufferT, dtype=np.dtype(Pdescr).newbyteorder('<')),
  373. np.array(NbufferT, dtype=np.dtype(Ndescr).newbyteorder('<')),
  374. np.array(PbufferT, dtype=np.dtype(Pdescr).newbyteorder('>')),
  375. np.array(NbufferT, dtype=np.dtype(Ndescr).newbyteorder('>')),
  376. np.zeros(1, dtype=[('c', ('<f8', (5,)), (2,))])
  377. ]
  378. #BytesIO that reads a random number of bytes at a time
  379. class BytesIOSRandomSize(BytesIO):
  380. def read(self, size=None):
  381. import random
  382. size = random.randint(1, size)
  383. return super().read(size)
  384. def roundtrip(arr):
  385. f = BytesIO()
  386. format.write_array(f, arr)
  387. f2 = BytesIO(f.getvalue())
  388. arr2 = format.read_array(f2, allow_pickle=True)
  389. return arr2
  390. def roundtrip_randsize(arr):
  391. f = BytesIO()
  392. format.write_array(f, arr)
  393. f2 = BytesIOSRandomSize(f.getvalue())
  394. arr2 = format.read_array(f2)
  395. return arr2
  396. def roundtrip_truncated(arr):
  397. f = BytesIO()
  398. format.write_array(f, arr)
  399. #BytesIO is one byte short
  400. f2 = BytesIO(f.getvalue()[0:-1])
  401. arr2 = format.read_array(f2)
  402. return arr2
  403. def assert_equal_(o1, o2):
  404. assert_(o1 == o2)
  405. def test_roundtrip():
  406. for arr in basic_arrays + record_arrays:
  407. arr2 = roundtrip(arr)
  408. assert_array_equal(arr, arr2)
  409. def test_roundtrip_randsize():
  410. for arr in basic_arrays + record_arrays:
  411. if arr.dtype != object:
  412. arr2 = roundtrip_randsize(arr)
  413. assert_array_equal(arr, arr2)
  414. def test_roundtrip_truncated():
  415. for arr in basic_arrays:
  416. if arr.dtype != object:
  417. assert_raises(ValueError, roundtrip_truncated, arr)
  418. def test_long_str():
  419. # check items larger than internal buffer size, gh-4027
  420. long_str_arr = np.ones(1, dtype=np.dtype((str, format.BUFFER_SIZE + 1)))
  421. long_str_arr2 = roundtrip(long_str_arr)
  422. assert_array_equal(long_str_arr, long_str_arr2)
  423. @pytest.mark.skipif(IS_WASM, reason="memmap doesn't work correctly")
  424. @pytest.mark.slow
  425. def test_memmap_roundtrip(tmpdir):
  426. for i, arr in enumerate(basic_arrays + record_arrays):
  427. if arr.dtype.hasobject:
  428. # Skip these since they can't be mmap'ed.
  429. continue
  430. # Write it out normally and through mmap.
  431. nfn = os.path.join(tmpdir, f'normal{i}.npy')
  432. mfn = os.path.join(tmpdir, f'memmap{i}.npy')
  433. with open(nfn, 'wb') as fp:
  434. format.write_array(fp, arr)
  435. fortran_order = (
  436. arr.flags.f_contiguous and not arr.flags.c_contiguous)
  437. ma = format.open_memmap(mfn, mode='w+', dtype=arr.dtype,
  438. shape=arr.shape, fortran_order=fortran_order)
  439. ma[...] = arr
  440. ma.flush()
  441. # Check that both of these files' contents are the same.
  442. with open(nfn, 'rb') as fp:
  443. normal_bytes = fp.read()
  444. with open(mfn, 'rb') as fp:
  445. memmap_bytes = fp.read()
  446. assert_equal_(normal_bytes, memmap_bytes)
  447. # Check that reading the file using memmap works.
  448. ma = format.open_memmap(nfn, mode='r')
  449. ma.flush()
  450. def test_compressed_roundtrip(tmpdir):
  451. arr = np.random.rand(200, 200)
  452. npz_file = os.path.join(tmpdir, 'compressed.npz')
  453. np.savez_compressed(npz_file, arr=arr)
  454. with np.load(npz_file) as npz:
  455. arr1 = npz['arr']
  456. assert_array_equal(arr, arr1)
  457. # aligned
  458. dt1 = np.dtype('i1, i4, i1', align=True)
  459. # non-aligned, explicit offsets
  460. dt2 = np.dtype({'names': ['a', 'b'], 'formats': ['i4', 'i4'],
  461. 'offsets': [1, 6]})
  462. # nested struct-in-struct
  463. dt3 = np.dtype({'names': ['c', 'd'], 'formats': ['i4', dt2]})
  464. # field with '' name
  465. dt4 = np.dtype({'names': ['a', '', 'b'], 'formats': ['i4']*3})
  466. # titles
  467. dt5 = np.dtype({'names': ['a', 'b'], 'formats': ['i4', 'i4'],
  468. 'offsets': [1, 6], 'titles': ['aa', 'bb']})
  469. # empty
  470. dt6 = np.dtype({'names': [], 'formats': [], 'itemsize': 8})
  471. @pytest.mark.parametrize("dt", [dt1, dt2, dt3, dt4, dt5, dt6])
  472. def test_load_padded_dtype(tmpdir, dt):
  473. arr = np.zeros(3, dt)
  474. for i in range(3):
  475. arr[i] = i + 5
  476. npz_file = os.path.join(tmpdir, 'aligned.npz')
  477. np.savez(npz_file, arr=arr)
  478. with np.load(npz_file) as npz:
  479. arr1 = npz['arr']
  480. assert_array_equal(arr, arr1)
  481. @pytest.mark.xfail(IS_WASM, reason="Emscripten NODEFS has a buggy dup")
  482. def test_python2_python3_interoperability():
  483. fname = 'win64python2.npy'
  484. path = os.path.join(os.path.dirname(__file__), 'data', fname)
  485. data = np.load(path)
  486. assert_array_equal(data, np.ones(2))
  487. def test_pickle_python2_python3():
  488. # Test that loading object arrays saved on Python 2 works both on
  489. # Python 2 and Python 3 and vice versa
  490. data_dir = os.path.join(os.path.dirname(__file__), 'data')
  491. expected = np.array([None, range, '\u512a\u826f',
  492. b'\xe4\xb8\x8d\xe8\x89\xaf'],
  493. dtype=object)
  494. for fname in ['py2-objarr.npy', 'py2-objarr.npz',
  495. 'py3-objarr.npy', 'py3-objarr.npz']:
  496. path = os.path.join(data_dir, fname)
  497. for encoding in ['bytes', 'latin1']:
  498. data_f = np.load(path, allow_pickle=True, encoding=encoding)
  499. if fname.endswith('.npz'):
  500. data = data_f['x']
  501. data_f.close()
  502. else:
  503. data = data_f
  504. if encoding == 'latin1' and fname.startswith('py2'):
  505. assert_(isinstance(data[3], str))
  506. assert_array_equal(data[:-1], expected[:-1])
  507. # mojibake occurs
  508. assert_array_equal(data[-1].encode(encoding), expected[-1])
  509. else:
  510. assert_(isinstance(data[3], bytes))
  511. assert_array_equal(data, expected)
  512. if fname.startswith('py2'):
  513. if fname.endswith('.npz'):
  514. data = np.load(path, allow_pickle=True)
  515. assert_raises(UnicodeError, data.__getitem__, 'x')
  516. data.close()
  517. data = np.load(path, allow_pickle=True, fix_imports=False,
  518. encoding='latin1')
  519. assert_raises(ImportError, data.__getitem__, 'x')
  520. data.close()
  521. else:
  522. assert_raises(UnicodeError, np.load, path,
  523. allow_pickle=True)
  524. assert_raises(ImportError, np.load, path,
  525. allow_pickle=True, fix_imports=False,
  526. encoding='latin1')
  527. def test_pickle_disallow(tmpdir):
  528. data_dir = os.path.join(os.path.dirname(__file__), 'data')
  529. path = os.path.join(data_dir, 'py2-objarr.npy')
  530. assert_raises(ValueError, np.load, path,
  531. allow_pickle=False, encoding='latin1')
  532. path = os.path.join(data_dir, 'py2-objarr.npz')
  533. with np.load(path, allow_pickle=False, encoding='latin1') as f:
  534. assert_raises(ValueError, f.__getitem__, 'x')
  535. path = os.path.join(tmpdir, 'pickle-disabled.npy')
  536. assert_raises(ValueError, np.save, path, np.array([None], dtype=object),
  537. allow_pickle=False)
  538. @pytest.mark.parametrize('dt', [
  539. np.dtype(np.dtype([('a', np.int8),
  540. ('b', np.int16),
  541. ('c', np.int32),
  542. ], align=True),
  543. (3,)),
  544. np.dtype([('x', np.dtype({'names':['a','b'],
  545. 'formats':['i1','i1'],
  546. 'offsets':[0,4],
  547. 'itemsize':8,
  548. },
  549. (3,)),
  550. (4,),
  551. )]),
  552. np.dtype([('x',
  553. ('<f8', (5,)),
  554. (2,),
  555. )]),
  556. np.dtype([('x', np.dtype((
  557. np.dtype((
  558. np.dtype({'names':['a','b'],
  559. 'formats':['i1','i1'],
  560. 'offsets':[0,4],
  561. 'itemsize':8}),
  562. (3,)
  563. )),
  564. (4,)
  565. )))
  566. ]),
  567. np.dtype([
  568. ('a', np.dtype((
  569. np.dtype((
  570. np.dtype((
  571. np.dtype([
  572. ('a', int),
  573. ('b', np.dtype({'names':['a','b'],
  574. 'formats':['i1','i1'],
  575. 'offsets':[0,4],
  576. 'itemsize':8})),
  577. ]),
  578. (3,),
  579. )),
  580. (4,),
  581. )),
  582. (5,),
  583. )))
  584. ]),
  585. ])
  586. def test_descr_to_dtype(dt):
  587. dt1 = format.descr_to_dtype(dt.descr)
  588. assert_equal_(dt1, dt)
  589. arr1 = np.zeros(3, dt)
  590. arr2 = roundtrip(arr1)
  591. assert_array_equal(arr1, arr2)
  592. def test_version_2_0():
  593. f = BytesIO()
  594. # requires more than 2 byte for header
  595. dt = [(("%d" % i) * 100, float) for i in range(500)]
  596. d = np.ones(1000, dtype=dt)
  597. format.write_array(f, d, version=(2, 0))
  598. with warnings.catch_warnings(record=True) as w:
  599. warnings.filterwarnings('always', '', UserWarning)
  600. format.write_array(f, d)
  601. assert_(w[0].category is UserWarning)
  602. # check alignment of data portion
  603. f.seek(0)
  604. header = f.readline()
  605. assert_(len(header) % format.ARRAY_ALIGN == 0)
  606. f.seek(0)
  607. n = format.read_array(f, max_header_size=200000)
  608. assert_array_equal(d, n)
  609. # 1.0 requested but data cannot be saved this way
  610. assert_raises(ValueError, format.write_array, f, d, (1, 0))
  611. @pytest.mark.skipif(IS_WASM, reason="memmap doesn't work correctly")
  612. def test_version_2_0_memmap(tmpdir):
  613. # requires more than 2 byte for header
  614. dt = [(("%d" % i) * 100, float) for i in range(500)]
  615. d = np.ones(1000, dtype=dt)
  616. tf1 = os.path.join(tmpdir, f'version2_01.npy')
  617. tf2 = os.path.join(tmpdir, f'version2_02.npy')
  618. # 1.0 requested but data cannot be saved this way
  619. assert_raises(ValueError, format.open_memmap, tf1, mode='w+', dtype=d.dtype,
  620. shape=d.shape, version=(1, 0))
  621. ma = format.open_memmap(tf1, mode='w+', dtype=d.dtype,
  622. shape=d.shape, version=(2, 0))
  623. ma[...] = d
  624. ma.flush()
  625. ma = format.open_memmap(tf1, mode='r', max_header_size=200000)
  626. assert_array_equal(ma, d)
  627. with warnings.catch_warnings(record=True) as w:
  628. warnings.filterwarnings('always', '', UserWarning)
  629. ma = format.open_memmap(tf2, mode='w+', dtype=d.dtype,
  630. shape=d.shape, version=None)
  631. assert_(w[0].category is UserWarning)
  632. ma[...] = d
  633. ma.flush()
  634. ma = format.open_memmap(tf2, mode='r', max_header_size=200000)
  635. assert_array_equal(ma, d)
  636. @pytest.mark.parametrize("mmap_mode", ["r", None])
  637. def test_huge_header(tmpdir, mmap_mode):
  638. f = os.path.join(tmpdir, f'large_header.npy')
  639. arr = np.array(1, dtype="i,"*10000+"i")
  640. with pytest.warns(UserWarning, match=".*format 2.0"):
  641. np.save(f, arr)
  642. with pytest.raises(ValueError, match="Header.*large"):
  643. np.load(f, mmap_mode=mmap_mode)
  644. with pytest.raises(ValueError, match="Header.*large"):
  645. np.load(f, mmap_mode=mmap_mode, max_header_size=20000)
  646. res = np.load(f, mmap_mode=mmap_mode, allow_pickle=True)
  647. assert_array_equal(res, arr)
  648. res = np.load(f, mmap_mode=mmap_mode, max_header_size=180000)
  649. assert_array_equal(res, arr)
  650. def test_huge_header_npz(tmpdir):
  651. f = os.path.join(tmpdir, f'large_header.npz')
  652. arr = np.array(1, dtype="i,"*10000+"i")
  653. with pytest.warns(UserWarning, match=".*format 2.0"):
  654. np.savez(f, arr=arr)
  655. # Only getting the array from the file actually reads it
  656. with pytest.raises(ValueError, match="Header.*large"):
  657. np.load(f)["arr"]
  658. with pytest.raises(ValueError, match="Header.*large"):
  659. np.load(f, max_header_size=20000)["arr"]
  660. res = np.load(f, allow_pickle=True)["arr"]
  661. assert_array_equal(res, arr)
  662. res = np.load(f, max_header_size=180000)["arr"]
  663. assert_array_equal(res, arr)
  664. def test_write_version():
  665. f = BytesIO()
  666. arr = np.arange(1)
  667. # These should pass.
  668. format.write_array(f, arr, version=(1, 0))
  669. format.write_array(f, arr)
  670. format.write_array(f, arr, version=None)
  671. format.write_array(f, arr)
  672. format.write_array(f, arr, version=(2, 0))
  673. format.write_array(f, arr)
  674. # These should all fail.
  675. bad_versions = [
  676. (1, 1),
  677. (0, 0),
  678. (0, 1),
  679. (2, 2),
  680. (255, 255),
  681. ]
  682. for version in bad_versions:
  683. with assert_raises_regex(ValueError,
  684. 'we only support format version.*'):
  685. format.write_array(f, arr, version=version)
  686. bad_version_magic = [
  687. b'\x93NUMPY\x01\x01',
  688. b'\x93NUMPY\x00\x00',
  689. b'\x93NUMPY\x00\x01',
  690. b'\x93NUMPY\x02\x00',
  691. b'\x93NUMPY\x02\x02',
  692. b'\x93NUMPY\xff\xff',
  693. ]
  694. malformed_magic = [
  695. b'\x92NUMPY\x01\x00',
  696. b'\x00NUMPY\x01\x00',
  697. b'\x93numpy\x01\x00',
  698. b'\x93MATLB\x01\x00',
  699. b'\x93NUMPY\x01',
  700. b'\x93NUMPY',
  701. b'',
  702. ]
  703. def test_read_magic():
  704. s1 = BytesIO()
  705. s2 = BytesIO()
  706. arr = np.ones((3, 6), dtype=float)
  707. format.write_array(s1, arr, version=(1, 0))
  708. format.write_array(s2, arr, version=(2, 0))
  709. s1.seek(0)
  710. s2.seek(0)
  711. version1 = format.read_magic(s1)
  712. version2 = format.read_magic(s2)
  713. assert_(version1 == (1, 0))
  714. assert_(version2 == (2, 0))
  715. assert_(s1.tell() == format.MAGIC_LEN)
  716. assert_(s2.tell() == format.MAGIC_LEN)
  717. def test_read_magic_bad_magic():
  718. for magic in malformed_magic:
  719. f = BytesIO(magic)
  720. assert_raises(ValueError, format.read_array, f)
  721. def test_read_version_1_0_bad_magic():
  722. for magic in bad_version_magic + malformed_magic:
  723. f = BytesIO(magic)
  724. assert_raises(ValueError, format.read_array, f)
  725. def test_bad_magic_args():
  726. assert_raises(ValueError, format.magic, -1, 1)
  727. assert_raises(ValueError, format.magic, 256, 1)
  728. assert_raises(ValueError, format.magic, 1, -1)
  729. assert_raises(ValueError, format.magic, 1, 256)
  730. def test_large_header():
  731. s = BytesIO()
  732. d = {'shape': tuple(), 'fortran_order': False, 'descr': '<i8'}
  733. format.write_array_header_1_0(s, d)
  734. s = BytesIO()
  735. d['descr'] = [('x'*256*256, '<i8')]
  736. assert_raises(ValueError, format.write_array_header_1_0, s, d)
  737. def test_read_array_header_1_0():
  738. s = BytesIO()
  739. arr = np.ones((3, 6), dtype=float)
  740. format.write_array(s, arr, version=(1, 0))
  741. s.seek(format.MAGIC_LEN)
  742. shape, fortran, dtype = format.read_array_header_1_0(s)
  743. assert_(s.tell() % format.ARRAY_ALIGN == 0)
  744. assert_((shape, fortran, dtype) == ((3, 6), False, float))
  745. def test_read_array_header_2_0():
  746. s = BytesIO()
  747. arr = np.ones((3, 6), dtype=float)
  748. format.write_array(s, arr, version=(2, 0))
  749. s.seek(format.MAGIC_LEN)
  750. shape, fortran, dtype = format.read_array_header_2_0(s)
  751. assert_(s.tell() % format.ARRAY_ALIGN == 0)
  752. assert_((shape, fortran, dtype) == ((3, 6), False, float))
  753. def test_bad_header():
  754. # header of length less than 2 should fail
  755. s = BytesIO()
  756. assert_raises(ValueError, format.read_array_header_1_0, s)
  757. s = BytesIO(b'1')
  758. assert_raises(ValueError, format.read_array_header_1_0, s)
  759. # header shorter than indicated size should fail
  760. s = BytesIO(b'\x01\x00')
  761. assert_raises(ValueError, format.read_array_header_1_0, s)
  762. # headers without the exact keys required should fail
  763. # d = {"shape": (1, 2),
  764. # "descr": "x"}
  765. s = BytesIO(
  766. b"\x93NUMPY\x01\x006\x00{'descr': 'x', 'shape': (1, 2), }" +
  767. b" \n"
  768. )
  769. assert_raises(ValueError, format.read_array_header_1_0, s)
  770. d = {"shape": (1, 2),
  771. "fortran_order": False,
  772. "descr": "x",
  773. "extrakey": -1}
  774. s = BytesIO()
  775. format.write_array_header_1_0(s, d)
  776. assert_raises(ValueError, format.read_array_header_1_0, s)
  777. def test_large_file_support(tmpdir):
  778. if (sys.platform == 'win32' or sys.platform == 'cygwin'):
  779. pytest.skip("Unknown if Windows has sparse filesystems")
  780. # try creating a large sparse file
  781. tf_name = os.path.join(tmpdir, 'sparse_file')
  782. try:
  783. # seek past end would work too, but linux truncate somewhat
  784. # increases the chances that we have a sparse filesystem and can
  785. # avoid actually writing 5GB
  786. import subprocess as sp
  787. sp.check_call(["truncate", "-s", "5368709120", tf_name])
  788. except Exception:
  789. pytest.skip("Could not create 5GB large file")
  790. # write a small array to the end
  791. with open(tf_name, "wb") as f:
  792. f.seek(5368709120)
  793. d = np.arange(5)
  794. np.save(f, d)
  795. # read it back
  796. with open(tf_name, "rb") as f:
  797. f.seek(5368709120)
  798. r = np.load(f)
  799. assert_array_equal(r, d)
  800. @pytest.mark.skipif(IS_PYPY, reason="flaky on PyPy")
  801. @pytest.mark.skipif(np.dtype(np.intp).itemsize < 8,
  802. reason="test requires 64-bit system")
  803. @pytest.mark.slow
  804. @requires_memory(free_bytes=2 * 2**30)
  805. def test_large_archive(tmpdir):
  806. # Regression test for product of saving arrays with dimensions of array
  807. # having a product that doesn't fit in int32. See gh-7598 for details.
  808. shape = (2**30, 2)
  809. try:
  810. a = np.empty(shape, dtype=np.uint8)
  811. except MemoryError:
  812. pytest.skip("Could not create large file")
  813. fname = os.path.join(tmpdir, "large_archive")
  814. with open(fname, "wb") as f:
  815. np.savez(f, arr=a)
  816. del a
  817. with open(fname, "rb") as f:
  818. new_a = np.load(f)["arr"]
  819. assert new_a.shape == shape
  820. def test_empty_npz(tmpdir):
  821. # Test for gh-9989
  822. fname = os.path.join(tmpdir, "nothing.npz")
  823. np.savez(fname)
  824. with np.load(fname) as nps:
  825. pass
  826. def test_unicode_field_names(tmpdir):
  827. # gh-7391
  828. arr = np.array([
  829. (1, 3),
  830. (1, 2),
  831. (1, 3),
  832. (1, 2)
  833. ], dtype=[
  834. ('int', int),
  835. ('\N{CJK UNIFIED IDEOGRAPH-6574}\N{CJK UNIFIED IDEOGRAPH-5F62}', int)
  836. ])
  837. fname = os.path.join(tmpdir, "unicode.npy")
  838. with open(fname, 'wb') as f:
  839. format.write_array(f, arr, version=(3, 0))
  840. with open(fname, 'rb') as f:
  841. arr2 = format.read_array(f)
  842. assert_array_equal(arr, arr2)
  843. # notifies the user that 3.0 is selected
  844. with open(fname, 'wb') as f:
  845. with assert_warns(UserWarning):
  846. format.write_array(f, arr, version=None)
  847. def test_header_growth_axis():
  848. for is_fortran_array, dtype_space, expected_header_length in [
  849. [False, 22, 128], [False, 23, 192], [True, 23, 128], [True, 24, 192]
  850. ]:
  851. for size in [10**i for i in range(format.GROWTH_AXIS_MAX_DIGITS)]:
  852. fp = BytesIO()
  853. format.write_array_header_1_0(fp, {
  854. 'shape': (2, size) if is_fortran_array else (size, 2),
  855. 'fortran_order': is_fortran_array,
  856. 'descr': np.dtype([(' '*dtype_space, int)])
  857. })
  858. assert len(fp.getvalue()) == expected_header_length
  859. @pytest.mark.parametrize('dt, fail', [
  860. (np.dtype({'names': ['a', 'b'], 'formats': [float, np.dtype('S3',
  861. metadata={'some': 'stuff'})]}), True),
  862. (np.dtype(int, metadata={'some': 'stuff'}), False),
  863. (np.dtype([('subarray', (int, (2,)))], metadata={'some': 'stuff'}), False),
  864. # recursive: metadata on the field of a dtype
  865. (np.dtype({'names': ['a', 'b'], 'formats': [
  866. float, np.dtype({'names': ['c'], 'formats': [np.dtype(int, metadata={})]})
  867. ]}), False)
  868. ])
  869. @pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
  870. reason="PyPy bug in error formatting")
  871. def test_metadata_dtype(dt, fail):
  872. # gh-14142
  873. arr = np.ones(10, dtype=dt)
  874. buf = BytesIO()
  875. with assert_warns(UserWarning):
  876. np.save(buf, arr)
  877. buf.seek(0)
  878. if fail:
  879. with assert_raises(ValueError):
  880. np.load(buf)
  881. else:
  882. arr2 = np.load(buf)
  883. # BUG: assert_array_equal does not check metadata
  884. from numpy.lib.format import _has_metadata
  885. assert_array_equal(arr, arr2)
  886. assert _has_metadata(arr.dtype)
  887. assert not _has_metadata(arr2.dtype)