test_format.py 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  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, IS_64BIT
  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.skipif(sys.version_info >= (3, 12), reason="see gh-23988")
  482. @pytest.mark.xfail(IS_WASM, reason="Emscripten NODEFS has a buggy dup")
  483. def test_python2_python3_interoperability():
  484. fname = 'win64python2.npy'
  485. path = os.path.join(os.path.dirname(__file__), 'data', fname)
  486. with pytest.warns(UserWarning, match="Reading.*this warning\\."):
  487. data = np.load(path)
  488. assert_array_equal(data, np.ones(2))
  489. def test_pickle_python2_python3():
  490. # Test that loading object arrays saved on Python 2 works both on
  491. # Python 2 and Python 3 and vice versa
  492. data_dir = os.path.join(os.path.dirname(__file__), 'data')
  493. expected = np.array([None, range, '\u512a\u826f',
  494. b'\xe4\xb8\x8d\xe8\x89\xaf'],
  495. dtype=object)
  496. for fname in ['py2-np0-objarr.npy', 'py2-objarr.npy', 'py2-objarr.npz',
  497. 'py3-objarr.npy', 'py3-objarr.npz']:
  498. path = os.path.join(data_dir, fname)
  499. for encoding in ['bytes', 'latin1']:
  500. data_f = np.load(path, allow_pickle=True, encoding=encoding)
  501. if fname.endswith('.npz'):
  502. data = data_f['x']
  503. data_f.close()
  504. else:
  505. data = data_f
  506. if encoding == 'latin1' and fname.startswith('py2'):
  507. assert_(isinstance(data[3], str))
  508. assert_array_equal(data[:-1], expected[:-1])
  509. # mojibake occurs
  510. assert_array_equal(data[-1].encode(encoding), expected[-1])
  511. else:
  512. assert_(isinstance(data[3], bytes))
  513. assert_array_equal(data, expected)
  514. if fname.startswith('py2'):
  515. if fname.endswith('.npz'):
  516. data = np.load(path, allow_pickle=True)
  517. assert_raises(UnicodeError, data.__getitem__, 'x')
  518. data.close()
  519. data = np.load(path, allow_pickle=True, fix_imports=False,
  520. encoding='latin1')
  521. assert_raises(ImportError, data.__getitem__, 'x')
  522. data.close()
  523. else:
  524. assert_raises(UnicodeError, np.load, path,
  525. allow_pickle=True)
  526. assert_raises(ImportError, np.load, path,
  527. allow_pickle=True, fix_imports=False,
  528. encoding='latin1')
  529. def test_pickle_disallow(tmpdir):
  530. data_dir = os.path.join(os.path.dirname(__file__), 'data')
  531. path = os.path.join(data_dir, 'py2-objarr.npy')
  532. assert_raises(ValueError, np.load, path,
  533. allow_pickle=False, encoding='latin1')
  534. path = os.path.join(data_dir, 'py2-objarr.npz')
  535. with np.load(path, allow_pickle=False, encoding='latin1') as f:
  536. assert_raises(ValueError, f.__getitem__, 'x')
  537. path = os.path.join(tmpdir, 'pickle-disabled.npy')
  538. assert_raises(ValueError, np.save, path, np.array([None], dtype=object),
  539. allow_pickle=False)
  540. @pytest.mark.parametrize('dt', [
  541. np.dtype(np.dtype([('a', np.int8),
  542. ('b', np.int16),
  543. ('c', np.int32),
  544. ], align=True),
  545. (3,)),
  546. np.dtype([('x', np.dtype({'names':['a','b'],
  547. 'formats':['i1','i1'],
  548. 'offsets':[0,4],
  549. 'itemsize':8,
  550. },
  551. (3,)),
  552. (4,),
  553. )]),
  554. np.dtype([('x',
  555. ('<f8', (5,)),
  556. (2,),
  557. )]),
  558. np.dtype([('x', np.dtype((
  559. np.dtype((
  560. np.dtype({'names':['a','b'],
  561. 'formats':['i1','i1'],
  562. 'offsets':[0,4],
  563. 'itemsize':8}),
  564. (3,)
  565. )),
  566. (4,)
  567. )))
  568. ]),
  569. np.dtype([
  570. ('a', np.dtype((
  571. np.dtype((
  572. np.dtype((
  573. np.dtype([
  574. ('a', int),
  575. ('b', np.dtype({'names':['a','b'],
  576. 'formats':['i1','i1'],
  577. 'offsets':[0,4],
  578. 'itemsize':8})),
  579. ]),
  580. (3,),
  581. )),
  582. (4,),
  583. )),
  584. (5,),
  585. )))
  586. ]),
  587. ])
  588. def test_descr_to_dtype(dt):
  589. dt1 = format.descr_to_dtype(dt.descr)
  590. assert_equal_(dt1, dt)
  591. arr1 = np.zeros(3, dt)
  592. arr2 = roundtrip(arr1)
  593. assert_array_equal(arr1, arr2)
  594. def test_version_2_0():
  595. f = BytesIO()
  596. # requires more than 2 byte for header
  597. dt = [(("%d" % i) * 100, float) for i in range(500)]
  598. d = np.ones(1000, dtype=dt)
  599. format.write_array(f, d, version=(2, 0))
  600. with warnings.catch_warnings(record=True) as w:
  601. warnings.filterwarnings('always', '', UserWarning)
  602. format.write_array(f, d)
  603. assert_(w[0].category is UserWarning)
  604. # check alignment of data portion
  605. f.seek(0)
  606. header = f.readline()
  607. assert_(len(header) % format.ARRAY_ALIGN == 0)
  608. f.seek(0)
  609. n = format.read_array(f, max_header_size=200000)
  610. assert_array_equal(d, n)
  611. # 1.0 requested but data cannot be saved this way
  612. assert_raises(ValueError, format.write_array, f, d, (1, 0))
  613. @pytest.mark.skipif(IS_WASM, reason="memmap doesn't work correctly")
  614. def test_version_2_0_memmap(tmpdir):
  615. # requires more than 2 byte for header
  616. dt = [(("%d" % i) * 100, float) for i in range(500)]
  617. d = np.ones(1000, dtype=dt)
  618. tf1 = os.path.join(tmpdir, 'version2_01.npy')
  619. tf2 = os.path.join(tmpdir, 'version2_02.npy')
  620. # 1.0 requested but data cannot be saved this way
  621. assert_raises(ValueError, format.open_memmap, tf1, mode='w+', dtype=d.dtype,
  622. shape=d.shape, version=(1, 0))
  623. ma = format.open_memmap(tf1, mode='w+', dtype=d.dtype,
  624. shape=d.shape, version=(2, 0))
  625. ma[...] = d
  626. ma.flush()
  627. ma = format.open_memmap(tf1, mode='r', max_header_size=200000)
  628. assert_array_equal(ma, d)
  629. with warnings.catch_warnings(record=True) as w:
  630. warnings.filterwarnings('always', '', UserWarning)
  631. ma = format.open_memmap(tf2, mode='w+', dtype=d.dtype,
  632. shape=d.shape, version=None)
  633. assert_(w[0].category is UserWarning)
  634. ma[...] = d
  635. ma.flush()
  636. ma = format.open_memmap(tf2, mode='r', max_header_size=200000)
  637. assert_array_equal(ma, d)
  638. @pytest.mark.parametrize("mmap_mode", ["r", None])
  639. def test_huge_header(tmpdir, mmap_mode):
  640. f = os.path.join(tmpdir, 'large_header.npy')
  641. arr = np.array(1, dtype="i,"*10000+"i")
  642. with pytest.warns(UserWarning, match=".*format 2.0"):
  643. np.save(f, arr)
  644. with pytest.raises(ValueError, match="Header.*large"):
  645. np.load(f, mmap_mode=mmap_mode)
  646. with pytest.raises(ValueError, match="Header.*large"):
  647. np.load(f, mmap_mode=mmap_mode, max_header_size=20000)
  648. res = np.load(f, mmap_mode=mmap_mode, allow_pickle=True)
  649. assert_array_equal(res, arr)
  650. res = np.load(f, mmap_mode=mmap_mode, max_header_size=180000)
  651. assert_array_equal(res, arr)
  652. def test_huge_header_npz(tmpdir):
  653. f = os.path.join(tmpdir, 'large_header.npz')
  654. arr = np.array(1, dtype="i,"*10000+"i")
  655. with pytest.warns(UserWarning, match=".*format 2.0"):
  656. np.savez(f, arr=arr)
  657. # Only getting the array from the file actually reads it
  658. with pytest.raises(ValueError, match="Header.*large"):
  659. np.load(f)["arr"]
  660. with pytest.raises(ValueError, match="Header.*large"):
  661. np.load(f, max_header_size=20000)["arr"]
  662. res = np.load(f, allow_pickle=True)["arr"]
  663. assert_array_equal(res, arr)
  664. res = np.load(f, max_header_size=180000)["arr"]
  665. assert_array_equal(res, arr)
  666. def test_write_version():
  667. f = BytesIO()
  668. arr = np.arange(1)
  669. # These should pass.
  670. format.write_array(f, arr, version=(1, 0))
  671. format.write_array(f, arr)
  672. format.write_array(f, arr, version=None)
  673. format.write_array(f, arr)
  674. format.write_array(f, arr, version=(2, 0))
  675. format.write_array(f, arr)
  676. # These should all fail.
  677. bad_versions = [
  678. (1, 1),
  679. (0, 0),
  680. (0, 1),
  681. (2, 2),
  682. (255, 255),
  683. ]
  684. for version in bad_versions:
  685. with assert_raises_regex(ValueError,
  686. 'we only support format version.*'):
  687. format.write_array(f, arr, version=version)
  688. bad_version_magic = [
  689. b'\x93NUMPY\x01\x01',
  690. b'\x93NUMPY\x00\x00',
  691. b'\x93NUMPY\x00\x01',
  692. b'\x93NUMPY\x02\x00',
  693. b'\x93NUMPY\x02\x02',
  694. b'\x93NUMPY\xff\xff',
  695. ]
  696. malformed_magic = [
  697. b'\x92NUMPY\x01\x00',
  698. b'\x00NUMPY\x01\x00',
  699. b'\x93numpy\x01\x00',
  700. b'\x93MATLB\x01\x00',
  701. b'\x93NUMPY\x01',
  702. b'\x93NUMPY',
  703. b'',
  704. ]
  705. def test_read_magic():
  706. s1 = BytesIO()
  707. s2 = BytesIO()
  708. arr = np.ones((3, 6), dtype=float)
  709. format.write_array(s1, arr, version=(1, 0))
  710. format.write_array(s2, arr, version=(2, 0))
  711. s1.seek(0)
  712. s2.seek(0)
  713. version1 = format.read_magic(s1)
  714. version2 = format.read_magic(s2)
  715. assert_(version1 == (1, 0))
  716. assert_(version2 == (2, 0))
  717. assert_(s1.tell() == format.MAGIC_LEN)
  718. assert_(s2.tell() == format.MAGIC_LEN)
  719. def test_read_magic_bad_magic():
  720. for magic in malformed_magic:
  721. f = BytesIO(magic)
  722. assert_raises(ValueError, format.read_array, f)
  723. def test_read_version_1_0_bad_magic():
  724. for magic in bad_version_magic + malformed_magic:
  725. f = BytesIO(magic)
  726. assert_raises(ValueError, format.read_array, f)
  727. def test_bad_magic_args():
  728. assert_raises(ValueError, format.magic, -1, 1)
  729. assert_raises(ValueError, format.magic, 256, 1)
  730. assert_raises(ValueError, format.magic, 1, -1)
  731. assert_raises(ValueError, format.magic, 1, 256)
  732. def test_large_header():
  733. s = BytesIO()
  734. d = {'shape': tuple(), 'fortran_order': False, 'descr': '<i8'}
  735. format.write_array_header_1_0(s, d)
  736. s = BytesIO()
  737. d['descr'] = [('x'*256*256, '<i8')]
  738. assert_raises(ValueError, format.write_array_header_1_0, s, d)
  739. def test_read_array_header_1_0():
  740. s = BytesIO()
  741. arr = np.ones((3, 6), dtype=float)
  742. format.write_array(s, arr, version=(1, 0))
  743. s.seek(format.MAGIC_LEN)
  744. shape, fortran, dtype = format.read_array_header_1_0(s)
  745. assert_(s.tell() % format.ARRAY_ALIGN == 0)
  746. assert_((shape, fortran, dtype) == ((3, 6), False, float))
  747. def test_read_array_header_2_0():
  748. s = BytesIO()
  749. arr = np.ones((3, 6), dtype=float)
  750. format.write_array(s, arr, version=(2, 0))
  751. s.seek(format.MAGIC_LEN)
  752. shape, fortran, dtype = format.read_array_header_2_0(s)
  753. assert_(s.tell() % format.ARRAY_ALIGN == 0)
  754. assert_((shape, fortran, dtype) == ((3, 6), False, float))
  755. def test_bad_header():
  756. # header of length less than 2 should fail
  757. s = BytesIO()
  758. assert_raises(ValueError, format.read_array_header_1_0, s)
  759. s = BytesIO(b'1')
  760. assert_raises(ValueError, format.read_array_header_1_0, s)
  761. # header shorter than indicated size should fail
  762. s = BytesIO(b'\x01\x00')
  763. assert_raises(ValueError, format.read_array_header_1_0, s)
  764. # headers without the exact keys required should fail
  765. # d = {"shape": (1, 2),
  766. # "descr": "x"}
  767. s = BytesIO(
  768. b"\x93NUMPY\x01\x006\x00{'descr': 'x', 'shape': (1, 2), }" +
  769. b" \n"
  770. )
  771. assert_raises(ValueError, format.read_array_header_1_0, s)
  772. d = {"shape": (1, 2),
  773. "fortran_order": False,
  774. "descr": "x",
  775. "extrakey": -1}
  776. s = BytesIO()
  777. format.write_array_header_1_0(s, d)
  778. assert_raises(ValueError, format.read_array_header_1_0, s)
  779. def test_large_file_support(tmpdir):
  780. if (sys.platform == 'win32' or sys.platform == 'cygwin'):
  781. pytest.skip("Unknown if Windows has sparse filesystems")
  782. # try creating a large sparse file
  783. tf_name = os.path.join(tmpdir, 'sparse_file')
  784. try:
  785. # seek past end would work too, but linux truncate somewhat
  786. # increases the chances that we have a sparse filesystem and can
  787. # avoid actually writing 5GB
  788. import subprocess as sp
  789. sp.check_call(["truncate", "-s", "5368709120", tf_name])
  790. except Exception:
  791. pytest.skip("Could not create 5GB large file")
  792. # write a small array to the end
  793. with open(tf_name, "wb") as f:
  794. f.seek(5368709120)
  795. d = np.arange(5)
  796. np.save(f, d)
  797. # read it back
  798. with open(tf_name, "rb") as f:
  799. f.seek(5368709120)
  800. r = np.load(f)
  801. assert_array_equal(r, d)
  802. @pytest.mark.skipif(IS_PYPY, reason="flaky on PyPy")
  803. @pytest.mark.skipif(not IS_64BIT, reason="test requires 64-bit system")
  804. @pytest.mark.slow
  805. @requires_memory(free_bytes=2 * 2**30)
  806. def test_large_archive(tmpdir):
  807. # Regression test for product of saving arrays with dimensions of array
  808. # having a product that doesn't fit in int32. See gh-7598 for details.
  809. shape = (2**30, 2)
  810. try:
  811. a = np.empty(shape, dtype=np.uint8)
  812. except MemoryError:
  813. pytest.skip("Could not create large file")
  814. fname = os.path.join(tmpdir, "large_archive")
  815. with open(fname, "wb") as f:
  816. np.savez(f, arr=a)
  817. del a
  818. with open(fname, "rb") as f:
  819. new_a = np.load(f)["arr"]
  820. assert new_a.shape == shape
  821. def test_empty_npz(tmpdir):
  822. # Test for gh-9989
  823. fname = os.path.join(tmpdir, "nothing.npz")
  824. np.savez(fname)
  825. with np.load(fname) as nps:
  826. pass
  827. def test_unicode_field_names(tmpdir):
  828. # gh-7391
  829. arr = np.array([
  830. (1, 3),
  831. (1, 2),
  832. (1, 3),
  833. (1, 2)
  834. ], dtype=[
  835. ('int', int),
  836. ('\N{CJK UNIFIED IDEOGRAPH-6574}\N{CJK UNIFIED IDEOGRAPH-5F62}', int)
  837. ])
  838. fname = os.path.join(tmpdir, "unicode.npy")
  839. with open(fname, 'wb') as f:
  840. format.write_array(f, arr, version=(3, 0))
  841. with open(fname, 'rb') as f:
  842. arr2 = format.read_array(f)
  843. assert_array_equal(arr, arr2)
  844. # notifies the user that 3.0 is selected
  845. with open(fname, 'wb') as f:
  846. with assert_warns(UserWarning):
  847. format.write_array(f, arr, version=None)
  848. def test_header_growth_axis():
  849. for is_fortran_array, dtype_space, expected_header_length in [
  850. [False, 22, 128], [False, 23, 192], [True, 23, 128], [True, 24, 192]
  851. ]:
  852. for size in [10**i for i in range(format.GROWTH_AXIS_MAX_DIGITS)]:
  853. fp = BytesIO()
  854. format.write_array_header_1_0(fp, {
  855. 'shape': (2, size) if is_fortran_array else (size, 2),
  856. 'fortran_order': is_fortran_array,
  857. 'descr': np.dtype([(' '*dtype_space, int)])
  858. })
  859. assert len(fp.getvalue()) == expected_header_length
  860. @pytest.mark.parametrize('dt', [
  861. np.dtype({'names': ['a', 'b'], 'formats': [float, np.dtype('S3',
  862. metadata={'some': 'stuff'})]}),
  863. np.dtype(int, metadata={'some': 'stuff'}),
  864. np.dtype([('subarray', (int, (2,)))], metadata={'some': 'stuff'}),
  865. # recursive: metadata on the field of a dtype
  866. np.dtype({'names': ['a', 'b'], 'formats': [
  867. float, np.dtype({'names': ['c'], 'formats': [np.dtype(int, metadata={})]})
  868. ]}),
  869. ])
  870. @pytest.mark.skipif(IS_PYPY and sys.implementation.version <= (7, 3, 8),
  871. reason="PyPy bug in error formatting")
  872. def test_metadata_dtype(dt):
  873. # gh-14142
  874. arr = np.ones(10, dtype=dt)
  875. buf = BytesIO()
  876. with assert_warns(UserWarning):
  877. np.save(buf, arr)
  878. buf.seek(0)
  879. # Loading should work (metadata was stripped):
  880. arr2 = np.load(buf)
  881. # BUG: assert_array_equal does not check metadata
  882. from numpy.lib._utils_impl import drop_metadata
  883. assert_array_equal(arr, arr2)
  884. assert drop_metadata(arr.dtype) is not arr.dtype
  885. assert drop_metadata(arr2.dtype) is arr2.dtype