Browse Source

Drop support for Python 2.

Jelmer Vernooij 5 years ago
parent
commit
20246a9e85

+ 2 - 4
.travis.yml

@@ -4,10 +4,10 @@ cache: pip
 
 
 python:
-  - 2.7
-  - 3.4
   - 3.5
   - 3.6
+  - 3.7
+  - 3.8
   - pypy3.5
 
 env:
@@ -33,8 +33,6 @@ matrix:
       sudo: true
     - python: 3.6
       env: PURE=true
-    - python: 2.7
-      env: PURE=true
 
 install:
   - travis_retry pip install -U pip coverage codecov flake8 $TEST_REQUIRE

+ 4 - 0
NEWS

@@ -1,3 +1,7 @@
+0.20.0	UNRELEASED
+
+ * Drop support for Python 2. (Jelmer Vernooij)
+
 0.19.17	UNRELEASED
 
  * Don't break when encountering block devices.

+ 2 - 2
README.rst

@@ -93,5 +93,5 @@ file and `list of open issues <https://github.com/dulwich/dulwich/issues>`_.
 Supported versions of Python
 ----------------------------
 
-At the moment, Dulwich supports (and is tested on) CPython 2.7, 3.4, 3.5, 3.6,
-3.7 and PyPy.
+At the moment, Dulwich supports (and is tested on) CPython 3.5, 3.6,
+3.7, 3.8 and Pypy.

+ 1 - 1
dulwich/__init__.py

@@ -22,4 +22,4 @@
 
 """Python implementation of the Git file formats and protocols."""
 
-__version__ = (0, 19, 17)
+__version__ = (0, 20, 0)

+ 1 - 4
dulwich/client.py

@@ -1025,10 +1025,7 @@ class SubprocessWrapper(object):
 
     def __init__(self, proc):
         self.proc = proc
-        if sys.version_info[0] == 2:
-            self.read = proc.stdout.read
-        else:
-            self.read = BufferedReader(proc.stdout).read
+        self.read = BufferedReader(proc.stdout).read
         self.write = proc.stdin.write
 
     @property

+ 0 - 172
dulwich/contrib/test_swift.py

@@ -52,9 +52,6 @@ from dulwich.objects import (
     )
 from dulwich.pack import (
     REF_DELTA,
-    write_pack_index_v2,
-    PackData,
-    load_pack_index_file,
     )
 
 try:
@@ -81,8 +78,6 @@ except ImportError:
 
 skipmsg = "Required libraries are not installed (%r)" % missing_libs
 
-skipIfPY3 = skipIf(sys.version_info[0] == 3,
-                   "SWIFT module not yet ported to python3.")
 
 if not missing_libs:
     from dulwich.contrib import swift
@@ -259,128 +254,6 @@ class FakeSwiftConnector(object):
         return {'content-length': len(self.store[name])}
 
 
-@skipIf(missing_libs, skipmsg)
-@skipIfPY3
-class TestSwiftObjectStore(TestCase):
-
-    def setUp(self):
-        super(TestSwiftObjectStore, self).setUp()
-        self.conf = swift.load_conf(file=StringIO(config_file %
-                                                  def_config_file))
-        self.fsc = FakeSwiftConnector('fakerepo', conf=self.conf)
-
-    def _put_pack(self, sos, commit_amount=1, marker='Default'):
-        odata = create_commits(length=commit_amount, marker=marker)
-        data = [(d.type_num, d.as_raw_string()) for d in odata]
-        f = BytesIO()
-        build_pack(f, data, store=sos)
-        sos.add_thin_pack(f.read, None)
-        return odata
-
-    def test_load_packs(self):
-        store = {'fakerepo/objects/pack/pack-'+'1'*40+'.idx': '',
-                 'fakerepo/objects/pack/pack-'+'1'*40+'.pack': '',
-                 'fakerepo/objects/pack/pack-'+'1'*40+'.info': '',
-                 'fakerepo/objects/pack/pack-'+'2'*40+'.idx': '',
-                 'fakerepo/objects/pack/pack-'+'2'*40+'.pack': '',
-                 'fakerepo/objects/pack/pack-'+'2'*40+'.info': ''}
-        fsc = FakeSwiftConnector('fakerepo', conf=self.conf, store=store)
-        sos = swift.SwiftObjectStore(fsc)
-        packs = sos.packs
-        self.assertEqual(len(packs), 2)
-        for pack in packs:
-            self.assertTrue(isinstance(pack, swift.SwiftPack))
-
-    def test_add_thin_pack(self):
-        sos = swift.SwiftObjectStore(self.fsc)
-        self._put_pack(sos, 1, 'Default')
-        self.assertEqual(len(self.fsc.store), 3)
-
-    def test_find_missing_objects(self):
-        commit_amount = 3
-        sos = swift.SwiftObjectStore(self.fsc)
-        odata = self._put_pack(sos, commit_amount, 'Default')
-        head = odata[-1].id
-        i = sos.iter_shas(sos.find_missing_objects([],
-                                                   [head, ],
-                                                   progress=None,
-                                                   get_tagged=None))
-        self.assertEqual(len(i), commit_amount * 3)
-        shas = [d.id for d in odata]
-        for sha, path in i:
-            self.assertIn(sha.id, shas)
-
-    def test_find_missing_objects_with_tag(self):
-        commit_amount = 3
-        sos = swift.SwiftObjectStore(self.fsc)
-        odata = self._put_pack(sos, commit_amount, 'Default')
-        head = odata[-1].id
-        peeled_sha = dict([(sha.object[1], sha.id)
-                           for sha in odata if isinstance(sha, Tag)])
-
-        def get_tagged():
-            return peeled_sha
-        i = sos.iter_shas(sos.find_missing_objects([],
-                                                   [head, ],
-                                                   progress=None,
-                                                   get_tagged=get_tagged))
-        self.assertEqual(len(i), commit_amount * 4)
-        shas = [d.id for d in odata]
-        for sha, path in i:
-            self.assertIn(sha.id, shas)
-
-    def test_find_missing_objects_with_common(self):
-        commit_amount = 3
-        sos = swift.SwiftObjectStore(self.fsc)
-        odata = self._put_pack(sos, commit_amount, 'Default')
-        head = odata[-1].id
-        have = odata[7].id
-        i = sos.iter_shas(sos.find_missing_objects([have, ],
-                                                   [head, ],
-                                                   progress=None,
-                                                   get_tagged=None))
-        self.assertEqual(len(i), 3)
-
-    def test_find_missing_objects_multiple_packs(self):
-        sos = swift.SwiftObjectStore(self.fsc)
-        commit_amount_a = 3
-        odataa = self._put_pack(sos, commit_amount_a, 'Default1')
-        heada = odataa[-1].id
-        commit_amount_b = 2
-        odatab = self._put_pack(sos, commit_amount_b, 'Default2')
-        headb = odatab[-1].id
-        i = sos.iter_shas(sos.find_missing_objects([],
-                                                   [heada, headb],
-                                                   progress=None,
-                                                   get_tagged=None))
-        self.assertEqual(len(self.fsc.store), 6)
-        self.assertEqual(len(i),
-                         commit_amount_a * 3 +
-                         commit_amount_b * 3)
-        shas = [d.id for d in odataa]
-        shas.extend([d.id for d in odatab])
-        for sha, path in i:
-            self.assertIn(sha.id, shas)
-
-    def test_add_thin_pack_ext_ref(self):
-        sos = swift.SwiftObjectStore(self.fsc)
-        odata = self._put_pack(sos, 1, 'Default1')
-        ref_blob_content = odata[0].as_raw_string()
-        ref_blob_id = odata[0].id
-        new_blob = Blob.from_string(ref_blob_content.replace('blob',
-                                                             'yummy blob'))
-        blob, tree, tag, cmt = \
-            create_commit([], marker='Default2', blob=new_blob)
-        data = [(REF_DELTA, (ref_blob_id, blob.as_raw_string())),
-                (tree.type_num, tree.as_raw_string()),
-                (cmt.type_num, cmt.as_raw_string()),
-                (tag.type_num, tag.as_raw_string())]
-        f = BytesIO()
-        build_pack(f, data, store=sos)
-        sos.add_thin_pack(f.read, None)
-        self.assertEqual(len(self.fsc.store), 6)
-
-
 @skipIf(missing_libs, skipmsg)
 class TestSwiftRepo(TestCase):
 
@@ -432,51 +305,6 @@ class TestSwiftRepo(TestCase):
         self.assertIn('fakeroot/description', fsc.store)
 
 
-@skipIf(missing_libs, skipmsg)
-@skipIfPY3
-class TestPackInfoLoadDump(TestCase):
-
-    def setUp(self):
-        super(TestPackInfoLoadDump, self).setUp()
-        conf = swift.load_conf(file=StringIO(config_file %
-                                             def_config_file))
-        sos = swift.SwiftObjectStore(
-            FakeSwiftConnector('fakerepo', conf=conf))
-        commit_amount = 10
-        self.commits = create_commits(length=commit_amount, marker="m")
-        data = [(d.type_num, d.as_raw_string()) for d in self.commits]
-        f = BytesIO()
-        fi = BytesIO()
-        expected = build_pack(f, data, store=sos)
-        entries = [(sha, ofs, checksum) for
-                   ofs, _, _, sha, checksum in expected]
-        self.pack_data = PackData.from_file(file=f, size=None)
-        write_pack_index_v2(
-            fi, entries, self.pack_data.calculate_checksum())
-        fi.seek(0)
-        self.pack_index = load_pack_index_file('', fi)
-
-#    def test_pack_info_perf(self):
-#        dump_time = []
-#        load_time = []
-#        for i in range(0, 100):
-#            start = time()
-#            dumps = swift.pack_info_create(self.pack_data, self.pack_index)
-#            dump_time.append(time() - start)
-#        for i in range(0, 100):
-#            start = time()
-#            pack_infos = swift.load_pack_info('', file=BytesIO(dumps))
-#            load_time.append(time() - start)
-#        print sum(dump_time) / float(len(dump_time))
-#        print sum(load_time) / float(len(load_time))
-
-    def test_pack_info(self):
-        dumps = swift.pack_info_create(self.pack_data, self.pack_index)
-        pack_infos = swift.load_pack_info('', file=BytesIO(dumps))
-        for obj in self.commits:
-            self.assertIn(obj.id, pack_infos)
-
-
 @skipIf(missing_libs, skipmsg)
 class TestSwiftInfoRefsContainer(TestCase):
 

+ 1 - 2
dulwich/diff_tree.py

@@ -315,8 +315,7 @@ def _count_blocks(obj):
     block_getvalue = block.getvalue
 
     for c in chain(*obj.as_raw_chunks()):
-        if sys.version_info[0] == 3:
-            c = c.to_bytes(1, 'big')
+        c = c.to_bytes(1, 'big')
         block_write(c)
         n += 1
         if c == b'\n' or n == _BLOCK_SIZE:

+ 0 - 4
dulwich/fastexport.py

@@ -32,10 +32,6 @@ from dulwich.objects import (
     Tag,
     ZERO_SHA,
     )
-from fastimport import __version__ as fastimport_version
-if (fastimport_version <= (0, 9, 5) and
-        sys.version_info[0] == 3 and sys.version_info[1] < 5):
-    raise ImportError("Older versions of fastimport don't support python3<3.5")
 from fastimport import (  # noqa: E402
     commands,
     errors as fastimport_errors,

+ 0 - 5
dulwich/hooks.py

@@ -82,11 +82,6 @@ class ShellHook(Hook):
 
         self.cwd = cwd
 
-        if sys.version_info[0] == 2 and sys.platform == 'win32':
-            # Python 2 on windows does not support unicode file paths
-            # http://bugs.python.org/issue1759845
-            self.filepath = self.filepath.encode(sys.getfilesystemencoding())
-
     def execute(self, *args):
         """Execute the hook with given args"""
 

+ 1 - 1
dulwich/index.py

@@ -477,7 +477,7 @@ def build_file_from_blob(blob, mode, target_path, honor_filemode=True):
         # FIXME: This will fail on Windows. What should we do instead?
         if oldstat:
             os.unlink(target_path)
-        if sys.platform == 'win32' and sys.version_info[0] == 3:
+        if sys.platform == 'win32':
             # os.readlink on Python3 on Windows requires a unicode string.
             # TODO(jelmer): Don't assume tree_encoding == fs_encoding
             tree_encoding = sys.getfilesystemencoding()

+ 3 - 8
dulwich/objects.py

@@ -322,14 +322,9 @@ class ShaFile(object):
         """
         return b''.join(self.as_raw_chunks())
 
-    if sys.version_info[0] >= 3:
-        def __bytes__(self):
-            """Return raw string serialization of this object."""
-            return self.as_raw_string()
-    else:
-        def __str__(self):
-            """Return raw string serialization of this object."""
-            return self.as_raw_string()
+    def __bytes__(self):
+        """Return raw string serialization of this object."""
+        return self.as_raw_string()
 
     def __hash__(self):
         """Return unique hash for this object."""

+ 4 - 8
dulwich/porcelain.py

@@ -156,14 +156,10 @@ class NoneStream(RawIOBase):
         return None
 
 
-if sys.version_info[0] == 2:
-    default_bytes_out_stream = sys.stdout or NoneStream()
-    default_bytes_err_stream = sys.stderr or NoneStream()
-else:
-    default_bytes_out_stream = (
-        getattr(sys.stdout, 'buffer', None) or NoneStream())
-    default_bytes_err_stream = (
-        getattr(sys.stderr, 'buffer', None) or NoneStream())
+default_bytes_out_stream = (
+    getattr(sys.stdout, 'buffer', None) or NoneStream())
+default_bytes_err_stream = (
+    getattr(sys.stderr, 'buffer', None) or NoneStream())
 
 
 DEFAULT_ENCODING = 'utf-8'

+ 1 - 1
dulwich/tests/test_repository.py

@@ -1090,7 +1090,7 @@ class BuildRepoRootTests(TestCase):
         r.stage(['c'])
         self.assertEqual([b'a'], list(r.open_index()))
 
-    @skipIf(sys.platform == 'win32' and sys.version_info[:2] >= (3, 6),
+    @skipIf(sys.platform == 'win32',
             'tries to implicitly decode as utf8')
     def test_commit_no_encode_decode(self):
         r = self._repo

+ 2 - 5
dulwich/web.py

@@ -443,11 +443,8 @@ class ServerHandlerLogger(ServerHandler):
     """ServerHandler that uses dulwich's logger for logging exceptions."""
 
     def log_exception(self, exc_info):
-        if sys.version_info < (2, 7):
-            logger.exception('Exception happened during processing of request')
-        else:
-            logger.exception('Exception happened during processing of request',
-                             exc_info=exc_info)
+        logger.exception('Exception happened during processing of request',
+                         exc_info=exc_info)
 
     def log_message(self, format, *args):
         logger.info(format, *args)

+ 4 - 14
setup.py

@@ -15,13 +15,7 @@ import io
 import os
 import sys
 
-dulwich_version_string = '0.19.17'
-
-include_dirs = []
-# Windows MSVC support
-if sys.platform == 'win32' and sys.version_info[:2] < (3, 6):
-    # Include dulwich/ for fallback stdint.h
-    include_dirs.append('dulwich')
+dulwich_version_string = '0.20.0'
 
 
 class DulwichDistribution(Distribution):
@@ -64,12 +58,9 @@ if '__pypy__' not in sys.modules and not sys.platform == 'win32':
 
 
 ext_modules = [
-    Extension('dulwich._objects', ['dulwich/_objects.c'],
-              include_dirs=include_dirs),
-    Extension('dulwich._pack', ['dulwich/_pack.c'],
-              include_dirs=include_dirs),
-    Extension('dulwich._diff_tree', ['dulwich/_diff_tree.c'],
-              include_dirs=include_dirs),
+    Extension('dulwich._objects', ['dulwich/_objects.c']),
+    Extension('dulwich._pack', ['dulwich/_pack.c']),
+    Extension('dulwich._diff_tree', ['dulwich/_diff_tree.c']),
 ]
 
 setup_kwargs = {}
@@ -112,7 +103,6 @@ setup(name='dulwich',
       classifiers=[
           'Development Status :: 4 - Beta',
           'License :: OSI Approved :: Apache Software License',
-          'Programming Language :: Python :: 2.7',
           'Programming Language :: Python :: 3.4',
           'Programming Language :: Python :: 3.5',
           'Programming Language :: Python :: 3.6',

+ 6 - 6
tox.ini

@@ -1,6 +1,6 @@
 [tox]
 downloadcache = {toxworkdir}/cache/
-envlist = py27, pypy, py27-noext, pypy-noext, py33, py33-noext, py34, py34-noext, py35, py35-noext, py36, py36-noext
+envlist = pypy, pypy-noext, py35, py35-noext, py36, py36-noext, py37, py37-noext, py38, py38-noext
 
 [testenv]
 
@@ -8,17 +8,17 @@ commands = make check
 recreate = True
 whitelist_externals = make
 
-[testenv:py27-noext]
+[testenv:pypy-noext]
 commands = make check-noextensions
 
-[testenv:pypy-noext]
+[testenv:py35-noext]
 commands = make check-noextensions
 
-[testenv:py34-noext]
+[testenv:py36-noext]
 commands = make check-noextensions
 
-[testenv:py35-noext]
+[testenv:py37-noext]
 commands = make check-noextensions
 
-[testenv:py36-noext]
+[testenv:py38-noext]
 commands = make check-noextensions