test_memoryio.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. """Unit tests for memory-based file-like objects.
  2. StringIO -- for unicode strings
  3. BytesIO -- for bytes
  4. """
  5. import unittest
  6. from test import support
  7. import io
  8. import _pyio as pyio
  9. import pickle
  10. import sys
  11. class IntLike:
  12. def __init__(self, num):
  13. self._num = num
  14. def __index__(self):
  15. return self._num
  16. __int__ = __index__
  17. class MemorySeekTestMixin:
  18. def testInit(self):
  19. buf = self.buftype("1234567890")
  20. bytesIo = self.ioclass(buf)
  21. def testRead(self):
  22. buf = self.buftype("1234567890")
  23. bytesIo = self.ioclass(buf)
  24. self.assertEqual(buf[:1], bytesIo.read(1))
  25. self.assertEqual(buf[1:5], bytesIo.read(4))
  26. self.assertEqual(buf[5:], bytesIo.read(900))
  27. self.assertEqual(self.EOF, bytesIo.read())
  28. def testReadNoArgs(self):
  29. buf = self.buftype("1234567890")
  30. bytesIo = self.ioclass(buf)
  31. self.assertEqual(buf, bytesIo.read())
  32. self.assertEqual(self.EOF, bytesIo.read())
  33. def testSeek(self):
  34. buf = self.buftype("1234567890")
  35. bytesIo = self.ioclass(buf)
  36. bytesIo.read(5)
  37. bytesIo.seek(0)
  38. self.assertEqual(buf, bytesIo.read())
  39. bytesIo.seek(3)
  40. self.assertEqual(buf[3:], bytesIo.read())
  41. self.assertRaises(TypeError, bytesIo.seek, 0.0)
  42. def testTell(self):
  43. buf = self.buftype("1234567890")
  44. bytesIo = self.ioclass(buf)
  45. self.assertEqual(0, bytesIo.tell())
  46. bytesIo.seek(5)
  47. self.assertEqual(5, bytesIo.tell())
  48. bytesIo.seek(10000)
  49. self.assertEqual(10000, bytesIo.tell())
  50. class MemoryTestMixin:
  51. def test_detach(self):
  52. buf = self.ioclass()
  53. self.assertRaises(self.UnsupportedOperation, buf.detach)
  54. def write_ops(self, f, t):
  55. self.assertEqual(f.write(t("blah.")), 5)
  56. self.assertEqual(f.seek(0), 0)
  57. self.assertEqual(f.write(t("Hello.")), 6)
  58. self.assertEqual(f.tell(), 6)
  59. self.assertEqual(f.seek(5), 5)
  60. self.assertEqual(f.tell(), 5)
  61. self.assertEqual(f.write(t(" world\n\n\n")), 9)
  62. self.assertEqual(f.seek(0), 0)
  63. self.assertEqual(f.write(t("h")), 1)
  64. self.assertEqual(f.truncate(12), 12)
  65. self.assertEqual(f.tell(), 1)
  66. def test_write(self):
  67. buf = self.buftype("hello world\n")
  68. memio = self.ioclass(buf)
  69. self.write_ops(memio, self.buftype)
  70. self.assertEqual(memio.getvalue(), buf)
  71. memio = self.ioclass()
  72. self.write_ops(memio, self.buftype)
  73. self.assertEqual(memio.getvalue(), buf)
  74. self.assertRaises(TypeError, memio.write, None)
  75. memio.close()
  76. self.assertRaises(ValueError, memio.write, self.buftype(""))
  77. def test_writelines(self):
  78. buf = self.buftype("1234567890")
  79. memio = self.ioclass()
  80. self.assertEqual(memio.writelines([buf] * 100), None)
  81. self.assertEqual(memio.getvalue(), buf * 100)
  82. memio.writelines([])
  83. self.assertEqual(memio.getvalue(), buf * 100)
  84. memio = self.ioclass()
  85. self.assertRaises(TypeError, memio.writelines, [buf] + [1])
  86. self.assertEqual(memio.getvalue(), buf)
  87. self.assertRaises(TypeError, memio.writelines, None)
  88. memio.close()
  89. self.assertRaises(ValueError, memio.writelines, [])
  90. def test_writelines_error(self):
  91. memio = self.ioclass()
  92. def error_gen():
  93. yield self.buftype('spam')
  94. raise KeyboardInterrupt
  95. self.assertRaises(KeyboardInterrupt, memio.writelines, error_gen())
  96. def test_truncate(self):
  97. buf = self.buftype("1234567890")
  98. memio = self.ioclass(buf)
  99. self.assertRaises(ValueError, memio.truncate, -1)
  100. self.assertRaises(ValueError, memio.truncate, IntLike(-1))
  101. memio.seek(6)
  102. self.assertEqual(memio.truncate(IntLike(8)), 8)
  103. self.assertEqual(memio.getvalue(), buf[:8])
  104. self.assertEqual(memio.truncate(), 6)
  105. self.assertEqual(memio.getvalue(), buf[:6])
  106. self.assertEqual(memio.truncate(4), 4)
  107. self.assertEqual(memio.getvalue(), buf[:4])
  108. self.assertEqual(memio.tell(), 6)
  109. memio.seek(0, 2)
  110. memio.write(buf)
  111. self.assertEqual(memio.getvalue(), buf[:4] + buf)
  112. pos = memio.tell()
  113. self.assertEqual(memio.truncate(None), pos)
  114. self.assertEqual(memio.tell(), pos)
  115. self.assertRaises(TypeError, memio.truncate, '0')
  116. memio.close()
  117. self.assertRaises(ValueError, memio.truncate, 0)
  118. self.assertRaises(ValueError, memio.truncate, IntLike(0))
  119. def test_init(self):
  120. buf = self.buftype("1234567890")
  121. memio = self.ioclass(buf)
  122. self.assertEqual(memio.getvalue(), buf)
  123. memio = self.ioclass(None)
  124. self.assertEqual(memio.getvalue(), self.EOF)
  125. memio.__init__(buf * 2)
  126. self.assertEqual(memio.getvalue(), buf * 2)
  127. memio.__init__(buf)
  128. self.assertEqual(memio.getvalue(), buf)
  129. self.assertRaises(TypeError, memio.__init__, [])
  130. def test_read(self):
  131. buf = self.buftype("1234567890")
  132. memio = self.ioclass(buf)
  133. self.assertEqual(memio.read(0), self.EOF)
  134. self.assertEqual(memio.read(1), buf[:1])
  135. self.assertEqual(memio.read(4), buf[1:5])
  136. self.assertEqual(memio.read(900), buf[5:])
  137. self.assertEqual(memio.read(), self.EOF)
  138. memio.seek(0)
  139. self.assertEqual(memio.read(IntLike(0)), self.EOF)
  140. self.assertEqual(memio.read(IntLike(1)), buf[:1])
  141. self.assertEqual(memio.read(IntLike(4)), buf[1:5])
  142. self.assertEqual(memio.read(IntLike(900)), buf[5:])
  143. memio.seek(0)
  144. self.assertEqual(memio.read(), buf)
  145. self.assertEqual(memio.read(), self.EOF)
  146. self.assertEqual(memio.tell(), 10)
  147. memio.seek(0)
  148. self.assertEqual(memio.read(-1), buf)
  149. memio.seek(0)
  150. self.assertEqual(memio.read(IntLike(-1)), buf)
  151. memio.seek(0)
  152. self.assertEqual(type(memio.read()), type(buf))
  153. memio.seek(100)
  154. self.assertEqual(type(memio.read()), type(buf))
  155. memio.seek(0)
  156. self.assertEqual(memio.read(None), buf)
  157. self.assertRaises(TypeError, memio.read, '')
  158. memio.seek(len(buf) + 1)
  159. self.assertEqual(memio.read(1), self.EOF)
  160. memio.seek(len(buf) + 1)
  161. self.assertEqual(memio.read(IntLike(1)), self.EOF)
  162. memio.seek(len(buf) + 1)
  163. self.assertEqual(memio.read(), self.EOF)
  164. memio.close()
  165. self.assertRaises(ValueError, memio.read)
  166. def test_readline(self):
  167. buf = self.buftype("1234567890\n")
  168. memio = self.ioclass(buf * 2)
  169. self.assertEqual(memio.readline(0), self.EOF)
  170. self.assertEqual(memio.readline(IntLike(0)), self.EOF)
  171. self.assertEqual(memio.readline(), buf)
  172. self.assertEqual(memio.readline(), buf)
  173. self.assertEqual(memio.readline(), self.EOF)
  174. memio.seek(0)
  175. self.assertEqual(memio.readline(5), buf[:5])
  176. self.assertEqual(memio.readline(5), buf[5:10])
  177. self.assertEqual(memio.readline(5), buf[10:15])
  178. memio.seek(0)
  179. self.assertEqual(memio.readline(IntLike(5)), buf[:5])
  180. self.assertEqual(memio.readline(IntLike(5)), buf[5:10])
  181. self.assertEqual(memio.readline(IntLike(5)), buf[10:15])
  182. memio.seek(0)
  183. self.assertEqual(memio.readline(-1), buf)
  184. memio.seek(0)
  185. self.assertEqual(memio.readline(IntLike(-1)), buf)
  186. memio.seek(0)
  187. self.assertEqual(memio.readline(0), self.EOF)
  188. self.assertEqual(memio.readline(IntLike(0)), self.EOF)
  189. # Issue #24989: Buffer overread
  190. memio.seek(len(buf) * 2 + 1)
  191. self.assertEqual(memio.readline(), self.EOF)
  192. buf = self.buftype("1234567890\n")
  193. memio = self.ioclass((buf * 3)[:-1])
  194. self.assertEqual(memio.readline(), buf)
  195. self.assertEqual(memio.readline(), buf)
  196. self.assertEqual(memio.readline(), buf[:-1])
  197. self.assertEqual(memio.readline(), self.EOF)
  198. memio.seek(0)
  199. self.assertEqual(type(memio.readline()), type(buf))
  200. self.assertEqual(memio.readline(), buf)
  201. self.assertRaises(TypeError, memio.readline, '')
  202. memio.close()
  203. self.assertRaises(ValueError, memio.readline)
  204. def test_readlines(self):
  205. buf = self.buftype("1234567890\n")
  206. memio = self.ioclass(buf * 10)
  207. self.assertEqual(memio.readlines(), [buf] * 10)
  208. memio.seek(5)
  209. self.assertEqual(memio.readlines(), [buf[5:]] + [buf] * 9)
  210. memio.seek(0)
  211. self.assertEqual(memio.readlines(15), [buf] * 2)
  212. memio.seek(0)
  213. self.assertEqual(memio.readlines(-1), [buf] * 10)
  214. memio.seek(0)
  215. self.assertEqual(memio.readlines(0), [buf] * 10)
  216. memio.seek(0)
  217. self.assertEqual(type(memio.readlines()[0]), type(buf))
  218. memio.seek(0)
  219. self.assertEqual(memio.readlines(None), [buf] * 10)
  220. self.assertRaises(TypeError, memio.readlines, '')
  221. # Issue #24989: Buffer overread
  222. memio.seek(len(buf) * 10 + 1)
  223. self.assertEqual(memio.readlines(), [])
  224. memio.close()
  225. self.assertRaises(ValueError, memio.readlines)
  226. def test_iterator(self):
  227. buf = self.buftype("1234567890\n")
  228. memio = self.ioclass(buf * 10)
  229. self.assertEqual(iter(memio), memio)
  230. self.assertTrue(hasattr(memio, '__iter__'))
  231. self.assertTrue(hasattr(memio, '__next__'))
  232. i = 0
  233. for line in memio:
  234. self.assertEqual(line, buf)
  235. i += 1
  236. self.assertEqual(i, 10)
  237. memio.seek(0)
  238. i = 0
  239. for line in memio:
  240. self.assertEqual(line, buf)
  241. i += 1
  242. self.assertEqual(i, 10)
  243. # Issue #24989: Buffer overread
  244. memio.seek(len(buf) * 10 + 1)
  245. self.assertEqual(list(memio), [])
  246. memio = self.ioclass(buf * 2)
  247. memio.close()
  248. self.assertRaises(ValueError, memio.__next__)
  249. def test_getvalue(self):
  250. buf = self.buftype("1234567890")
  251. memio = self.ioclass(buf)
  252. self.assertEqual(memio.getvalue(), buf)
  253. memio.read()
  254. self.assertEqual(memio.getvalue(), buf)
  255. self.assertEqual(type(memio.getvalue()), type(buf))
  256. memio = self.ioclass(buf * 1000)
  257. self.assertEqual(memio.getvalue()[-3:], self.buftype("890"))
  258. memio = self.ioclass(buf)
  259. memio.close()
  260. self.assertRaises(ValueError, memio.getvalue)
  261. def test_seek(self):
  262. buf = self.buftype("1234567890")
  263. memio = self.ioclass(buf)
  264. memio.read(5)
  265. self.assertRaises(ValueError, memio.seek, -1)
  266. self.assertRaises(ValueError, memio.seek, 1, -1)
  267. self.assertRaises(ValueError, memio.seek, 1, 3)
  268. self.assertEqual(memio.seek(0), 0)
  269. self.assertEqual(memio.seek(0, 0), 0)
  270. self.assertEqual(memio.read(), buf)
  271. self.assertEqual(memio.seek(3), 3)
  272. self.assertEqual(memio.seek(0, 1), 3)
  273. self.assertEqual(memio.read(), buf[3:])
  274. self.assertEqual(memio.seek(len(buf)), len(buf))
  275. self.assertEqual(memio.read(), self.EOF)
  276. memio.seek(len(buf) + 1)
  277. self.assertEqual(memio.read(), self.EOF)
  278. self.assertEqual(memio.seek(0, 2), len(buf))
  279. self.assertEqual(memio.read(), self.EOF)
  280. memio.close()
  281. self.assertRaises(ValueError, memio.seek, 0)
  282. def test_overseek(self):
  283. buf = self.buftype("1234567890")
  284. memio = self.ioclass(buf)
  285. self.assertEqual(memio.seek(len(buf) + 1), 11)
  286. self.assertEqual(memio.read(), self.EOF)
  287. self.assertEqual(memio.tell(), 11)
  288. self.assertEqual(memio.getvalue(), buf)
  289. memio.write(self.EOF)
  290. self.assertEqual(memio.getvalue(), buf)
  291. memio.write(buf)
  292. self.assertEqual(memio.getvalue(), buf + self.buftype('\0') + buf)
  293. def test_tell(self):
  294. buf = self.buftype("1234567890")
  295. memio = self.ioclass(buf)
  296. self.assertEqual(memio.tell(), 0)
  297. memio.seek(5)
  298. self.assertEqual(memio.tell(), 5)
  299. memio.seek(10000)
  300. self.assertEqual(memio.tell(), 10000)
  301. memio.close()
  302. self.assertRaises(ValueError, memio.tell)
  303. def test_flush(self):
  304. buf = self.buftype("1234567890")
  305. memio = self.ioclass(buf)
  306. self.assertEqual(memio.flush(), None)
  307. def test_flags(self):
  308. memio = self.ioclass()
  309. self.assertEqual(memio.writable(), True)
  310. self.assertEqual(memio.readable(), True)
  311. self.assertEqual(memio.seekable(), True)
  312. self.assertEqual(memio.isatty(), False)
  313. self.assertEqual(memio.closed, False)
  314. memio.close()
  315. self.assertRaises(ValueError, memio.writable)
  316. self.assertRaises(ValueError, memio.readable)
  317. self.assertRaises(ValueError, memio.seekable)
  318. self.assertRaises(ValueError, memio.isatty)
  319. self.assertEqual(memio.closed, True)
  320. def test_subclassing(self):
  321. buf = self.buftype("1234567890")
  322. def test1():
  323. class MemIO(self.ioclass):
  324. pass
  325. m = MemIO(buf)
  326. return m.getvalue()
  327. def test2():
  328. class MemIO(self.ioclass):
  329. def __init__(me, a, b):
  330. self.ioclass.__init__(me, a)
  331. m = MemIO(buf, None)
  332. return m.getvalue()
  333. self.assertEqual(test1(), buf)
  334. self.assertEqual(test2(), buf)
  335. def test_instance_dict_leak(self):
  336. # Test case for issue #6242.
  337. # This will be caught by regrtest.py -R if this leak.
  338. for _ in range(100):
  339. memio = self.ioclass()
  340. memio.foo = 1
  341. def test_pickling(self):
  342. buf = self.buftype("1234567890")
  343. memio = self.ioclass(buf)
  344. memio.foo = 42
  345. memio.seek(2)
  346. class PickleTestMemIO(self.ioclass):
  347. def __init__(me, initvalue, foo):
  348. self.ioclass.__init__(me, initvalue)
  349. me.foo = foo
  350. # __getnewargs__ is undefined on purpose. This checks that PEP 307
  351. # is used to provide pickling support.
  352. # Pickle expects the class to be on the module level. Here we use a
  353. # little hack to allow the PickleTestMemIO class to derive from
  354. # self.ioclass without having to define all combinations explicitly on
  355. # the module-level.
  356. import __main__
  357. PickleTestMemIO.__module__ = '__main__'
  358. PickleTestMemIO.__qualname__ = PickleTestMemIO.__name__
  359. __main__.PickleTestMemIO = PickleTestMemIO
  360. submemio = PickleTestMemIO(buf, 80)
  361. submemio.seek(2)
  362. # We only support pickle protocol 2 and onward since we use extended
  363. # __reduce__ API of PEP 307 to provide pickling support.
  364. for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
  365. for obj in (memio, submemio):
  366. obj2 = pickle.loads(pickle.dumps(obj, protocol=proto))
  367. self.assertEqual(obj.getvalue(), obj2.getvalue())
  368. self.assertEqual(obj.__class__, obj2.__class__)
  369. self.assertEqual(obj.foo, obj2.foo)
  370. self.assertEqual(obj.tell(), obj2.tell())
  371. obj2.close()
  372. self.assertRaises(ValueError, pickle.dumps, obj2, proto)
  373. del __main__.PickleTestMemIO
  374. class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
  375. # Test _pyio.BytesIO; class also inherited for testing C implementation
  376. UnsupportedOperation = pyio.UnsupportedOperation
  377. @staticmethod
  378. def buftype(s):
  379. return s.encode("ascii")
  380. ioclass = pyio.BytesIO
  381. EOF = b""
  382. def test_getbuffer(self):
  383. memio = self.ioclass(b"1234567890")
  384. buf = memio.getbuffer()
  385. self.assertEqual(bytes(buf), b"1234567890")
  386. memio.seek(5)
  387. buf = memio.getbuffer()
  388. self.assertEqual(bytes(buf), b"1234567890")
  389. # Trying to change the size of the BytesIO while a buffer is exported
  390. # raises a BufferError.
  391. self.assertRaises(BufferError, memio.write, b'x' * 100)
  392. self.assertRaises(BufferError, memio.truncate)
  393. self.assertRaises(BufferError, memio.close)
  394. self.assertFalse(memio.closed)
  395. # Mutating the buffer updates the BytesIO
  396. buf[3:6] = b"abc"
  397. self.assertEqual(bytes(buf), b"123abc7890")
  398. self.assertEqual(memio.getvalue(), b"123abc7890")
  399. # After the buffer gets released, we can resize and close the BytesIO
  400. # again
  401. del buf
  402. support.gc_collect()
  403. memio.truncate()
  404. memio.close()
  405. self.assertRaises(ValueError, memio.getbuffer)
  406. def test_read1(self):
  407. buf = self.buftype("1234567890")
  408. self.assertEqual(self.ioclass(buf).read1(), buf)
  409. self.assertEqual(self.ioclass(buf).read1(-1), buf)
  410. def test_readinto(self):
  411. buf = self.buftype("1234567890")
  412. memio = self.ioclass(buf)
  413. b = bytearray(b"hello")
  414. self.assertEqual(memio.readinto(b), 5)
  415. self.assertEqual(b, b"12345")
  416. self.assertEqual(memio.readinto(b), 5)
  417. self.assertEqual(b, b"67890")
  418. self.assertEqual(memio.readinto(b), 0)
  419. self.assertEqual(b, b"67890")
  420. b = bytearray(b"hello world")
  421. memio.seek(0)
  422. self.assertEqual(memio.readinto(b), 10)
  423. self.assertEqual(b, b"1234567890d")
  424. b = bytearray(b"")
  425. memio.seek(0)
  426. self.assertEqual(memio.readinto(b), 0)
  427. self.assertEqual(b, b"")
  428. self.assertRaises(TypeError, memio.readinto, '')
  429. import array
  430. a = array.array('b', b"hello world")
  431. memio = self.ioclass(buf)
  432. memio.readinto(a)
  433. self.assertEqual(a.tobytes(), b"1234567890d")
  434. memio.close()
  435. self.assertRaises(ValueError, memio.readinto, b)
  436. memio = self.ioclass(b"123")
  437. b = bytearray()
  438. memio.seek(42)
  439. memio.readinto(b)
  440. self.assertEqual(b, b"")
  441. def test_relative_seek(self):
  442. buf = self.buftype("1234567890")
  443. memio = self.ioclass(buf)
  444. self.assertEqual(memio.seek(-1, 1), 0)
  445. self.assertEqual(memio.seek(3, 1), 3)
  446. self.assertEqual(memio.seek(-4, 1), 0)
  447. self.assertEqual(memio.seek(-1, 2), 9)
  448. self.assertEqual(memio.seek(1, 1), 10)
  449. self.assertEqual(memio.seek(1, 2), 11)
  450. memio.seek(-3, 2)
  451. self.assertEqual(memio.read(), buf[-3:])
  452. memio.seek(0)
  453. memio.seek(1, 1)
  454. self.assertEqual(memio.read(), buf[1:])
  455. def test_unicode(self):
  456. memio = self.ioclass()
  457. self.assertRaises(TypeError, self.ioclass, "1234567890")
  458. self.assertRaises(TypeError, memio.write, "1234567890")
  459. self.assertRaises(TypeError, memio.writelines, ["1234567890"])
  460. def test_bytes_array(self):
  461. buf = b"1234567890"
  462. import array
  463. a = array.array('b', list(buf))
  464. memio = self.ioclass(a)
  465. self.assertEqual(memio.getvalue(), buf)
  466. self.assertEqual(memio.write(a), 10)
  467. self.assertEqual(memio.getvalue(), buf)
  468. def test_issue5449(self):
  469. buf = self.buftype("1234567890")
  470. self.ioclass(initial_bytes=buf)
  471. self.assertRaises(TypeError, self.ioclass, buf, foo=None)
  472. class TextIOTestMixin:
  473. def test_newlines_property(self):
  474. memio = self.ioclass(newline=None)
  475. # The C StringIO decodes newlines in write() calls, but the Python
  476. # implementation only does when reading. This function forces them to
  477. # be decoded for testing.
  478. def force_decode():
  479. memio.seek(0)
  480. memio.read()
  481. self.assertEqual(memio.newlines, None)
  482. memio.write("a\n")
  483. force_decode()
  484. self.assertEqual(memio.newlines, "\n")
  485. memio.write("b\r\n")
  486. force_decode()
  487. self.assertEqual(memio.newlines, ("\n", "\r\n"))
  488. memio.write("c\rd")
  489. force_decode()
  490. self.assertEqual(memio.newlines, ("\r", "\n", "\r\n"))
  491. def test_relative_seek(self):
  492. memio = self.ioclass()
  493. self.assertRaises(OSError, memio.seek, -1, 1)
  494. self.assertRaises(OSError, memio.seek, 3, 1)
  495. self.assertRaises(OSError, memio.seek, -3, 1)
  496. self.assertRaises(OSError, memio.seek, -1, 2)
  497. self.assertRaises(OSError, memio.seek, 1, 1)
  498. self.assertRaises(OSError, memio.seek, 1, 2)
  499. def test_textio_properties(self):
  500. memio = self.ioclass()
  501. # These are just dummy values but we nevertheless check them for fear
  502. # of unexpected breakage.
  503. self.assertIsNone(memio.encoding)
  504. self.assertIsNone(memio.errors)
  505. self.assertFalse(memio.line_buffering)
  506. def test_newline_default(self):
  507. memio = self.ioclass("a\nb\r\nc\rd")
  508. self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
  509. self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
  510. memio = self.ioclass()
  511. self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
  512. memio.seek(0)
  513. self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
  514. self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
  515. def test_newline_none(self):
  516. # newline=None
  517. memio = self.ioclass("a\nb\r\nc\rd", newline=None)
  518. self.assertEqual(list(memio), ["a\n", "b\n", "c\n", "d"])
  519. memio.seek(0)
  520. self.assertEqual(memio.read(1), "a")
  521. self.assertEqual(memio.read(2), "\nb")
  522. self.assertEqual(memio.read(2), "\nc")
  523. self.assertEqual(memio.read(1), "\n")
  524. self.assertEqual(memio.getvalue(), "a\nb\nc\nd")
  525. memio = self.ioclass(newline=None)
  526. self.assertEqual(2, memio.write("a\n"))
  527. self.assertEqual(3, memio.write("b\r\n"))
  528. self.assertEqual(3, memio.write("c\rd"))
  529. memio.seek(0)
  530. self.assertEqual(memio.read(), "a\nb\nc\nd")
  531. self.assertEqual(memio.getvalue(), "a\nb\nc\nd")
  532. memio = self.ioclass("a\r\nb", newline=None)
  533. self.assertEqual(memio.read(3), "a\nb")
  534. def test_newline_empty(self):
  535. # newline=""
  536. memio = self.ioclass("a\nb\r\nc\rd", newline="")
  537. self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
  538. memio.seek(0)
  539. self.assertEqual(memio.read(4), "a\nb\r")
  540. self.assertEqual(memio.read(2), "\nc")
  541. self.assertEqual(memio.read(1), "\r")
  542. self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
  543. memio = self.ioclass(newline="")
  544. self.assertEqual(2, memio.write("a\n"))
  545. self.assertEqual(2, memio.write("b\r"))
  546. self.assertEqual(2, memio.write("\nc"))
  547. self.assertEqual(2, memio.write("\rd"))
  548. memio.seek(0)
  549. self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
  550. self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
  551. def test_newline_lf(self):
  552. # newline="\n"
  553. memio = self.ioclass("a\nb\r\nc\rd", newline="\n")
  554. self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
  555. self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
  556. memio = self.ioclass(newline="\n")
  557. self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
  558. memio.seek(0)
  559. self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
  560. self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
  561. def test_newline_cr(self):
  562. # newline="\r"
  563. memio = self.ioclass("a\nb\r\nc\rd", newline="\r")
  564. self.assertEqual(memio.read(), "a\rb\r\rc\rd")
  565. memio.seek(0)
  566. self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
  567. self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd")
  568. memio = self.ioclass(newline="\r")
  569. self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
  570. memio.seek(0)
  571. self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
  572. memio.seek(0)
  573. self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"])
  574. self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd")
  575. def test_newline_crlf(self):
  576. # newline="\r\n"
  577. memio = self.ioclass("a\nb\r\nc\rd", newline="\r\n")
  578. self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd")
  579. memio.seek(0)
  580. self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
  581. memio.seek(0)
  582. self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"])
  583. self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd")
  584. memio = self.ioclass(newline="\r\n")
  585. self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
  586. memio.seek(0)
  587. self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
  588. self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd")
  589. def test_issue5265(self):
  590. # StringIO can duplicate newlines in universal newlines mode
  591. memio = self.ioclass("a\r\nb\r\n", newline=None)
  592. self.assertEqual(memio.read(5), "a\nb\n")
  593. self.assertEqual(memio.getvalue(), "a\nb\n")
  594. def test_newline_argument(self):
  595. self.assertRaises(TypeError, self.ioclass, newline=b"\n")
  596. self.assertRaises(ValueError, self.ioclass, newline="error")
  597. # These should not raise an error
  598. for newline in (None, "", "\n", "\r", "\r\n"):
  599. self.ioclass(newline=newline)
  600. class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin,
  601. TextIOTestMixin, unittest.TestCase):
  602. buftype = str
  603. ioclass = pyio.StringIO
  604. UnsupportedOperation = pyio.UnsupportedOperation
  605. EOF = ""
  606. def test_lone_surrogates(self):
  607. # Issue #20424
  608. memio = self.ioclass('\ud800')
  609. self.assertEqual(memio.read(), '\ud800')
  610. memio = self.ioclass()
  611. memio.write('\ud800')
  612. self.assertEqual(memio.getvalue(), '\ud800')
  613. class PyStringIOPickleTest(TextIOTestMixin, unittest.TestCase):
  614. """Test if pickle restores properly the internal state of StringIO.
  615. """
  616. buftype = str
  617. UnsupportedOperation = pyio.UnsupportedOperation
  618. EOF = ""
  619. class ioclass(pyio.StringIO):
  620. def __new__(cls, *args, **kwargs):
  621. return pickle.loads(pickle.dumps(pyio.StringIO(*args, **kwargs)))
  622. def __init__(self, *args, **kwargs):
  623. pass
  624. class CBytesIOTest(PyBytesIOTest):
  625. ioclass = io.BytesIO
  626. UnsupportedOperation = io.UnsupportedOperation
  627. def test_getstate(self):
  628. memio = self.ioclass()
  629. state = memio.__getstate__()
  630. self.assertEqual(len(state), 3)
  631. bytearray(state[0]) # Check if state[0] supports the buffer interface.
  632. self.assertIsInstance(state[1], int)
  633. if state[2] is not None:
  634. self.assertIsInstance(state[2], dict)
  635. memio.close()
  636. self.assertRaises(ValueError, memio.__getstate__)
  637. def test_setstate(self):
  638. # This checks whether __setstate__ does proper input validation.
  639. memio = self.ioclass()
  640. memio.__setstate__((b"no error", 0, None))
  641. memio.__setstate__((bytearray(b"no error"), 0, None))
  642. memio.__setstate__((b"no error", 0, {'spam': 3}))
  643. self.assertRaises(ValueError, memio.__setstate__, (b"", -1, None))
  644. self.assertRaises(TypeError, memio.__setstate__, ("unicode", 0, None))
  645. self.assertRaises(TypeError, memio.__setstate__, (b"", 0.0, None))
  646. self.assertRaises(TypeError, memio.__setstate__, (b"", 0, 0))
  647. self.assertRaises(TypeError, memio.__setstate__, (b"len-test", 0))
  648. self.assertRaises(TypeError, memio.__setstate__)
  649. self.assertRaises(TypeError, memio.__setstate__, 0)
  650. memio.close()
  651. self.assertRaises(ValueError, memio.__setstate__, (b"closed", 0, None))
  652. check_sizeof = support.check_sizeof
  653. @support.cpython_only
  654. def test_sizeof(self):
  655. basesize = support.calcobjsize('P2n2Pn')
  656. check = self.check_sizeof
  657. self.assertEqual(object.__sizeof__(io.BytesIO()), basesize)
  658. check(io.BytesIO(), basesize )
  659. n = 1000 # use a variable to prevent constant folding
  660. check(io.BytesIO(b'a' * n), basesize + sys.getsizeof(b'a' * n))
  661. # Various tests of copy-on-write behaviour for BytesIO.
  662. def _test_cow_mutation(self, mutation):
  663. # Common code for all BytesIO copy-on-write mutation tests.
  664. imm = b' ' * 1024
  665. old_rc = sys.getrefcount(imm)
  666. memio = self.ioclass(imm)
  667. self.assertEqual(sys.getrefcount(imm), old_rc + 1)
  668. mutation(memio)
  669. self.assertEqual(sys.getrefcount(imm), old_rc)
  670. @support.cpython_only
  671. def test_cow_truncate(self):
  672. # Ensure truncate causes a copy.
  673. def mutation(memio):
  674. memio.truncate(1)
  675. self._test_cow_mutation(mutation)
  676. @support.cpython_only
  677. def test_cow_write(self):
  678. # Ensure write that would not cause a resize still results in a copy.
  679. def mutation(memio):
  680. memio.seek(0)
  681. memio.write(b'foo')
  682. self._test_cow_mutation(mutation)
  683. @support.cpython_only
  684. def test_cow_setstate(self):
  685. # __setstate__ should cause buffer to be released.
  686. memio = self.ioclass(b'foooooo')
  687. state = memio.__getstate__()
  688. def mutation(memio):
  689. memio.__setstate__(state)
  690. self._test_cow_mutation(mutation)
  691. @support.cpython_only
  692. def test_cow_mutable(self):
  693. # BytesIO should accept only Bytes for copy-on-write sharing, since
  694. # arbitrary buffer-exporting objects like bytearray() aren't guaranteed
  695. # to be immutable.
  696. ba = bytearray(1024)
  697. old_rc = sys.getrefcount(ba)
  698. memio = self.ioclass(ba)
  699. self.assertEqual(sys.getrefcount(ba), old_rc)
  700. class CStringIOTest(PyStringIOTest):
  701. ioclass = io.StringIO
  702. UnsupportedOperation = io.UnsupportedOperation
  703. # XXX: For the Python version of io.StringIO, this is highly
  704. # dependent on the encoding used for the underlying buffer.
  705. def test_widechar(self):
  706. buf = self.buftype("\U0002030a\U00020347")
  707. memio = self.ioclass(buf)
  708. self.assertEqual(memio.getvalue(), buf)
  709. self.assertEqual(memio.write(buf), len(buf))
  710. self.assertEqual(memio.tell(), len(buf))
  711. self.assertEqual(memio.getvalue(), buf)
  712. self.assertEqual(memio.write(buf), len(buf))
  713. self.assertEqual(memio.tell(), len(buf) * 2)
  714. self.assertEqual(memio.getvalue(), buf + buf)
  715. def test_getstate(self):
  716. memio = self.ioclass()
  717. state = memio.__getstate__()
  718. self.assertEqual(len(state), 4)
  719. self.assertIsInstance(state[0], str)
  720. self.assertIsInstance(state[1], str)
  721. self.assertIsInstance(state[2], int)
  722. if state[3] is not None:
  723. self.assertIsInstance(state[3], dict)
  724. memio.close()
  725. self.assertRaises(ValueError, memio.__getstate__)
  726. def test_setstate(self):
  727. # This checks whether __setstate__ does proper input validation.
  728. memio = self.ioclass()
  729. memio.__setstate__(("no error", "\n", 0, None))
  730. memio.__setstate__(("no error", "", 0, {'spam': 3}))
  731. self.assertRaises(ValueError, memio.__setstate__, ("", "f", 0, None))
  732. self.assertRaises(ValueError, memio.__setstate__, ("", "", -1, None))
  733. self.assertRaises(TypeError, memio.__setstate__, (b"", "", 0, None))
  734. self.assertRaises(TypeError, memio.__setstate__, ("", b"", 0, None))
  735. self.assertRaises(TypeError, memio.__setstate__, ("", "", 0.0, None))
  736. self.assertRaises(TypeError, memio.__setstate__, ("", "", 0, 0))
  737. self.assertRaises(TypeError, memio.__setstate__, ("len-test", 0))
  738. self.assertRaises(TypeError, memio.__setstate__)
  739. self.assertRaises(TypeError, memio.__setstate__, 0)
  740. memio.close()
  741. self.assertRaises(ValueError, memio.__setstate__, ("closed", "", 0, None))
  742. class CStringIOPickleTest(PyStringIOPickleTest):
  743. UnsupportedOperation = io.UnsupportedOperation
  744. class ioclass(io.StringIO):
  745. def __new__(cls, *args, **kwargs):
  746. return pickle.loads(pickle.dumps(io.StringIO(*args, **kwargs)))
  747. def __init__(self, *args, **kwargs):
  748. pass
  749. if __name__ == '__main__':
  750. unittest.main()