From 4868442b8d724a24aaed681eda76559b0da0e0e3 Mon Sep 17 00:00:00 2001 From: Markus Lehtonen Date: Sat, 16 Dec 2017 00:15:57 +0200 Subject: gbp.git: Python compatibility fixes Make gbp compatible with older versions of Python 3. As 'bytes' objects do not support the '%' operator until Python v3.5 we introduce a format_b() wrapper that handles this. NOTE: This change should be reverted when Python v3.5 (or newer) has been widely adopted. Signed-off-by: Markus Lehtonen --- gbp/format.py | 22 ++++++++++++++++++++++ gbp/git/fastimport.py | 11 ++++++----- gbp/git/repository.py | 3 ++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/gbp/format.py b/gbp/format.py index 2edf4ebd..541ab7b0 100644 --- a/gbp/format.py +++ b/gbp/format.py @@ -42,3 +42,25 @@ def format_str(msg, args): except KeyError as e: raise GbpError("Failed to format %s: Missing value %s in %s" % (msg, e, args)) + + +def format_b(fmtstr, *args): + """String-like interpolation for bytes objects. + + NOTE: This is a compatibility wrapper for older versions (<3.5) of Python 3 + which do not support the percent operator ('%') for bytes objects. This + function should be removed (and replaced by simple '%') when Python 3.5 + has gained wide enough adoption. + + >>> format_b(b'%s %d', b'foo', 123) + b'foo 123' + >>> format_b(b'foo 123') + b'foo 123' + >>> format_b('%s %d', b'foo', 123) + Traceback (most recent call last): + ... + AttributeError: 'str' object has no attribute 'decode' + """ + fmtstr = fmtstr.decode() + strargs = tuple([(a.decode() if isinstance(a, bytes) else a) for a in args]) + return (fmtstr % strargs).encode() diff --git a/gbp/git/fastimport.py b/gbp/git/fastimport.py index 40433700..a9941036 100644 --- a/gbp/git/fastimport.py +++ b/gbp/git/fastimport.py @@ -20,6 +20,7 @@ import subprocess import time from gbp.errors import GbpError +from gbp.format import format_b from gbp.paths import to_bin @@ -48,7 +49,7 @@ class FastImport(object): "Invalid argument when spawning git fast-import: %s" % err) def _do_data(self, fd, size): - self._out.write(b"data %d\n" % size) + self._out.write(format_b(b"data %d\n", size)) while True: data = fd.read(self._bufsize) self._out.write(data) @@ -58,7 +59,7 @@ class FastImport(object): def _do_file(self, filename, mode, fd, size): name = b"/".join(to_bin(filename).split(b'/')[1:]) - self._out.write(b"M %d inline %s\n" % (mode, name)) + self._out.write(format_b(b"M %d inline %s\n", mode, name)) self._do_data(fd, size) def add_file(self, filename, fd, size, mode=m_regular): @@ -87,9 +88,9 @@ class FastImport(object): """ linktarget = to_bin(linktarget) linkname = to_bin(linkname) - self._out.write(b"M %d inline %s\n" % (self.m_symlink, linkname)) - self._out.write(b"data %d\n" % len(linktarget)) - self._out.write(b"%s\n" % linktarget) + self._out.write(format_b(b"M %d inline %s\n", self.m_symlink, linkname)) + self._out.write(format_b(b"data %d\n", len(linktarget))) + self._out.write(format_b(b"%s\n", linktarget)) def start_commit(self, branch, committer, msg): """ diff --git a/gbp/git/repository.py b/gbp/git/repository.py index 3c858fa9..397ee9c9 100644 --- a/gbp/git/repository.py +++ b/gbp/git/repository.py @@ -24,6 +24,7 @@ from collections import defaultdict import gbp.log as log from gbp.errors import GbpError +from gbp.format import format_b from gbp.git.modifier import GitModifier from gbp.git.commit import GitCommit from gbp.git.errors import GitError @@ -1044,7 +1045,7 @@ class GitRepository(object): for mode, type_, sha1, name in contents: name = to_bin(name) - objs += b'%s %s %s\t%s\0' % (mode.encode(), type_.encode(), sha1.encode(), name) + objs += format_b(b'%s %s %s\t%s\0', mode.encode(), type_.encode(), sha1.encode(), name) sha1, err, ret = self._git_inout('mktree', args.args, -- cgit v1.2.3