ファイル操作の練習とStringIO(3)

前回までにStringIOと同じように動作するモジュールMY_StringIOを実装するところまで話が進みました。実装自体にストーリーを付けたり、意味のあるまとめ方をするのは難しいと思うので淡々と実装を進めることにします。

MY_StringIOにはまだwriteすらありません。実装するためのテストを書きましょう。

    fp.close()
    self.assertTrue(fp.closed)
  def test_write_blank_fp(self):
    fp = self.MODULE.StringIO()
    self.assertEqual(0, fp.tell())
    s = 'hello'
    fp.write(s)
    self.assertEqual(5, fp.tell())
    self.assertEqual('hello', fp.getvalue())
    fp.close()

このテストがStringIOの動作に従っていれば、テストの失敗は1つだけのはずです。実際、テストを実行するとそのようになります。


.E..
======================================================================
ERROR: test_write_blank_fp (__main__.MY_StringIOTest)

                                                                                                                                          • -

Traceback (most recent call last):
File "./test_StringIO.py", line 14, in test_write_blank_fp
fp = self.MODULE.StringIO()
TypeError: __init__() takes exactly 2 arguments (1 given)

                                                                                                                                          • -

Ran 4 tests in 0.002s

FAILED (errors=1)


まずMY_String.StringIOのコンストラクタの引数の数が合ってないと教えてくれてます。これに関しては第2引数をオプショナルにすれば良いはずです。またファイルポインタ(正確にはself.bufのindex)を返すtell, ファイルポインタの位置から文字列の書き込みをするwriteも実装する必要があります。

class StringIO:
  def __init__(self, inp = ''):
    self.pos = 0
    self.buf = inp
...
  def close(self):
    self.closed = True
  def tell(self):
    return self.pos
  def write(self, inp):
    self.buf = inp
    self.pos += len(inp)

これでパスします。


....

                                                                                                                                          • -

Ran 4 tests in 0.000s

OK


ファイルポインタの位置を返すtellを追加しましたが、ファイルポインタの位置を移動させるseekというメソッドもStringIO.StringIOにはあります。次回はこれを実装します。最後にテストを追加して失敗して終わりましょう。

  def test_write_noblank_fp(self):
    fp = self.MODULE.StringIO('hello, ')
    fp.seek(7)
    fp.write('world')
    self.assertEqual(12, fp.tell())
    self.assertEquals('hello, world', fp.getvalue())
    fp.close()# del fp.buf

実行結果:


..E...
======================================================================
ERROR: test_write_noblank_fp (__main__.MY_StringIOTest)

                                                                                                                                          • -

Traceback (most recent call last):
File "./test_StringIO.py", line 32, in test_write_noblank_fp
fp.seek(7)
AttributeError: StringIO instance has no attribute 'seek'

                                                                                                                                          • -

Ran 6 tests in 0.002s

FAILED (errors=1)