python (3.12.0)

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