diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2015-01-05 17:59:22 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2015-01-05 17:59:22 +0100 |
commit | e1060a2a8c90c0730c3541811df8f906dac510a7 (patch) | |
tree | 1c29ef00a756be7e88aeb43cfa847dbf2e6f3079 | |
parent | 8a308613467a1510f8dac514624abae4e10c0779 (diff) | |
download | gitpython-e1060a2a8c90c0730c3541811df8f906dac510a7.tar.gz |
test_commit works once again
-rw-r--r-- | doc/source/changes.rst | 1 | ||||
-rw-r--r-- | git/cmd.py | 7 | ||||
-rw-r--r-- | git/config.py | 7 | ||||
-rw-r--r-- | git/diff.py | 2 | ||||
-rw-r--r-- | git/objects/base.py | 7 | ||||
-rw-r--r-- | git/objects/commit.py | 4 | ||||
-rw-r--r-- | git/objects/fun.py | 3 | ||||
-rw-r--r-- | git/refs/symbolic.py | 2 | ||||
-rw-r--r-- | git/repo/base.py | 17 | ||||
-rw-r--r-- | git/test/test_commit.py | 44 |
10 files changed, 55 insertions, 39 deletions
diff --git a/doc/source/changes.rst b/doc/source/changes.rst index cf528b28..06a73f41 100644 --- a/doc/source/changes.rst +++ b/doc/source/changes.rst @@ -5,6 +5,7 @@ Changelog 0.3.4 - python 3 support ======================== * Internally, hexadecimal SHA1 are treated as ascii encoded strings. Binary SHA1 are treated as bytes. +* Id attribute of Commit objects is now `hexsha`, instead of `binsha`. The latter makes no sense in python 3 and I see no application of it anyway besides its artificial usage in test cases. 0.3.3 ===== @@ -320,6 +320,7 @@ class Git(LazyMixin): always be created with a pipe due to issues with subprocess. This merely is a workaround as data will be copied from the output pipe to the given output stream directly. + Judging from the implementation, you shouldn't use this flag ! :param subprocess_kwargs: Keyword arguments to be passed to subprocess.Popen. Please note that @@ -411,9 +412,13 @@ class Git(LazyMixin): else: raise GitCommandError(command, status, stderr_value) + + if isinstance(stdout_value, bytes): # could also be output_stream + stdout_value = stdout_value.decode(defenc) + # Allow access to the command's status code if with_extended_output: - return (status, stdout_value, stderr_value) + return (status, stdout_value, stderr_value.decode(defenc)) else: return stdout_value diff --git a/git/config.py b/git/config.py index 988547a0..7917bc5a 100644 --- a/git/config.py +++ b/git/config.py @@ -201,6 +201,11 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, obje self.write() except IOError: log.error("Exception during destruction of GitConfigParser", exc_info=True) + except ReferenceError: + # This happens in PY3 ... and usually means that some state cannot be written + # as the sections dict cannot be iterated + # Usually when shutting down the interpreter, don'y know how to fix this + pass finally: self._lock._release_lock() @@ -345,7 +350,7 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, obje # END get lock for physical files if not hasattr(fp, "seek"): - fp = open(self._file_or_files, "w") + fp = open(self._file_or_files, "wb") close_fp = True else: fp.seek(0) diff --git a/git/diff.py b/git/diff.py index b3e7245b..1692d83e 100644 --- a/git/diff.py +++ b/git/diff.py @@ -195,7 +195,7 @@ class Diff(object): """, re.VERBOSE | re.MULTILINE) # can be used for comparisons NULL_HEX_SHA = "0" * 40 - NULL_BIN_SHA = "\0" * 20 + NULL_BIN_SHA = b"\0" * 20 __slots__ = ("a_blob", "b_blob", "a_mode", "b_mode", "new_file", "deleted_file", "rename_from", "rename_to", "diff") diff --git a/git/objects/base.py b/git/objects/base.py index 1f0d5752..004e3981 100644 --- a/git/objects/base.py +++ b/git/objects/base.py @@ -21,7 +21,7 @@ class Object(LazyMixin): """Implements an Object which may be Blobs, Trees, Commits and Tags""" NULL_HEX_SHA = '0' * 40 - NULL_BIN_SHA = '\0' * 20 + NULL_BIN_SHA = b'\0' * 20 TYPES = (dbtyp.str_blob_type, dbtyp.str_tree_type, dbtyp.str_commit_type, dbtyp.str_tag_type) __slots__ = ("repo", "binsha", "size") @@ -94,7 +94,7 @@ class Object(LazyMixin): def __str__(self): """:return: string of our SHA1 as understood by all git commands""" - return bin_to_hex(self.binsha) + return self.hexsha def __repr__(self): """:return: string with pythonic representation of our object""" @@ -103,7 +103,8 @@ class Object(LazyMixin): @property def hexsha(self): """:return: 40 byte hex version of our 20 byte binary sha""" - return bin_to_hex(self.binsha) + # b2a_hex produces bytes + return bin_to_hex(self.binsha).decode('ascii') @property def data_stream(self): diff --git a/git/objects/commit.py b/git/objects/commit.py index f8b5c969..53af22cd 100644 --- a/git/objects/commit.py +++ b/git/objects/commit.py @@ -62,7 +62,7 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable): "author", "authored_date", "author_tz_offset", "committer", "committed_date", "committer_tz_offset", "message", "parents", "encoding", "gpgsig") - _id_attribute_ = "binsha" + _id_attribute_ = "hexsha" def __init__(self, repo, binsha, tree=None, author=None, authored_date=None, author_tz_offset=None, committer=None, committed_date=None, committer_tz_offset=None, @@ -395,7 +395,7 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable): write(("encoding %s\n" % self.encoding).encode('ascii')) if self.gpgsig: - write("gpgsig") + write(b"gpgsig") for sigline in self.gpgsig.rstrip("\n").split("\n"): write((" " + sigline + "\n").encode('ascii')) diff --git a/git/objects/fun.py b/git/objects/fun.py index f92a4c06..610bdb5c 100644 --- a/git/objects/fun.py +++ b/git/objects/fun.py @@ -2,7 +2,6 @@ from stat import S_ISDIR from git.compat import ( byte_ord, - force_bytes, defenc, xrange, text_type @@ -37,7 +36,7 @@ def tree_to_stream(entries, write): # takes the input literally, which appears to be utf8 on linux. if isinstance(name, text_type): name = name.encode(defenc) - write(b''.join(mode_str, b' ', name, b'\0', binsha)) + write(b''.join((mode_str, b' ', name, b'\0', binsha))) # END for each item def tree_entries_from_data(data): diff --git a/git/refs/symbolic.py b/git/refs/symbolic.py index 1ac9ac65..252462a9 100644 --- a/git/refs/symbolic.py +++ b/git/refs/symbolic.py @@ -308,7 +308,7 @@ class SymbolicReference(object): lfd = LockedFD(fpath) fd = lfd.open(write=True, stream=True) - fd.write(write_value) + fd.write(write_value.encode('ascii')) lfd.commit() # Adjust the reflog diff --git a/git/repo/base.py b/git/repo/base.py index f92a85ce..27c640ff 100644 --- a/git/repo/base.py +++ b/git/repo/base.py @@ -47,7 +47,10 @@ from .fun import ( read_gitfile, touch, ) -from git.compat import text_type +from git.compat import ( + text_type, + defenc +) import os import sys @@ -177,11 +180,11 @@ class Repo(object): # Description property def _get_description(self): filename = join(self.git_dir, 'description') - return open(filename).read().rstrip() + return open(filename, 'rb').read().rstrip().decode(defenc) def _set_description(self, descr): filename = join(self.git_dir, 'description') - open(filename, 'w').write(descr + '\n') + open(filename, 'wb').write((descr + '\n').encode(defenc)) description = property(_get_description, _set_description, doc="the project's description") @@ -464,8 +467,8 @@ class Repo(object): if os.path.exists(alternates_path): try: - f = open(alternates_path) - alts = f.read() + f = open(alternates_path, 'rb') + alts = f.read().decode(defenc) finally: f.close() return alts.strip().splitlines() @@ -489,8 +492,8 @@ class Repo(object): os.remove(alternates_path) else: try: - f = open(alternates_path, 'w') - f.write("\n".join(alts)) + f = open(alternates_path, 'wb') + f.write("\n".join(alts).encode(defenc)) finally: f.close() # END file handling diff --git a/git/test/test_commit.py b/git/test/test_commit.py index 5f45e59d..37a54092 100644 --- a/git/test/test_commit.py +++ b/git/test/test_commit.py @@ -51,7 +51,7 @@ def assert_commit_serialization(rwrepo, commit_id, print_performance_info=False) stream.seek(0) istream = rwrepo.odb.store(IStream(Commit.type, streamlen, stream)) - assert istream.hexsha == cm.hexsha + assert istream.hexsha == cm.hexsha.encode('ascii') nc = Commit(rwrepo, Commit.NULL_BIN_SHA, cm.tree, cm.author, cm.authored_date, cm.author_tz_offset, @@ -129,7 +129,7 @@ class TestCommit(TestBase): def test_unicode_actor(self): # assure we can parse unicode actors correctly - name = "Üäöß ÄußÉ".decode("utf-8") + name = u"Üäöß ÄußÉ" assert len(name) == 9 special = Actor._from_string(u"%s <something@this.com>" % name) assert special.name == name @@ -146,13 +146,13 @@ class TestCommit(TestBase): # basic branch first, depth first dfirst = start.traverse(branch_first=False) bfirst = start.traverse(branch_first=True) - assert dfirst.next() == p0 - assert dfirst.next() == p00 + assert next(dfirst) == p0 + assert next(dfirst) == p00 - assert bfirst.next() == p0 - assert bfirst.next() == p1 - assert bfirst.next() == p00 - assert bfirst.next() == p10 + assert next(bfirst) == p0 + assert next(bfirst) == p1 + assert next(bfirst) == p00 + assert next(bfirst) == p10 # at some point, both iterations should stop assert list(bfirst)[-1] == first @@ -161,19 +161,19 @@ class TestCommit(TestBase): assert len(l[0]) == 2 # ignore self - assert start.traverse(ignore_self=False).next() == start + assert next(start.traverse(ignore_self=False)) == start # depth assert len(list(start.traverse(ignore_self=False, depth=0))) == 1 # prune - assert start.traverse(branch_first=1, prune=lambda i, d: i == p0).next() == p1 + assert next(start.traverse(branch_first=1, prune=lambda i, d: i == p0)) == p1 # predicate - assert start.traverse(branch_first=1, predicate=lambda i, d: i == p1).next() == p1 + assert next(start.traverse(branch_first=1, predicate=lambda i, d: i == p1)) == p1 # traversal should stop when the beginning is reached - self.failUnlessRaises(StopIteration, first.traverse().next) + self.failUnlessRaises(StopIteration, next, first.traverse()) # parents of the first commit should be empty ( as the only parent has a null # sha ) @@ -210,7 +210,7 @@ class TestCommit(TestBase): first_parent=True, bisect_all=True) - commits = Commit._iter_from_process_or_stream(self.rorepo, StringProcessAdapter(revs)) + commits = Commit._iter_from_process_or_stream(self.rorepo, StringProcessAdapter(revs.encode('ascii'))) expected_ids = ( '7156cece3c49544abb6bf7a0c218eb36646fad6d', '1f66cfbbce58b4b552b041707a12d437cc5f400a', @@ -224,8 +224,10 @@ class TestCommit(TestBase): assert self.rorepo.tag('refs/tags/0.1.5').commit.count() == 143 def test_list(self): + # This doesn't work anymore, as we will either attempt getattr with bytes, or compare 20 byte string + # with actual 20 byte bytes. This usage makes no sense anyway assert isinstance(Commit.list_items(self.rorepo, '0.1.5', max_count=5)[ - hex_to_bin('5117c9c8a4d3af19a9958677e45cda9269de1541')], Commit) + '5117c9c8a4d3af19a9958677e45cda9269de1541'], Commit) def test_str(self): commit = Commit(self.rorepo, Commit.NULL_BIN_SHA) @@ -247,12 +249,12 @@ class TestCommit(TestBase): c = self.rorepo.commit('0.1.5') for skip in (0, 1): piter = c.iter_parents(skip=skip) - first_parent = piter.next() + first_parent = next(piter) assert first_parent != c assert first_parent == c.parents[0] # END for each - def test_base(self): + def test_name_rev(self): name_rev = self.rorepo.head.commit.name_rev assert isinstance(name_rev, string_types) @@ -270,10 +272,10 @@ class TestCommit(TestBase): assert isinstance(cmt.message, text_type) # it automatically decodes it as such assert isinstance(cmt.author.name, text_type) # same here - cmt.message = "üäêèß".decode("utf-8") + cmt.message = u"üäêèß" assert len(cmt.message) == 5 - cmt.author.name = "äüß".decode("utf-8") + cmt.author.name = u"äüß" assert len(cmt.author.name) == 3 cstream = BytesIO() @@ -292,7 +294,7 @@ class TestCommit(TestBase): def test_gpgsig(self): cmt = self.rorepo.commit() - cmt._deserialize(open(fixture_path('commit_with_gpgsig'))) + cmt._deserialize(open(fixture_path('commit_with_gpgsig'), 'rb')) fixture_sig = """-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) @@ -318,7 +320,7 @@ JzJMZDRLQLFvnzqZuCjE cstream = BytesIO() cmt._serialize(cstream) - assert re.search(r"^gpgsig <test\n dummy\n sig>$", cstream.getvalue(), re.MULTILINE) + assert re.search(r"^gpgsig <test\n dummy\n sig>$", cstream.getvalue().decode('ascii'), re.MULTILINE) cstream.seek(0) cmt.gpgsig = None @@ -328,4 +330,4 @@ JzJMZDRLQLFvnzqZuCjE cmt.gpgsig = None cstream = BytesIO() cmt._serialize(cstream) - assert not re.search(r"^gpgsig ", cstream.getvalue(), re.MULTILINE) + assert not re.search(r"^gpgsig ", cstream.getvalue().decode('ascii'), re.MULTILINE) |