Browse Source

New upstream version 0.17.3

Jelmer Vernooij 7 years ago
parent
commit
50aa77c9d5

+ 27 - 25
.travis.yml

@@ -1,36 +1,38 @@
 language: python
 sudo: false
+cache: pip
+
+python:
+  - 2.7
+  - 3.3
+  - 3.4
+  - 3.5
+  - 3.5-dev
+  - 3.6
+  - 3.6-dev
+  - 3.7-dev
+  - pypy3.3-5.2-alpha1
+
 env:
-  global: TEST_RUNNER=unittest PYTHONHASHSEED=random
+  - PYTHONHASHSEED=random
+    TEST_REQUIRE="gevent greenlet geventhttpclient fastimport"
+
 matrix:
   include:
-    - python: "2.7"
-      env: TEST_REQUIRE="gevent greenlet geventhttpclient fastimport"
-    - python: "pypy"
-      env: TEST_REQUIRE="fastimport"
-    - python: "3.4"
-      env: TEST_REQUIRE="gevent greenlet geventhttpclient fastimport"
-    - python: "3.5"
-      env: TEST_REQUIRE="gevent greenlet geventhttpclient fastimport"
-    - python: "3.5-dev"
-      env: TEST_REQUIRE="gevent greenlet geventhttpclient fastimport"
-    - python: "3.6"
-      env: TEST_REQUIRE="gevent greenlet geventhttpclient fastimport"
-    - python: "3.6-dev"
-      env: TEST_REQUIRE="gevent greenlet geventhttpclient fastimport"
-    - python: "3.7-dev"
-      env: TEST_REQUIRE="gevent greenlet geventhttpclient fastimport"
-cache:
-  directories:
-    - $HOME/.cache/pip
-script:
-  - pip install pip --upgrade
-  - pip install $TEST_REQUIRE
+    - python: pypy
+      env: TEST_REQUIRE=fastimport
+
+install:
+  - travis_retry pip install -U pip coverage codecov $TEST_REQUIRE
 
+script:
   # Test without c extensions
-  - python -m $TEST_RUNNER dulwich.tests.test_suite
+  - python -m coverage run -p --source=dulwich -m unittest dulwich.tests.test_suite
 
   # Test with c extensions
   - python setup.py build_ext -i
-  - python -m $TEST_RUNNER dulwich.tests.test_suite
+  - python -m coverage run -p --source=dulwich -m unittest dulwich.tests.test_suite
 
+after_success:
+  - python -m coverage combine
+  - codecov

+ 21 - 0
NEWS

@@ -1,3 +1,24 @@
+0.17.3	2017-03-20
+
+ PLATFORM SUPPORT
+
+  * List Python 3.3 as supported. (Jelmer Vernooij, #513)
+
+ BUG FIXES
+
+  * Fix compatibility with pypy 3. (Jelmer Vernooij)
+
+0.17.2	2017-03-19
+
+ BUG FIXES
+
+ * Add workaround for
+   https://bitbucket.org/pypy/pypy/issues/2499/cpyext-pystring_asstring-doesnt-work,
+   fixing Dulwich when used with C extensions on pypy < 5.6. (Victor Stinner)
+
+ * Properly quote config values with a '#' character in them.
+   (Jelmer Vernooij, #511)
+
 0.17.1	2017-03-01
 
  IMPROVEMENTS

+ 3 - 1
PKG-INFO

@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: dulwich
-Version: 0.17.1
+Version: 0.17.3
 Summary: Python Git Library
 Home-page: https://www.dulwich.io/
 Author: Jelmer Vernooij
@@ -21,8 +21,10 @@ Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
 Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Operating System :: POSIX

+ 1 - 1
README.md

@@ -47,4 +47,4 @@ mailing lists.
 Supported versions of Python
 ----------------------------
 
-At the moment, Dulwich supports (and is tested on) CPython 2.7, 3.4, 3.5 and Pypy.
+At the moment, Dulwich supports (and is tested on) CPython 2.7, 3.3, 3.4, 3.5, 3.6 and Pypy.

+ 3 - 1
dulwich.egg-info/PKG-INFO

@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: dulwich
-Version: 0.17.1
+Version: 0.17.3
 Summary: Python Git Library
 Home-page: https://www.dulwich.io/
 Author: Jelmer Vernooij
@@ -21,8 +21,10 @@ Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
 Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Operating System :: POSIX

+ 1 - 1
dulwich/__init__.py

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

+ 0 - 1
dulwich/_diff_tree.c

@@ -38,7 +38,6 @@ typedef int Py_ssize_t;
 #define PyInt_AsLong PyLong_AsLong
 #define PyInt_AS_LONG PyLong_AS_LONG
 #define PyString_AS_STRING PyBytes_AS_STRING
-#define PyString_AsString PyBytes_AsString
 #define PyString_AsStringAndSize PyBytes_AsStringAndSize
 #define PyString_Check PyBytes_Check
 #define PyString_CheckExact PyBytes_CheckExact

+ 3 - 3
dulwich/_pack.c

@@ -24,7 +24,7 @@
 #if PY_MAJOR_VERSION >= 3
 #define PyInt_FromLong PyLong_FromLong
 #define PyString_AS_STRING PyBytes_AS_STRING
-#define PyString_AsString PyBytes_AsString
+#define PyString_AS_STRING PyBytes_AS_STRING
 #define PyString_Check PyBytes_Check
 #define PyString_CheckExact PyBytes_CheckExact
 #define PyString_FromStringAndSize PyBytes_FromStringAndSize
@@ -133,7 +133,7 @@ static PyObject *py_apply_delta(PyObject *self, PyObject *args)
 		Py_DECREF(py_delta);
 		return NULL;
 	}
-	out = (uint8_t *)PyString_AsString(ret);
+	out = (uint8_t *)PyString_AS_STRING(ret);
 	while (index < delta_len) {
 		uint8_t cmd = delta[index];
 		index++;
@@ -238,7 +238,7 @@ static PyObject *py_bisect_find_sha(PyObject *self, PyObject *args)
 			Py_DECREF(file_sha);
 			return NULL;
 		}
-		cmp = memcmp(PyString_AsString(file_sha), sha, 20);
+		cmp = memcmp(PyString_AS_STRING(file_sha), sha, 20);
 		Py_DECREF(file_sha);
 		if (cmp < 0)
 			start = i + 1;

+ 2 - 1
dulwich/config.py

@@ -174,6 +174,7 @@ def _format_string(value):
     if (value.startswith(b" ") or
         value.startswith(b"\t") or
         value.endswith(b" ") or
+        b'#' in value or
         value.endswith(b"\t")):
         return b'"' + _escape_value(value) + b'"'
     return _escape_value(value)
@@ -365,7 +366,7 @@ class ConfigFile(ConfigDict):
                 elif value is False:
                     value = b"false"
                 else:
-                    value = _escape_value(value)
+                    value = _format_string(value)
                 f.write(b"\t" + key + b" = " + value + b"\n")
 
 

+ 5 - 1
dulwich/contrib/swift.py

@@ -172,7 +172,11 @@ def load_conf(path=None, file=None):
     """
     conf = ConfigParser()
     if file:
-        conf.readfp(file)
+        try:
+            conf.read_file(file, path)
+        except AttributeError:
+            # read_file only exists in Python3
+            conf.readfp(file)
         return conf
     confpath = None
     if not path:

+ 2 - 2
dulwich/objects.py

@@ -1126,8 +1126,8 @@ class Commit(ShaFile):
     __slots__ = ('_parents', '_encoding', '_extra', '_author_timezone_neg_utc',
                  '_commit_timezone_neg_utc', '_commit_time',
                  '_author_time', '_author_timezone', '_commit_timezone',
-                 '_author', '_committer', '_parents', '_extra',
-                 '_encoding', '_tree', '_message', '_mergetag', '_gpgsig')
+                 '_author', '_committer', '_tree', '_message',
+                 '_mergetag', '_gpgsig')
 
     def __init__(self):
         super(Commit, self).__init__()

+ 7 - 0
dulwich/tests/test_config.py

@@ -173,6 +173,13 @@ who\"
         self.assertEqual(ConfigFile({(b'alias', ): {
             b'who': b"!who() {git log --no-merges --pretty=format:'%an - %ae' $@ | sort | uniq -c | sort -rn;};who"}}), cf)
 
+    def test_set_hash_gets_quoted(self):
+        c = ConfigFile()
+        c.set(b"xandikos", b"color", b"#665544")
+        f = BytesIO()
+        c.write_to_file(f)
+        self.assertEqual(b"[xandikos]\n\tcolor = \"#665544\"\n", f.getvalue())
+
 
 class ConfigDictTests(TestCase):
 

+ 30 - 0
dulwich/tests/test_pack.py

@@ -198,6 +198,36 @@ class TestPackDeltas(TestCase):
             ApplyDeltaError,
             apply_delta, b'', b'\x00\x80\x02\xb0\x11\x11')
 
+    def test_pypy_issue(self):
+        # Test for https://github.com/jelmer/dulwich/issues/509 /
+        # https://bitbucket.org/pypy/pypy/issues/2499/cpyext-pystring_asstring-doesnt-work
+        chunks = [
+            b'tree 03207ccf58880a748188836155ceed72f03d65d6\n'
+            b'parent 408fbab530fd4abe49249a636a10f10f44d07a21\n'
+            b'author Victor Stinner <victor.stinner@gmail.com> 1421355207 +0100\n'
+            b'committer Victor Stinner <victor.stinner@gmail.com> 1421355207 +0100\n'
+            b'\n'
+            b'Backout changeset 3a06020af8cf\n'
+            b'\nStreamWriter: close() now clears the reference to the transport\n'
+            b'\nStreamWriter now raises an exception if it is closed: write(), writelines(),\n'
+            b'write_eof(), can_write_eof(), get_extra_info(), drain().\n']
+        delta = [
+            b'\xcd\x03\xad\x03]tree ff3c181a393d5a7270cddc01ea863818a8621ca8\n'
+            b'parent 20a103cc90135494162e819f98d0edfc1f1fba6b\x91]7\x0510738'
+            b'\x91\x99@\x0b10738 +0100\x93\x04\x01\xc9']
+        res = apply_delta(chunks, delta)
+        expected = [
+            b'tree ff3c181a393d5a7270cddc01ea863818a8621ca8\n'
+            b'parent 20a103cc90135494162e819f98d0edfc1f1fba6b',
+            b'\nauthor Victor Stinner <victor.stinner@gmail.com> 14213',
+            b'10738',
+            b' +0100\ncommitter Victor Stinner <victor.stinner@gmail.com> 14213',
+            b'10738 +0100',
+            b'\n\nStreamWriter: close() now clears the reference to the transport\n\n'
+            b'StreamWriter now raises an exception if it is closed: write(), writelines(),\n'
+            b'write_eof(), can_write_eof(), get_extra_info(), drain().\n']
+        self.assertEqual(b''.join(expected), b''.join(res))
+
 
 class TestPackData(PackTests):
     """Tests getting the data from the packfile."""

+ 18 - 6
dulwich/tests/test_repository.py

@@ -401,8 +401,9 @@ exit 0
 """
 
         repo_dir = os.path.join(self.mkdtemp())
-        r = Repo.init(repo_dir)
         self.addCleanup(shutil.rmtree, repo_dir)
+        r = Repo.init(repo_dir)
+        self.addCleanup(r.close)
 
         pre_commit = os.path.join(r.controldir(), 'hooks', 'pre-commit')
 
@@ -441,8 +442,9 @@ exit 0
 """
 
         repo_dir = self.mkdtemp()
-        r = Repo.init(repo_dir)
         self.addCleanup(shutil.rmtree, repo_dir)
+        r = Repo.init(repo_dir)
+        self.addCleanup(r.close)
 
         commit_msg = os.path.join(r.controldir(), 'hooks', 'commit-msg')
 
@@ -473,9 +475,10 @@ exit 0
             self.skipTest('shell hook tests requires POSIX shell')
 
         repo_dir = self.mkdtemp()
+        self.addCleanup(shutil.rmtree, repo_dir)
 
         r = Repo.init(repo_dir)
-        self.addCleanup(shutil.rmtree, repo_dir)
+        self.addCleanup(r.close)
 
         (fd, path) = tempfile.mkstemp(dir=repo_dir)
         os.close(fd)
@@ -525,9 +528,16 @@ exit 1
             author=b'Test Author <test@nodomain.com>',
             commit_timestamp=12345, commit_timezone=0,
             author_timestamp=12345, author_timezone=0)
-        self.assertEqual(len(warnings_list), 1, warnings_list)
-        self.assertIsInstance(warnings_list[-1], UserWarning)
-        self.assertTrue("post-commit hook failed: " in str(warnings_list[-1]))
+        expected_warning = UserWarning(
+            'post-commit hook failed: Hook post-commit exited with '
+            'non-zero status',)
+        for w in warnings_list:
+            if (type(w) == type(expected_warning) and
+                    w.args == expected_warning.args):
+                break
+        else:
+            raise AssertionError('Expected warning %r not in %r' %
+                    (expected_warning, warnings_list))
         self.assertEqual([commit_sha], r[commit_sha2].parents)
 
     def test_as_dict(self):
@@ -549,6 +559,7 @@ exit 1
         worktree_temp_dir = tempfile.mkdtemp()
         self.addCleanup(shutil.rmtree, worktree_temp_dir)
         r = Repo.init(temp_dir)
+        self.addCleanup(r.close)
         root_sha = r.do_commit(
                 b'empty commit',
                 committer=b'Test Committer <test@nodomain.com>',
@@ -557,6 +568,7 @@ exit 1
                 author_timestamp=12345, author_timezone=0)
         r.refs[b'refs/heads/master'] = root_sha
         w = Repo._init_new_working_directory(worktree_temp_dir, r)
+        self.addCleanup(w.close)
         new_sha = w.do_commit(
                 b'new commit',
                 committer=b'Test Committer <test@nodomain.com>',

+ 3 - 1
setup.py

@@ -9,7 +9,7 @@ except ImportError:
     from distutils.core import setup, Extension
 from distutils.core import Distribution
 
-dulwich_version_string = '0.17.1'
+dulwich_version_string = '0.17.3'
 
 include_dirs = []
 # Windows MSVC support
@@ -91,8 +91,10 @@ setup(name='dulwich',
           'Development Status :: 4 - Beta',
           'License :: OSI Approved :: Apache Software License',
           'Programming Language :: Python :: 2.7',
+          'Programming Language :: Python :: 3.3',
           'Programming Language :: Python :: 3.4',
           'Programming Language :: Python :: 3.5',
+          'Programming Language :: Python :: 3.6',
           'Programming Language :: Python :: Implementation :: CPython',
           'Programming Language :: Python :: Implementation :: PyPy',
           'Operating System :: POSIX',

+ 1 - 1
tox.ini

@@ -1,6 +1,6 @@
 [tox]
 downloadcache = {toxworkdir}/cache/
-envlist = py27, pypy, py27-noext, pypy-noext, py34, py34-noext, py35, py35-noext, py36, py36-noext
+envlist = py27, pypy, py27-noext, pypy-noext, py33, py33-noext, py34, py34-noext, py35, py35-noext, py36, py36-noext
 
 [testenv]