Преглед изворни кода

Use io.BytesIO rather than cStringIO.

Gary van der Merwe пре 11 година
родитељ
комит
8914c3457f

+ 3 - 3
docs/tutorial/remote.txt

@@ -55,10 +55,10 @@ which claims that the client doesn't have any objects::
    ...     def next(self): pass
 
 With the ``determine_wants`` function in place, we can now fetch a pack,
-which we will write to a ``StringIO`` object::
+which we will write to a ``BytesIO`` object::
 
-   >>> from cStringIO import StringIO
-   >>> f = StringIO()
+   >>> from io import BytesIO
+   >>> f = BytesIO()
    >>> remote_refs = client.fetch_pack("/", determine_wants,
    ...    DummyGraphWalker(), pack_data=f.write)
 

+ 3 - 3
dulwich/client.py

@@ -38,7 +38,7 @@ Known capabilities that are not supported:
 
 __docformat__ = 'restructuredText'
 
-from cStringIO import StringIO
+from io import BytesIO
 import dulwich
 import select
 import socket
@@ -997,7 +997,7 @@ class HttpGitClient(GitClient):
             return old_refs
         if self.dumb:
             raise NotImplementedError(self.fetch_pack)
-        req_data = StringIO()
+        req_data = BytesIO()
         req_proto = Protocol(None, req_data.write)
         (have, want) = self._handle_receive_pack_head(
             req_proto, negotiated_capabilities, old_refs, new_refs)
@@ -1034,7 +1034,7 @@ class HttpGitClient(GitClient):
             return refs
         if self.dumb:
             raise NotImplementedError(self.send_pack)
-        req_data = StringIO()
+        req_data = BytesIO()
         req_proto = Protocol(None, req_data.write)
         self._handle_upload_pack_head(req_proto,
             negotiated_capabilities, graph_walker, wants,

+ 2 - 2
dulwich/diff_tree.py

@@ -23,7 +23,7 @@ from collections import (
     namedtuple,
     )
 
-from cStringIO import StringIO
+from io import BytesIO
 import itertools
 import stat
 
@@ -281,7 +281,7 @@ def _count_blocks(obj):
     :return: A dict of block hashcode -> total bytes occurring.
     """
     block_counts = defaultdict(int)
-    block = StringIO()
+    block = BytesIO()
     n = 0
 
     # Cache attrs as locals to avoid expensive lookups in the inner loop.

+ 3 - 3
dulwich/object_store.py

@@ -21,7 +21,7 @@
 """Git object store interfaces and implementation."""
 
 
-from cStringIO import StringIO
+from io import BytesIO
 import errno
 import itertools
 import os
@@ -765,9 +765,9 @@ class MemoryObjectStore(BaseObjectStore):
         :return: Fileobject to write to and a commit function to
             call when the pack is finished.
         """
-        f = StringIO()
+        f = BytesIO()
         def commit():
-            p = PackData.from_file(StringIO(f.getvalue()), f.tell())
+            p = PackData.from_file(BytesIO(f.getvalue()), f.tell())
             f.close()
             for obj in PackInflater.for_pack_data(p):
                 self._data[obj.id] = obj

+ 2 - 4
dulwich/objects.py

@@ -20,9 +20,7 @@
 """Access to base git objects."""
 
 import binascii
-from cStringIO import (
-    StringIO,
-    )
+from io import BytesIO
 from collections import namedtuple
 import os
 import posixpath
@@ -590,7 +588,7 @@ def _parse_message(chunks):
         order read from the text, possibly including duplicates. Includes a
         field named None for the freeform tag/commit text.
     """
-    f = StringIO("".join(chunks))
+    f = BytesIO("".join(chunks))
     k = None
     v = ""
     for l in f:

+ 5 - 7
dulwich/pack.py

@@ -33,9 +33,7 @@ a pointer in to the corresponding packfile.
 from collections import defaultdict
 
 import binascii
-from cStringIO import (
-    StringIO,
-    )
+from io import BytesIO
 from collections import (
     deque,
     )
@@ -742,7 +740,7 @@ class PackStreamReader(object):
             self.read_some = read_some
         self.sha = sha1()
         self._offset = 0
-        self._rbuf = StringIO()
+        self._rbuf = BytesIO()
         # trailer is a deque to avoid memory allocation on small reads
         self._trailer = deque()
         self._zlib_bufsize = zlib_bufsize
@@ -795,7 +793,7 @@ class PackStreamReader(object):
         if buf_len >= size:
             return self._rbuf.read(size)
         buf_data = self._rbuf.read()
-        self._rbuf = StringIO()
+        self._rbuf = BytesIO()
         return buf_data + self._read(self.read_all, size - buf_len)
 
     def recv(self, size):
@@ -804,7 +802,7 @@ class PackStreamReader(object):
         if buf_len:
             data = self._rbuf.read(size)
             if size >= buf_len:
-                self._rbuf = StringIO()
+                self._rbuf = BytesIO()
             return data
         return self._read(self.read_some, size)
 
@@ -841,7 +839,7 @@ class PackStreamReader(object):
             unpacked.offset = offset
 
             # prepend any unused data to current read buffer
-            buf = StringIO()
+            buf = BytesIO()
             buf.write(unused)
             buf.write(self._rbuf.read())
             buf.seek(0)

+ 13 - 13
dulwich/protocol.py

@@ -19,7 +19,7 @@
 
 """Generic functions for talking the git smart server protocol."""
 
-from cStringIO import StringIO
+from io import BytesIO
 from os import (
     SEEK_END,
     )
@@ -137,7 +137,7 @@ class Protocol(object):
         """
         if self._readahead is not None:
             raise ValueError('Attempted to unread multiple pkt-lines.')
-        self._readahead = StringIO(pkt_line(data))
+        self._readahead = BytesIO(pkt_line(data))
 
     def read_pkt_seq(self):
         """Read a sequence of pkt-lines from the remote git process.
@@ -240,7 +240,7 @@ class ReceivableProtocol(Protocol):
         super(ReceivableProtocol, self).__init__(self.read, write,
                                                  report_activity)
         self._recv = recv
-        self._rbuf = StringIO()
+        self._rbuf = BytesIO()
         self._rbufsize = rbufsize
 
     def read(self, size):
@@ -252,10 +252,10 @@ class ReceivableProtocol(Protocol):
         #  - use SEEK_END instead of the magic number.
         # Copyright (c) 2001-2010 Python Software Foundation; All Rights Reserved
         # Licensed under the Python Software Foundation License.
-        # TODO: see if buffer is more efficient than cStringIO.
+        # TODO: see if buffer is more efficient than cBytesIO.
         assert size > 0
 
-        # Our use of StringIO rather than lists of string objects returned by
+        # Our use of BytesIO rather than lists of string objects returned by
         # recv() minimizes memory usage and fragmentation that occurs when
         # rbufsize is large compared to the typical return value of recv().
         buf = self._rbuf
@@ -267,18 +267,18 @@ class ReceivableProtocol(Protocol):
             # Already have size bytes in our buffer?  Extract and return.
             buf.seek(start)
             rv = buf.read(size)
-            self._rbuf = StringIO()
+            self._rbuf = BytesIO()
             self._rbuf.write(buf.read())
             self._rbuf.seek(0)
             return rv
 
-        self._rbuf = StringIO()  # reset _rbuf.  we consume it via buf.
+        self._rbuf = BytesIO()  # reset _rbuf.  we consume it via buf.
         while True:
             left = size - buf_len
             # recv() will malloc the amount of memory given as its
             # parameter even though it often returns much less data
             # than that.  The returned data string is short lived
-            # as we copy it into a StringIO and free it.  This avoids
+            # as we copy it into a BytesIO and free it.  This avoids
             # fragmentation issues on many platforms.
             data = self._recv(left)
             if not data:
@@ -319,7 +319,7 @@ class ReceivableProtocol(Protocol):
             if len(data) == size:
                 # shortcut: skip the buffer if we read exactly size bytes
                 return data
-            buf = StringIO()
+            buf = BytesIO()
             buf.write(data)
             buf.seek(0)
             del data  # explicit free
@@ -381,7 +381,7 @@ class BufferedPktLineWriter(object):
         """
         self._write = write
         self._bufsize = bufsize
-        self._wbuf = StringIO()
+        self._wbuf = BytesIO()
         self._buflen = 0
 
     def write(self, data):
@@ -405,7 +405,7 @@ class BufferedPktLineWriter(object):
         if data:
             self._write(data)
         self._len = 0
-        self._wbuf = StringIO()
+        self._wbuf = BytesIO()
 
 
 class PktLineParser(object):
@@ -414,7 +414,7 @@ class PktLineParser(object):
 
     def __init__(self, handle_pkt):
         self.handle_pkt = handle_pkt
-        self._readahead = StringIO()
+        self._readahead = BytesIO()
 
     def parse(self, data):
         """Parse a fragment of data and call back for any completed packets.
@@ -433,7 +433,7 @@ class PktLineParser(object):
                 buf = buf[size:]
             else:
                 break
-        self._readahead = StringIO()
+        self._readahead = BytesIO()
         self._readahead.write(buf)
 
     def get_tail(self):

+ 3 - 3
dulwich/repo.py

@@ -27,7 +27,7 @@ local disk (Repo).
 
 """
 
-from cStringIO import StringIO
+from io import BytesIO
 import errno
 import os
 
@@ -176,7 +176,7 @@ class BaseRepo(object):
         """Initialize a default set of named files."""
         from dulwich.config import ConfigFile
         self._put_named_file('description', "Unnamed repository")
-        f = StringIO()
+        f = BytesIO()
         cf = ConfigFile()
         cf.set("core", "repositoryformatversion", "0")
         cf.set("core", "filemode", "true")
@@ -934,7 +934,7 @@ class MemoryRepo(BaseRepo):
         contents = self._named_files.get(path, None)
         if contents is None:
             return None
-        return StringIO(contents)
+        return BytesIO(contents)
 
     def open_index(self):
         """Fail to open index for this repo, since it is bare.

+ 2 - 2
dulwich/tests/compat/test_client.py

@@ -19,7 +19,7 @@
 
 """Compatibilty tests between the Dulwich client and the cgit server."""
 
-from cStringIO import StringIO
+from io import BytesIO
 import BaseHTTPServer
 import SimpleHTTPServer
 import copy
@@ -169,7 +169,7 @@ class DulwichClientTestBase(object):
 
     def test_archive(self):
         c = self._client()
-        f = StringIO()
+        f = BytesIO()
         c.archive(self._build_path('/server_new.export'), 'HEAD', f.write)
         f.seek(0)
         tf = tarfile.open(fileobj=f)

+ 3 - 3
dulwich/tests/compat/test_repository.py

@@ -20,7 +20,7 @@
 """Compatibility tests for dulwich repositories."""
 
 
-from cStringIO import StringIO
+from io import BytesIO
 import itertools
 import os
 
@@ -54,7 +54,7 @@ class ObjectStoreTestCase(CompatTestCase):
 
     def _parse_refs(self, output):
         refs = {}
-        for line in StringIO(output):
+        for line in BytesIO(output):
             fields = line.rstrip('\n').split(' ')
             self.assertEqual(3, len(fields))
             refname, type_name, sha = fields
@@ -64,7 +64,7 @@ class ObjectStoreTestCase(CompatTestCase):
         return refs
 
     def _parse_objects(self, output):
-        return set(s.rstrip('\n').split(' ')[0] for s in StringIO(output))
+        return set(s.rstrip('\n').split(' ')[0] for s in BytesIO(output))
 
     def test_bare(self):
         self.assertTrue(self._repo.bare)

+ 7 - 7
dulwich/tests/test_client.py

@@ -16,7 +16,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA  02110-1301, USA.
 
-from cStringIO import StringIO
+from io import BytesIO
 
 from dulwich import (
     client,
@@ -71,8 +71,8 @@ class GitClientTests(TestCase):
 
     def setUp(self):
         super(GitClientTests, self).setUp()
-        self.rout = StringIO()
-        self.rin = StringIO()
+        self.rout = BytesIO()
+        self.rin = BytesIO()
         self.client = DummyClient(lambda x: True, self.rin.read,
                                   self.rout.write)
 
@@ -202,7 +202,7 @@ class GitClientTests(TestCase):
         def generate_pack_contents(have, want):
             return {}
 
-        f = StringIO()
+        f = BytesIO()
         empty_pack = write_pack_objects(f, {})
         self.client.send_pack('/', determine_wants, generate_pack_contents)
         self.assertEqual(
@@ -240,7 +240,7 @@ class GitClientTests(TestCase):
         def generate_pack_contents(have, want):
             return [(commit, None), (tree, ''), ]
 
-        f = StringIO()
+        f = BytesIO()
         pack = write_pack_objects(f, generate_pack_contents(None, None))
         self.client.send_pack('/', determine_wants, generate_pack_contents)
         self.assertEqual(
@@ -563,7 +563,7 @@ class LocalGitClientTests(TestCase):
     def test_fetch_empty(self):
         c = LocalGitClient()
         s = open_repo('a.git')
-        out = StringIO()
+        out = BytesIO()
         walker = {}
         c.fetch_pack(s.path, lambda heads: [], graph_walker=walker,
             pack_data=out.write)
@@ -573,7 +573,7 @@ class LocalGitClientTests(TestCase):
     def test_fetch_pack_none(self):
         c = LocalGitClient()
         s = open_repo('a.git')
-        out = StringIO()
+        out = BytesIO()
         walker = MemoryRepo().get_graph_walker()
         c.fetch_pack(s.path,
             lambda heads: ["a90fa2d900a17e99b433217e988c4eb4a2e9a097"],

+ 5 - 5
dulwich/tests/test_config.py

@@ -18,7 +18,7 @@
 
 """Tests for reading and writing configuration files."""
 
-from cStringIO import StringIO
+from io import BytesIO
 from dulwich.config import (
     ConfigDict,
     ConfigFile,
@@ -37,7 +37,7 @@ from dulwich.tests import TestCase
 class ConfigFileTests(TestCase):
 
     def from_file(self, text):
-        return ConfigFile.from_file(StringIO(text))
+        return ConfigFile.from_file(BytesIO(text))
 
     def test_empty(self):
         ConfigFile()
@@ -129,21 +129,21 @@ class ConfigFileTests(TestCase):
 
     def test_write_to_file_empty(self):
         c = ConfigFile()
-        f = StringIO()
+        f = BytesIO()
         c.write_to_file(f)
         self.assertEqual("", f.getvalue())
 
     def test_write_to_file_section(self):
         c = ConfigFile()
         c.set(("core", ), "foo", "bar")
-        f = StringIO()
+        f = BytesIO()
         c.write_to_file(f)
         self.assertEqual("[core]\n\tfoo = bar\n", f.getvalue())
 
     def test_write_to_file_subsection(self):
         c = ConfigFile()
         c.set(("branch", "blie"), "foo", "bar")
-        f = StringIO()
+        f = BytesIO()
         c.write_to_file(f)
         self.assertEqual("[branch \"blie\"]\n\tfoo = bar\n", f.getvalue())
 

+ 3 - 3
dulwich/tests/test_fastexport.py

@@ -17,7 +17,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA  02110-1301, USA.
 
-from cStringIO import StringIO
+from io import BytesIO
 import stat
 
 
@@ -47,7 +47,7 @@ class GitFastExporterTests(TestCase):
     def setUp(self):
         super(GitFastExporterTests, self).setUp()
         self.store = MemoryObjectStore()
-        self.stream = StringIO()
+        self.stream = BytesIO()
         try:
             from dulwich.fastexport import GitFastExporter
         except ImportError:
@@ -126,7 +126,7 @@ class GitImportProcessorTests(TestCase):
         self.assertEqual(commit, self.repo["refs/heads/foo"])
 
     def test_import_stream(self):
-        markers = self.processor.import_stream(StringIO("""blob
+        markers = self.processor.import_stream(BytesIO("""blob
 mark :1
 data 11
 text for a

+ 5 - 7
dulwich/tests/test_index.py

@@ -19,9 +19,7 @@
 """Tests for the index."""
 
 
-from cStringIO import (
-    StringIO,
-    )
+from io import BytesIO
 import os
 import shutil
 import stat
@@ -163,21 +161,21 @@ class CleanupModeTests(TestCase):
 class WriteCacheTimeTests(TestCase):
 
     def test_write_string(self):
-        f = StringIO()
+        f = BytesIO()
         self.assertRaises(TypeError, write_cache_time, f, "foo")
 
     def test_write_int(self):
-        f = StringIO()
+        f = BytesIO()
         write_cache_time(f, 434343)
         self.assertEqual(struct.pack(">LL", 434343, 0), f.getvalue())
 
     def test_write_tuple(self):
-        f = StringIO()
+        f = BytesIO()
         write_cache_time(f, (434343, 21))
         self.assertEqual(struct.pack(">LL", 434343, 21), f.getvalue())
 
     def test_write_float(self):
-        f = StringIO()
+        f = BytesIO()
         write_cache_time(f, 434343.000000021)
         self.assertEqual(struct.pack(">LL", 434343, 21), f.getvalue())
 

+ 3 - 3
dulwich/tests/test_object_store.py

@@ -19,7 +19,7 @@
 """Tests for the object store interface."""
 
 
-from cStringIO import StringIO
+from io import BytesIO
 import os
 import shutil
 import tempfile
@@ -217,7 +217,7 @@ class MemoryObjectStoreTests(ObjectStoreTests, TestCase):
         blob = make_object(Blob, data='yummy data')
         o.add_object(blob)
 
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (REF_DELTA, (blob.id, 'more yummy data')),
           ], store=o)
@@ -315,7 +315,7 @@ class DiskObjectStoreTests(PackBasedObjectStoreTests, TestCase):
         blob = make_object(Blob, data='yummy data')
         o.add_object(blob)
 
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (REF_DELTA, (blob.id, 'more yummy data')),
           ], store=o)

+ 3 - 3
dulwich/tests/test_objects.py

@@ -22,7 +22,7 @@
 # TODO: Round-trip parse-serialize-parse and serialize-parse-serialize tests.
 
 
-from cStringIO import StringIO
+from io import BytesIO
 import datetime
 from itertools import (
     permutations,
@@ -124,7 +124,7 @@ class BlobReadTests(TestCase):
     def test_legacy_from_file(self):
         b1 = Blob.from_string("foo")
         b_raw = b1.as_legacy_object()
-        b2 = b1.from_file(StringIO(b_raw))
+        b2 = b1.from_file(BytesIO(b_raw))
         self.assertEqual(b1, b2)
 
     def test_chunks(self):
@@ -251,7 +251,7 @@ class ShaFileTests(TestCase):
         # zlib on some systems uses smaller buffers,
         # resulting in a different header.
         # See https://github.com/libgit2/libgit2/pull/464
-        sf = ShaFile.from_file(StringIO(small_buffer_zlib_object))
+        sf = ShaFile.from_file(BytesIO(small_buffer_zlib_object))
         self.assertEqual(sf.type_name, "tag")
         self.assertEqual(sf.tagger, " <@localhost>")
 

+ 32 - 32
dulwich/tests/test_pack.py

@@ -20,7 +20,7 @@
 """Tests for Dulwich packs."""
 
 
-from cStringIO import StringIO
+from io import BytesIO
 from hashlib import sha1
 import os
 import shutil
@@ -247,7 +247,7 @@ class TestPackData(PackTests):
         self.assertEqual(idx1, idx2)
 
     def test_compute_file_sha(self):
-        f = StringIO('abcd1234wxyz')
+        f = BytesIO('abcd1234wxyz')
         self.assertEqual(sha1('abcd1234wxyz').hexdigest(),
                          compute_file_sha(f).hexdigest())
         self.assertEqual(sha1('abcd1234wxyz').hexdigest(),
@@ -385,10 +385,10 @@ class TestPack(PackTests):
         Pack.from_objects(data, index).check_length_and_checksum()
 
         data._file.seek(12)
-        bad_file = StringIO()
+        bad_file = BytesIO()
         write_pack_header(bad_file, 9999)
         bad_file.write(data._file.read())
-        bad_file = StringIO(bad_file.getvalue())
+        bad_file = BytesIO(bad_file.getvalue())
         bad_data = PackData('', file=bad_file)
         bad_pack = Pack.from_lazy_objects(lambda: bad_data, lambda: index)
         self.assertRaises(AssertionError, lambda: bad_pack.data)
@@ -401,7 +401,7 @@ class TestPack(PackTests):
         Pack.from_objects(data, index).check_length_and_checksum()
 
         data._file.seek(0)
-        bad_file = StringIO(data._file.read()[:-20] + ('\xff' * 20))
+        bad_file = BytesIO(data._file.read()[:-20] + ('\xff' * 20))
         bad_data = PackData('', file=bad_file)
         bad_pack = Pack.from_lazy_objects(lambda: bad_data, lambda: index)
         self.assertRaises(ChecksumMismatch, lambda: bad_pack.data)
@@ -476,13 +476,13 @@ class TestThinPack(PackTests):
 class WritePackTests(TestCase):
 
     def test_write_pack_header(self):
-        f = StringIO()
+        f = BytesIO()
         write_pack_header(f, 42)
         self.assertEqual('PACK\x00\x00\x00\x02\x00\x00\x00*',
                 f.getvalue())
 
     def test_write_pack_object(self):
-        f = StringIO()
+        f = BytesIO()
         f.write('header')
         offset = f.tell()
         crc32 = write_pack_object(f, Blob.type_num, 'blob')
@@ -499,7 +499,7 @@ class WritePackTests(TestCase):
         self.assertEqual('x', unused)
 
     def test_write_pack_object_sha(self):
-        f = StringIO()
+        f = BytesIO()
         f.write('header')
         offset = f.tell()
         sha_a = sha1('foo')
@@ -589,7 +589,7 @@ class BaseTestFilePackIndexWriting(BaseTestPackIndexWriting):
         return idx
 
     def writeIndex(self, filename, entries, pack_checksum):
-        # FIXME: Write to StringIO instead rather than hitting disk ?
+        # FIXME: Write to BytesIO instead rather than hitting disk ?
         f = GitFile(filename, "wb")
         try:
             self._write_fn(f, entries, pack_checksum)
@@ -655,7 +655,7 @@ class ReadZlibTests(TestCase):
 
     def setUp(self):
         super(ReadZlibTests, self).setUp()
-        self.read = StringIO(self.comp + self.extra).read
+        self.read = BytesIO(self.comp + self.extra).read
         self.unpacked = UnpackedObject(Tree.type_num, None, len(self.decomp), 0)
 
     def test_decompress_size(self):
@@ -671,16 +671,16 @@ class ReadZlibTests(TestCase):
                           self.unpacked)
 
     def test_decompress_truncated(self):
-        read = StringIO(self.comp[:10]).read
+        read = BytesIO(self.comp[:10]).read
         self.assertRaises(zlib.error, read_zlib_chunks, read, self.unpacked)
 
-        read = StringIO(self.comp).read
+        read = BytesIO(self.comp).read
         self.assertRaises(zlib.error, read_zlib_chunks, read, self.unpacked)
 
     def test_decompress_empty(self):
         unpacked = UnpackedObject(Tree.type_num, None, 0, None)
         comp = zlib.compress('')
-        read = StringIO(comp + self.extra).read
+        read = BytesIO(comp + self.extra).read
         unused = read_zlib_chunks(read, unpacked)
         self.assertEqual('', ''.join(unpacked.decomp_chunks))
         self.assertNotEquals('', unused)
@@ -747,13 +747,13 @@ class DeltifyTests(TestCase):
 class TestPackStreamReader(TestCase):
 
     def test_read_objects_emtpy(self):
-        f = StringIO()
+        f = BytesIO()
         build_pack(f, [])
         reader = PackStreamReader(f.read)
         self.assertEqual(0, len(list(reader.read_objects())))
 
     def test_read_objects(self):
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (Blob.type_num, 'blob'),
           (OFS_DELTA, (0, 'blob1')),
@@ -781,7 +781,7 @@ class TestPackStreamReader(TestCase):
         self.assertEqual(entries[1][4], unpacked_delta.crc32)
 
     def test_read_objects_buffered(self):
-        f = StringIO()
+        f = BytesIO()
         build_pack(f, [
           (Blob.type_num, 'blob'),
           (OFS_DELTA, (0, 'blob1')),
@@ -790,7 +790,7 @@ class TestPackStreamReader(TestCase):
         self.assertEqual(2, len(list(reader.read_objects())))
 
     def test_read_objects_empty(self):
-        reader = PackStreamReader(StringIO().read)
+        reader = PackStreamReader(BytesIO().read)
         self.assertEqual([], list(reader.read_objects()))
 
 
@@ -851,7 +851,7 @@ class DeltaChainIteratorTests(TestCase):
         self.assertEqual(expected, list(pack_iter._walk_all_chains()))
 
     def test_no_deltas(self):
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (Commit.type_num, 'commit'),
           (Blob.type_num, 'blob'),
@@ -860,7 +860,7 @@ class DeltaChainIteratorTests(TestCase):
         self.assertEntriesMatch([0, 1, 2], entries, self.make_pack_iter(f))
 
     def test_ofs_deltas(self):
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (Blob.type_num, 'blob'),
           (OFS_DELTA, (0, 'blob1')),
@@ -869,7 +869,7 @@ class DeltaChainIteratorTests(TestCase):
         self.assertEntriesMatch([0, 1, 2], entries, self.make_pack_iter(f))
 
     def test_ofs_deltas_chain(self):
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (Blob.type_num, 'blob'),
           (OFS_DELTA, (0, 'blob1')),
@@ -878,7 +878,7 @@ class DeltaChainIteratorTests(TestCase):
         self.assertEntriesMatch([0, 1, 2], entries, self.make_pack_iter(f))
 
     def test_ref_deltas(self):
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (REF_DELTA, (1, 'blob1')),
           (Blob.type_num, ('blob')),
@@ -887,7 +887,7 @@ class DeltaChainIteratorTests(TestCase):
         self.assertEntriesMatch([1, 0, 2], entries, self.make_pack_iter(f))
 
     def test_ref_deltas_chain(self):
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (REF_DELTA, (2, 'blob1')),
           (Blob.type_num, ('blob')),
@@ -898,7 +898,7 @@ class DeltaChainIteratorTests(TestCase):
     def test_ofs_and_ref_deltas(self):
         # Deltas pending on this offset are popped before deltas depending on
         # this ref.
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (REF_DELTA, (1, 'blob1')),
           (Blob.type_num, ('blob')),
@@ -907,7 +907,7 @@ class DeltaChainIteratorTests(TestCase):
         self.assertEntriesMatch([1, 2, 0], entries, self.make_pack_iter(f))
 
     def test_mixed_chain(self):
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (Blob.type_num, 'blob'),
           (REF_DELTA, (2, 'blob2')),
@@ -923,7 +923,7 @@ class DeltaChainIteratorTests(TestCase):
         objects_spec = [(Blob.type_num, 'blob')]
         for i in range(n):
             objects_spec.append((OFS_DELTA, (i, 'blob%i' % i)))
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, objects_spec)
         self.assertEntriesMatch(range(n + 1), entries, self.make_pack_iter(f))
 
@@ -932,13 +932,13 @@ class DeltaChainIteratorTests(TestCase):
         objects_spec = [(Blob.type_num, 'blob')]
         for i in range(n):
             objects_spec.append((OFS_DELTA, (0, 'blob%i' % i)))
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, objects_spec)
         self.assertEntriesMatch(range(n + 1), entries, self.make_pack_iter(f))
 
     def test_ext_ref(self):
         blob, = self.store_blobs(['blob'])
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [(REF_DELTA, (blob.id, 'blob1'))],
                              store=self.store)
         pack_iter = self.make_pack_iter(f)
@@ -947,7 +947,7 @@ class DeltaChainIteratorTests(TestCase):
 
     def test_ext_ref_chain(self):
         blob, = self.store_blobs(['blob'])
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (REF_DELTA, (1, 'blob2')),
           (REF_DELTA, (blob.id, 'blob1')),
@@ -958,7 +958,7 @@ class DeltaChainIteratorTests(TestCase):
 
     def test_ext_ref_multiple_times(self):
         blob, = self.store_blobs(['blob'])
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (REF_DELTA, (blob.id, 'blob1')),
           (REF_DELTA, (blob.id, 'blob2')),
@@ -969,7 +969,7 @@ class DeltaChainIteratorTests(TestCase):
 
     def test_multiple_ext_refs(self):
         b1, b2 = self.store_blobs(['foo', 'bar'])
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (REF_DELTA, (b1.id, 'foo1')),
           (REF_DELTA, (b2.id, 'bar2')),
@@ -981,7 +981,7 @@ class DeltaChainIteratorTests(TestCase):
 
     def test_bad_ext_ref_non_thin_pack(self):
         blob, = self.store_blobs(['blob'])
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [(REF_DELTA, (blob.id, 'blob1'))],
                              store=self.store)
         pack_iter = self.make_pack_iter(f, thin=False)
@@ -993,7 +993,7 @@ class DeltaChainIteratorTests(TestCase):
 
     def test_bad_ext_ref_thin_pack(self):
         b1, b2, b3 = self.store_blobs(['foo', 'bar', 'baz'])
-        f = StringIO()
+        f = BytesIO()
         entries = build_pack(f, [
           (REF_DELTA, (1, 'foo99')),
           (REF_DELTA, (b1.id, 'foo1')),

+ 21 - 21
dulwich/tests/test_patch.py

@@ -18,7 +18,7 @@
 
 """Tests for patch.py."""
 
-from cStringIO import StringIO
+from io import BytesIO
 
 from dulwich.objects import (
     Blob,
@@ -45,7 +45,7 @@ from dulwich.tests import (
 class WriteCommitPatchTests(TestCase):
 
     def test_simple(self):
-        f = StringIO()
+        f = BytesIO()
         c = Commit()
         c.committer = c.author = "Jelmer <jelmer@samba.org>"
         c.commit_time = c.author_time = 1271350201
@@ -88,7 +88,7 @@ Subject: [PATCH 1/2] Remove executable bit from prey.ico (triggers a lintian war
 -- 
 1.7.0.4
 """
-        c, diff, version = git_am_patch_split(StringIO(text))
+        c, diff, version = git_am_patch_split(BytesIO(text))
         self.assertEqual("Jelmer Vernooij <jelmer@samba.org>", c.committer)
         self.assertEqual("Jelmer Vernooij <jelmer@samba.org>", c.author)
         self.assertEqual("Remove executable bit from prey.ico "
@@ -118,7 +118,7 @@ Subject:  [Dulwich-users] [PATCH] Added unit tests for
 -- 
 1.7.0.4
 """
-        c, diff, version = git_am_patch_split(StringIO(text))
+        c, diff, version = git_am_patch_split(BytesIO(text))
         self.assertEqual('Added unit tests for dulwich.object_store.tree_lookup_path.\n\n* dulwich/tests/test_object_store.py\n  (TreeLookupPathTests): This test case contains a few tests that ensure the\n   tree_lookup_path function works as expected.\n', c.message)
 
     def test_extract_pseudo_from_header(self):
@@ -141,7 +141,7 @@ From: Jelmer Vernooy <jelmer@debian.org>
 -- 
 1.7.0.4
 """
-        c, diff, version = git_am_patch_split(StringIO(text))
+        c, diff, version = git_am_patch_split(BytesIO(text))
         self.assertEqual("Jelmer Vernooy <jelmer@debian.org>", c.author)
         self.assertEqual('Added unit tests for dulwich.object_store.tree_lookup_path.\n\n* dulwich/tests/test_object_store.py\n  (TreeLookupPathTests): This test case contains a few tests that ensure the\n   tree_lookup_path function works as expected.\n', c.message)
 
@@ -160,7 +160,7 @@ From: Jelmer Vernooy <jelmer@debian.org>
  mode change 100755 => 100644 pixmaps/prey.ico
 
 """
-        c, diff, version = git_am_patch_split(StringIO(text))
+        c, diff, version = git_am_patch_split(BytesIO(text))
         self.assertEqual(None, version)
 
     def test_extract_mercurial(self):
@@ -171,7 +171,7 @@ From: Jelmer Vernooy <jelmer@debian.org>
 @@ -158,7 +158,7 @@
  
  '''
-         c, diff, version = git_am_patch_split(StringIO(text))
+         c, diff, version = git_am_patch_split(BytesIO(text))
 -        self.assertIs(None, version)
 +        self.assertEqual(None, version)
  
@@ -196,7 +196,7 @@ Unsubscribe : https://launchpad.net/~dulwich-users
 More help   : https://help.launchpad.net/ListHelp
 
 """ % expected_diff
-        c, diff, version = git_am_patch_split(StringIO(text))
+        c, diff, version = git_am_patch_split(BytesIO(text))
         self.assertEqual(expected_diff, diff)
         self.assertEqual(None, version)
 
@@ -205,7 +205,7 @@ class DiffTests(TestCase):
     """Tests for write_blob_diff and write_tree_diff."""
 
     def test_blob_diff(self):
-        f = StringIO()
+        f = BytesIO()
         write_blob_diff(f, ("foo.txt", 0o644, Blob.from_string("old\nsame\n")),
                            ("bar.txt", 0o644, Blob.from_string("new\nsame\n")))
         self.assertEqual([
@@ -220,7 +220,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_blob_add(self):
-        f = StringIO()
+        f = BytesIO()
         write_blob_diff(f, (None, None, None),
                            ("bar.txt", 0o644, Blob.from_string("new\nsame\n")))
         self.assertEqual([
@@ -235,7 +235,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_blob_remove(self):
-        f = StringIO()
+        f = BytesIO()
         write_blob_diff(f, ("bar.txt", 0o644, Blob.from_string("new\nsame\n")),
                            (None, None, None))
         self.assertEqual([
@@ -250,7 +250,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_tree_diff(self):
-        f = StringIO()
+        f = BytesIO()
         store = MemoryObjectStore()
         added = Blob.from_string("add\n")
         removed = Blob.from_string("removed\n")
@@ -294,7 +294,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_tree_diff_submodule(self):
-        f = StringIO()
+        f = BytesIO()
         store = MemoryObjectStore()
         tree1 = Tree()
         tree1.add("asubmodule", S_IFGITLINK,
@@ -315,7 +315,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_object_diff_blob(self):
-        f = StringIO()
+        f = BytesIO()
         b1 = Blob.from_string("old\nsame\n")
         b2 = Blob.from_string("new\nsame\n")
         store = MemoryObjectStore()
@@ -334,7 +334,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_object_diff_add_blob(self):
-        f = StringIO()
+        f = BytesIO()
         store = MemoryObjectStore()
         b2 = Blob.from_string("new\nsame\n")
         store.add_object(b2)
@@ -352,7 +352,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_object_diff_remove_blob(self):
-        f = StringIO()
+        f = BytesIO()
         b1 = Blob.from_string("new\nsame\n")
         store = MemoryObjectStore()
         store.add_object(b1)
@@ -370,7 +370,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_object_diff_bin_blob_force(self):
-        f = StringIO()
+        f = BytesIO()
         # Prepare two slightly different PNG headers
         b1 = Blob.from_string(
             "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52"
@@ -398,7 +398,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_object_diff_bin_blob(self):
-        f = StringIO()
+        f = BytesIO()
         # Prepare two slightly different PNG headers
         b1 = Blob.from_string(
             "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52"
@@ -417,7 +417,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_object_diff_add_bin_blob(self):
-        f = StringIO()
+        f = BytesIO()
         b2 = Blob.from_string(
             '\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52'
             '\x00\x00\x01\xd5\x00\x00\x00\x9f\x08\x03\x00\x00\x00\x98\xd3\xb3')
@@ -433,7 +433,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_object_diff_remove_bin_blob(self):
-        f = StringIO()
+        f = BytesIO()
         b1 = Blob.from_string(
             '\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52'
             '\x00\x00\x01\xd5\x00\x00\x00\x9f\x08\x04\x00\x00\x00\x05\x04\x8b')
@@ -449,7 +449,7 @@ class DiffTests(TestCase):
             ], f.getvalue().splitlines())
 
     def test_object_diff_kind_change(self):
-        f = StringIO()
+        f = BytesIO()
         b1 = Blob.from_string("new\nsame\n")
         store = MemoryObjectStore()
         store.add_object(b1)

+ 19 - 19
dulwich/tests/test_porcelain.py

@@ -18,7 +18,7 @@
 
 """Tests for dulwich.porcelain."""
 
-from cStringIO import StringIO
+from io import BytesIO
 import os
 import shutil
 import tarfile
@@ -56,8 +56,8 @@ class ArchiveTests(PorcelainTestCase):
     def test_simple(self):
         c1, c2, c3 = build_commit_graph(self.repo.object_store, [[1], [2, 1], [3, 1, 2]])
         self.repo.refs["refs/heads/master"] = c3.id
-        out = StringIO()
-        err = StringIO()
+        out = BytesIO()
+        err = BytesIO()
         porcelain.archive(self.repo.path, "refs/heads/master", outstream=out,
             errstream=err)
         self.assertEquals("", err.getvalue())
@@ -102,7 +102,7 @@ class CloneTests(PorcelainTestCase):
                                         commit_spec, trees)
         self.repo.refs["refs/heads/master"] = c3.id
         target_path = tempfile.mkdtemp()
-        outstream = StringIO()
+        outstream = BytesIO()
         self.addCleanup(shutil.rmtree, target_path)
         r = porcelain.clone(self.repo.path, target_path,
                             checkout=False, outstream=outstream)
@@ -122,7 +122,7 @@ class CloneTests(PorcelainTestCase):
                                         commit_spec, trees)
         self.repo.refs["refs/heads/master"] = c3.id
         target_path = tempfile.mkdtemp()
-        outstream = StringIO()
+        outstream = BytesIO()
         self.addCleanup(shutil.rmtree, target_path)
         r = porcelain.clone(self.repo.path, target_path,
                             checkout=True, outstream=outstream)
@@ -142,7 +142,7 @@ class CloneTests(PorcelainTestCase):
                                         commit_spec, trees)
         self.repo.refs["refs/heads/master"] = c3.id
         target_path = tempfile.mkdtemp()
-        outstream = StringIO()
+        outstream = BytesIO()
         self.addCleanup(shutil.rmtree, target_path)
         r = porcelain.clone(self.repo.path, target_path,
                             bare=True, outstream=outstream)
@@ -159,7 +159,7 @@ class CloneTests(PorcelainTestCase):
         (c1, ) = build_commit_graph(self.repo.object_store, commit_spec, trees)
         self.repo.refs["refs/heads/master"] = c1.id
         target_path = tempfile.mkdtemp()
-        outstream = StringIO()
+        outstream = BytesIO()
         self.addCleanup(shutil.rmtree, target_path)
         self.assertRaises(ValueError, porcelain.clone, self.repo.path,
             target_path, checkout=True, bare=True, outstream=outstream)
@@ -225,7 +225,7 @@ class LogTests(PorcelainTestCase):
         c1, c2, c3 = build_commit_graph(self.repo.object_store, [[1], [2, 1],
             [3, 1, 2]])
         self.repo.refs["HEAD"] = c3.id
-        outstream = StringIO()
+        outstream = BytesIO()
         porcelain.log(self.repo.path, outstream=outstream)
         self.assertEquals(3, outstream.getvalue().count("-" * 50))
 
@@ -233,7 +233,7 @@ class LogTests(PorcelainTestCase):
         c1, c2, c3 = build_commit_graph(self.repo.object_store, [[1], [2, 1],
             [3, 1, 2]])
         self.repo.refs["HEAD"] = c3.id
-        outstream = StringIO()
+        outstream = BytesIO()
         porcelain.log(self.repo.path, outstream=outstream, max_entries=1)
         self.assertEquals(1, outstream.getvalue().count("-" * 50))
 
@@ -244,7 +244,7 @@ class ShowTests(PorcelainTestCase):
         c1, c2, c3 = build_commit_graph(self.repo.object_store, [[1], [2, 1],
             [3, 1, 2]])
         self.repo.refs["HEAD"] = c3.id
-        outstream = StringIO()
+        outstream = BytesIO()
         porcelain.show(self.repo.path, objects=c3.id, outstream=outstream)
         self.assertTrue(outstream.getvalue().startswith("-" * 50))
 
@@ -252,14 +252,14 @@ class ShowTests(PorcelainTestCase):
         c1, c2, c3 = build_commit_graph(self.repo.object_store, [[1], [2, 1],
             [3, 1, 2]])
         self.repo.refs["HEAD"] = c3.id
-        outstream = StringIO()
+        outstream = BytesIO()
         porcelain.show(self.repo.path, objects=[c3.id], outstream=outstream)
         self.assertTrue(outstream.getvalue().startswith("-" * 50))
 
     def test_blob(self):
         b = Blob.from_string("The Foo\n")
         self.repo.object_store.add_object(b)
-        outstream = StringIO()
+        outstream = BytesIO()
         porcelain.show(self.repo.path, objects=[b.id], outstream=outstream)
         self.assertEquals(outstream.getvalue(), "The Foo\n")
 
@@ -271,7 +271,7 @@ class SymbolicRefTests(PorcelainTestCase):
             [3, 1, 2]])
         self.repo.refs["HEAD"] = c3.id
 
-        outstream = StringIO()
+        outstream = BytesIO()
         self.assertRaises(ValueError, porcelain.symbolic_ref, self.repo.path, 'foobar')
 
     def test_set_force_wrong_symbolic_ref(self):
@@ -311,7 +311,7 @@ class DiffTreeTests(PorcelainTestCase):
         c1, c2, c3 = build_commit_graph(self.repo.object_store, [[1], [2, 1],
             [3, 1, 2]])
         self.repo.refs["HEAD"] = c3.id
-        outstream = StringIO()
+        outstream = BytesIO()
         porcelain.diff_tree(self.repo.path, c2.tree, c3.tree, outstream=outstream)
         self.assertEquals(outstream.getvalue(), "")
 
@@ -340,7 +340,7 @@ class RevListTests(PorcelainTestCase):
     def test_simple(self):
         c1, c2, c3 = build_commit_graph(self.repo.object_store, [[1], [2, 1],
             [3, 1, 2]])
-        outstream = StringIO()
+        outstream = BytesIO()
         porcelain.rev_list(
             self.repo.path, [c3.id], outstream=outstream)
         self.assertEquals(
@@ -429,8 +429,8 @@ class PushTests(PorcelainTestCase):
         clone the remote, commit a file to the clone, then push the changes
         back to the remote.
         """
-        outstream = StringIO()
-        errstream = StringIO()
+        outstream = BytesIO()
+        errstream = BytesIO()
 
         porcelain.commit(repo=self.repo.path, message='init',
             author='', committer='')
@@ -468,8 +468,8 @@ class PushTests(PorcelainTestCase):
 class PullTests(PorcelainTestCase):
 
     def test_simple(self):
-        outstream = StringIO()
-        errstream = StringIO()
+        outstream = BytesIO()
+        errstream = BytesIO()
 
         # create a file for initial commit
         handle, fullpath = tempfile.mkstemp(dir=self.repo.path)

+ 10 - 10
dulwich/tests/test_protocol.py

@@ -19,7 +19,7 @@
 """Tests for the smart protocol utility functions."""
 
 
-from StringIO import StringIO
+from io import BytesIO
 
 from dulwich.errors import (
     HangupException,
@@ -105,16 +105,16 @@ class ProtocolTests(BaseProtocolTests, TestCase):
 
     def setUp(self):
         TestCase.setUp(self)
-        self.rout = StringIO()
-        self.rin = StringIO()
+        self.rout = BytesIO()
+        self.rin = BytesIO()
         self.proto = Protocol(self.rin.read, self.rout.write)
 
 
-class ReceivableStringIO(StringIO):
-    """StringIO with socket-like recv semantics for testing."""
+class ReceivableBytesIO(BytesIO):
+    """BytesIO with socket-like recv semantics for testing."""
 
     def __init__(self):
-        StringIO.__init__(self)
+        BytesIO.__init__(self)
         self.allow_read_past_eof = False
 
     def recv(self, size):
@@ -132,8 +132,8 @@ class ReceivableProtocolTests(BaseProtocolTests, TestCase):
 
     def setUp(self):
         TestCase.setUp(self)
-        self.rout = StringIO()
-        self.rin = ReceivableStringIO()
+        self.rout = BytesIO()
+        self.rin = ReceivableBytesIO()
         self.proto = ReceivableProtocol(self.rin.recv, self.rout.write)
         self.proto._rbufsize = 8
 
@@ -186,7 +186,7 @@ class ReceivableProtocolTests(BaseProtocolTests, TestCase):
             # if we get to the end, do a non-blocking read instead of blocking
             if len(data) + i > len(all_data):
                 data += self.proto.recv(i)
-                # ReceivableStringIO leaves off the last byte unless we ask
+                # ReceivableBytesIO leaves off the last byte unless we ask
                 # nicely
                 data += self.proto.recv(1)
                 break
@@ -232,7 +232,7 @@ class BufferedPktLineWriterTests(TestCase):
 
     def setUp(self):
         TestCase.setUp(self)
-        self._output = StringIO()
+        self._output = BytesIO()
         self._writer = BufferedPktLineWriter(self._output.write, bufsize=16)
 
     def assertOutputEquals(self, expected):

+ 13 - 13
dulwich/tests/test_refs.py

@@ -19,7 +19,7 @@
 
 """Tests for dulwich.refs."""
 
-from cStringIO import StringIO
+from io import BytesIO
 import os
 import tempfile
 
@@ -90,16 +90,16 @@ class PackedRefsFileTests(TestCase):
                           '%s bad/../refname' % ONES)
 
     def test_read_without_peeled(self):
-        f = StringIO('# comment\n%s ref/1\n%s ref/2' % (ONES, TWOS))
+        f = BytesIO('# comment\n%s ref/1\n%s ref/2' % (ONES, TWOS))
         self.assertEqual([(ONES, 'ref/1'), (TWOS, 'ref/2')],
                          list(read_packed_refs(f)))
 
     def test_read_without_peeled_errors(self):
-        f = StringIO('%s ref/1\n^%s' % (ONES, TWOS))
+        f = BytesIO('%s ref/1\n^%s' % (ONES, TWOS))
         self.assertRaises(errors.PackedRefsException, list, read_packed_refs(f))
 
     def test_read_with_peeled(self):
-        f = StringIO('%s ref/1\n%s ref/2\n^%s\n%s ref/4' % (
+        f = BytesIO('%s ref/1\n%s ref/2\n^%s\n%s ref/4' % (
           ONES, TWOS, THREES, FOURS))
         self.assertEqual([
           (ONES, 'ref/1', None),
@@ -108,14 +108,14 @@ class PackedRefsFileTests(TestCase):
           ], list(read_packed_refs_with_peeled(f)))
 
     def test_read_with_peeled_errors(self):
-        f = StringIO('^%s\n%s ref/1' % (TWOS, ONES))
+        f = BytesIO('^%s\n%s ref/1' % (TWOS, ONES))
         self.assertRaises(errors.PackedRefsException, list, read_packed_refs(f))
 
-        f = StringIO('%s ref/1\n^%s\n^%s' % (ONES, TWOS, THREES))
+        f = BytesIO('%s ref/1\n^%s\n^%s' % (ONES, TWOS, THREES))
         self.assertRaises(errors.PackedRefsException, list, read_packed_refs(f))
 
     def test_write_with_peeled(self):
-        f = StringIO()
+        f = BytesIO()
         write_packed_refs(f, {'ref/1': ONES, 'ref/2': TWOS},
                           {'ref/1': THREES})
         self.assertEqual(
@@ -123,7 +123,7 @@ class PackedRefsFileTests(TestCase):
           ONES, THREES, TWOS), f.getvalue())
 
     def test_write_without_peeled(self):
-        f = StringIO()
+        f = BytesIO()
         write_packed_refs(f, {'ref/1': ONES, 'ref/2': TWOS})
         self.assertEqual("%s ref/1\n%s ref/2\n" % (ONES, TWOS), f.getvalue())
 
@@ -429,14 +429,14 @@ class InfoRefsContainerTests(TestCase):
 
     def test_invalid_refname(self):
         text = _TEST_REFS_SERIALIZED + '00' * 20 + '\trefs/stash\n'
-        refs = InfoRefsContainer(StringIO(text))
+        refs = InfoRefsContainer(BytesIO(text))
         expected_refs = dict(_TEST_REFS)
         del expected_refs['HEAD']
         expected_refs["refs/stash"] = "00" * 20
         self.assertEqual(expected_refs, refs.as_dict())
 
     def test_keys(self):
-        refs = InfoRefsContainer(StringIO(_TEST_REFS_SERIALIZED))
+        refs = InfoRefsContainer(BytesIO(_TEST_REFS_SERIALIZED))
         actual_keys = set(refs.keys())
         self.assertEqual(set(refs.allkeys()), actual_keys)
         # ignore the symref loop if it exists
@@ -454,19 +454,19 @@ class InfoRefsContainerTests(TestCase):
                          sorted(refs.keys('refs/tags')))
 
     def test_as_dict(self):
-        refs = InfoRefsContainer(StringIO(_TEST_REFS_SERIALIZED))
+        refs = InfoRefsContainer(BytesIO(_TEST_REFS_SERIALIZED))
         # refs/heads/loop does not show up even if it exists
         expected_refs = dict(_TEST_REFS)
         del expected_refs['HEAD']
         self.assertEqual(expected_refs, refs.as_dict())
 
     def test_contains(self):
-        refs = InfoRefsContainer(StringIO(_TEST_REFS_SERIALIZED))
+        refs = InfoRefsContainer(BytesIO(_TEST_REFS_SERIALIZED))
         self.assertTrue('refs/heads/master' in refs)
         self.assertFalse('refs/heads/bar' in refs)
 
     def test_get_peeled(self):
-        refs = InfoRefsContainer(StringIO(_TEST_REFS_SERIALIZED))
+        refs = InfoRefsContainer(BytesIO(_TEST_REFS_SERIALIZED))
         # refs/heads/loop does not show up even if it exists
         self.assertEqual(
             _TEST_REFS['refs/heads/master'],

+ 3 - 3
dulwich/tests/test_server.py

@@ -18,7 +18,7 @@
 
 """Tests for the smart protocol server."""
 
-from cStringIO import StringIO
+from io import BytesIO
 import os
 import tempfile
 
@@ -868,8 +868,8 @@ class ServeCommandTests(TestCase):
         commit = make_commit(id=ONE, parents=[], commit_time=111)
         self.backend.repos["/"] = MemoryRepo.init_bare(
             [commit], {"refs/heads/master": commit.id})
-        outf = StringIO()
-        exitcode = self.serve_command(ReceivePackHandler, ["/"], StringIO("0000"), outf)
+        outf = BytesIO()
+        exitcode = self.serve_command(ReceivePackHandler, ["/"], BytesIO("0000"), outf)
         outlines = outf.getvalue().splitlines()
         self.assertEqual(2, len(outlines))
         self.assertEqual("1111111111111111111111111111111111111111 refs/heads/master",

+ 10 - 10
dulwich/tests/test_web.py

@@ -18,7 +18,7 @@
 
 """Tests for the Git HTTP server."""
 
-from cStringIO import StringIO
+from io import BytesIO
 import gzip
 import re
 import os
@@ -90,7 +90,7 @@ class WebTestCase(TestCase):
                                     handlers=self._handlers())
         self._status = None
         self._headers = []
-        self._output = StringIO()
+        self._output = BytesIO()
 
     def _start_response(self, status, headers):
         self._status = status
@@ -122,7 +122,7 @@ class DumbHandlersTestCase(WebTestCase):
         self.assertEqual(HTTP_NOT_FOUND, self._status)
 
     def test_send_file(self):
-        f = StringIO('foobar')
+        f = BytesIO('foobar')
         output = ''.join(send_file(self._req, f, 'some/thing'))
         self.assertEqual('foobar', output)
         self.assertEqual(HTTP_OK, self._status)
@@ -132,7 +132,7 @@ class DumbHandlersTestCase(WebTestCase):
     def test_send_file_buffered(self):
         bufsize = 10240
         xs = 'x' * bufsize
-        f = StringIO(2 * xs)
+        f = BytesIO(2 * xs)
         self.assertEqual([xs, xs],
                           list(send_file(self._req, f, 'some/thing')))
         self.assertEqual(HTTP_OK, self._status)
@@ -311,7 +311,7 @@ class SmartHandlersTestCase(WebTestCase):
         self.assertFalse(self._req.cached)
 
     def _run_handle_service_request(self, content_length=None):
-        self._environ['wsgi.input'] = StringIO('foo')
+        self._environ['wsgi.input'] = BytesIO('foo')
         if content_length is not None:
             self._environ['CONTENT_LENGTH'] = content_length
         mat = re.search('.*', '/git-upload-pack')
@@ -342,7 +342,7 @@ class SmartHandlersTestCase(WebTestCase):
         self.assertFalse(self._req.cached)
 
     def test_get_info_refs(self):
-        self._environ['wsgi.input'] = StringIO('foo')
+        self._environ['wsgi.input'] = BytesIO('foo')
         self._environ['QUERY_STRING'] = 'service=git-upload-pack'
 
         mat = re.search('.*', '/git-upload-pack')
@@ -361,16 +361,16 @@ class SmartHandlersTestCase(WebTestCase):
 
 class LengthLimitedFileTestCase(TestCase):
     def test_no_cutoff(self):
-        f = _LengthLimitedFile(StringIO('foobar'), 1024)
+        f = _LengthLimitedFile(BytesIO('foobar'), 1024)
         self.assertEqual('foobar', f.read())
 
     def test_cutoff(self):
-        f = _LengthLimitedFile(StringIO('foobar'), 3)
+        f = _LengthLimitedFile(BytesIO('foobar'), 3)
         self.assertEqual('foo', f.read())
         self.assertEqual('', f.read())
 
     def test_multiple_reads(self):
-        f = _LengthLimitedFile(StringIO('foobar'), 3)
+        f = _LengthLimitedFile(BytesIO('foobar'), 3)
         self.assertEqual('fo', f.read(2))
         self.assertEqual('o', f.read(2))
         self.assertEqual('', f.read())
@@ -466,7 +466,7 @@ class GunzipTestCase(HTTPGitApplicationTestCase):
         self._environ['REQUEST_METHOD'] = 'POST'
 
     def _get_zstream(self, text):
-        zstream = StringIO()
+        zstream = BytesIO()
         zfile = gzip.GzipFile(fileobj=zstream, mode='w')
         zfile.write(text)
         zfile.close()

+ 2 - 2
dulwich/web.py

@@ -19,7 +19,7 @@
 
 """HTTP server for dulwich that implements the git smart HTTP protocol."""
 
-from cStringIO import StringIO
+from io import BytesIO
 import shutil
 import tempfile
 import gzip
@@ -170,7 +170,7 @@ def get_info_refs(req, backend, mat):
             return
         req.nocache()
         write = req.respond(HTTP_OK, 'application/x-%s-advertisement' % service)
-        proto = ReceivableProtocol(StringIO().read, write)
+        proto = ReceivableProtocol(BytesIO().read, write)
         handler = handler_cls(backend, [url_prefix(mat)], proto,
                               http_req=req, advertise_refs=True)
         handler.proto.write_pkt_line('# service=%s\n' % service)