Merge ~pappacena/turnip:py3-strings-compat into turnip:master

Proposed by Thiago F. Pappacena
Status: Merged
Approved by: Thiago F. Pappacena
Approved revision: 75d004fdfe0011fc49dca6ffbb8505af1de9a1ad
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~pappacena/turnip:py3-strings-compat
Merge into: turnip:master
Diff against target: 259 lines (+80/-29)
5 files modified
turnip/api/store.py (+11/-9)
turnip/api/tests/test_api.py (+10/-13)
turnip/api/tests/test_helpers.py (+30/-7)
turnip/tests/__init__.py (+13/-0)
turnip/tests/logging.py (+16/-0)
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+380451@code.launchpad.net

Commit message

Making some strings compatible both with python2 and python3

Description of the change

This MP should only be merged once we have the new dependencies in place.

It reduces the total amount of failing tests on python3:
From (failures=10, errors=28) to (failures=6, errors=21)

To post a comment you must log in.
Revision history for this message
Thiago F. Pappacena (pappacena) :
Revision history for this message
Colin Watson (cjwatson) wrote :

I'd particularly like to see my comments about get_refs disentangled, but should be fine after that.

review: Approve
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Pushed the required changes.

Revision history for this message
Colin Watson (cjwatson) :
review: Approve
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Thanks for the review, cjwatson. Pushed the changes. Landing this now.

Revision history for this message
Otto Co-Pilot (otto-copilot) wrote :
Revision history for this message
Otto Co-Pilot (otto-copilot) wrote :
Revision history for this message
Otto Co-Pilot (otto-copilot) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/turnip/api/store.py b/turnip/api/store.py
2index 11b4756..934dd71 100644
3--- a/turnip/api/store.py
4+++ b/turnip/api/store.py
5@@ -2,10 +2,6 @@
6 # GNU Affero General Public License version 3 (see the file LICENSE).
7
8 import base64
9-from contextlib2 import (
10- contextmanager,
11- ExitStack,
12- )
13 import itertools
14 import os
15 import re
16@@ -13,14 +9,18 @@ import shutil
17 import subprocess
18 import uuid
19
20+from contextlib2 import (
21+ contextmanager,
22+ ExitStack,
23+ )
24 from pygit2 import (
25- GitError,
26 GIT_OBJ_BLOB,
27 GIT_OBJ_COMMIT,
28- GIT_OBJ_TREE,
29 GIT_OBJ_TAG,
30+ GIT_OBJ_TREE,
31 GIT_REF_OID,
32 GIT_SORT_TOPOLOGICAL,
33+ GitError,
34 IndexEntry,
35 init_repository,
36 Oid,
37@@ -335,12 +335,14 @@ def get_refs(repo_store, repo_name, exclude_prefixes=None):
38 """Return all refs for a git repository."""
39 with open_repo(repo_store, repo_name) as repo:
40 refs = {}
41- for ref in repo.listall_references():
42- git_object = repo.references[ref].peel()
43+ for ref_obj in repo.listall_reference_objects():
44 # Filter non-unicode refs, as refs are treated as unicode
45 # given json is unable to represent arbitrary byte strings.
46 try:
47- ref = ref.decode('utf-8')
48+ ref = ref_obj.name
49+ if isinstance(ref, bytes):
50+ ref = ref.decode('utf-8')
51+ git_object = repo.references[ref].peel()
52 except UnicodeDecodeError:
53 pass
54 else:
55diff --git a/turnip/api/tests/test_api.py b/turnip/api/tests/test_api.py
56index 2ff34d0..396369b 100644
57--- a/turnip/api/tests/test_api.py
58+++ b/turnip/api/tests/test_api.py
59@@ -10,16 +10,13 @@ import os
60 import subprocess
61 from textwrap import dedent
62 import unittest
63-try:
64- from urllib.parse import quote
65-except ImportError:
66- from urllib import quote
67 import uuid
68
69 from fixtures import (
70 EnvironmentVariable,
71 TempDir,
72 )
73+from six.moves.urllib.parse import quote
74 from testtools import TestCase
75 from testtools.matchers import (
76 Equals,
77@@ -217,7 +214,7 @@ class ApiTestCase(TestCase):
78 """Ensure non-unicode refs are dropped from ref collection."""
79 factory = RepoFactory(self.repo_store)
80 commit_oid = factory.add_commit('foo', 'foobar.txt')
81- tag = '\xe9\xe9\xe9' # latin-1
82+ tag = b'\xe9\xe9\xe9' # latin-1
83 tag_message = 'tag message'
84 factory.add_tag(tag, tag_message, commit_oid)
85
86@@ -335,7 +332,7 @@ class ApiTestCase(TestCase):
87 def test_repo_diff_non_unicode_commits(self):
88 """Ensure non utf-8 chars are handled but stripped from diff."""
89 factory = RepoFactory(self.repo_store)
90- message = 'not particularly sensible latin-1: \xe9\xe9\xe9.'
91+ message = b'not particularly sensible latin-1: \xe9\xe9\xe9.'
92 oid = factory.add_commit(message, 'foo.py')
93 oid2 = factory.add_commit('a sensible commit message', 'foo.py', [oid])
94
95@@ -406,7 +403,7 @@ class ApiTestCase(TestCase):
96 self.repo_path, quote('{}^'.format(c2)), c2)
97 resp = self.app.get(path)
98 self.assertIn(
99- b'diff --git a/foo.txt b/bar.txt\n', resp.json_body['patch'])
100+ 'diff --git a/foo.txt b/bar.txt\n', resp.json_body['patch'])
101
102 def test_repo_diff_rename_and_change_content_conflict(self):
103 # Create repo1 with foo.txt.
104@@ -576,7 +573,7 @@ class ApiTestCase(TestCase):
105 resp = self.app.get('/repo/{}/compare-merge/{}:{}'.format(
106 self.repo_path, c1, c2))
107 self.assertIn(
108- b'diff --git a/foo.txt b/bar.txt\n', resp.json_body['patch'])
109+ 'diff --git a/foo.txt b/bar.txt\n', resp.json_body['patch'])
110
111 def test_repo_get_commit(self):
112 factory = RepoFactory(self.repo_store)
113@@ -671,7 +668,7 @@ class ApiTestCase(TestCase):
114 def test_repo_get_non_unicode_log(self):
115 """Ensure that non-unicode data is discarded."""
116 factory = RepoFactory(self.repo_store)
117- message = '\xe9\xe9\xe9' # latin-1
118+ message = b'\xe9\xe9\xe9' # latin-1
119 oid = factory.add_commit(message, 'foo.py')
120 resp = self.app.get('/repo/{}/log/{}'.format(self.repo_path, oid))
121 self.assertEqual(message.decode('utf-8', 'replace'),
122@@ -809,15 +806,15 @@ class ApiTestCase(TestCase):
123 factory.add_commit('b\n', 'dir/file', parents=[c1])
124 resp = self.app.get('/repo/{}/blob/dir/file'.format(self.repo_path))
125 self.assertEqual(2, resp.json['size'])
126- self.assertEqual('b\n', base64.b64decode(resp.json['data']))
127+ self.assertEqual(b'b\n', base64.b64decode(resp.json['data']))
128 resp = self.app.get('/repo/{}/blob/dir/file?rev=master'.format(
129 self.repo_path))
130 self.assertEqual(2, resp.json['size'])
131- self.assertEqual('b\n', base64.b64decode(resp.json['data']))
132+ self.assertEqual(b'b\n', base64.b64decode(resp.json['data']))
133 resp = self.app.get('/repo/{}/blob/dir/file?rev={}'.format(
134 self.repo_path, c1.hex))
135 self.assertEqual(2, resp.json['size'])
136- self.assertEqual('a\n', base64.b64decode(resp.json['data']))
137+ self.assertEqual(b'a\n', base64.b64decode(resp.json['data']))
138
139 def test_repo_blob_missing_commit(self):
140 """Trying to get a blob from a non-existent commit returns HTTP 404."""
141@@ -861,7 +858,7 @@ class ApiTestCase(TestCase):
142 resp = self.app.get('/repo/{}/blob/dir/file?rev=tag-name'.format(
143 self.repo_path))
144 self.assertEqual(2, resp.json['size'])
145- self.assertEqual('a\n', base64.b64decode(resp.json['data']))
146+ self.assertEqual(b'a\n', base64.b64decode(resp.json['data']))
147
148 def test_repo_blob_from_non_commit(self):
149 """Trying to get a blob from a non-commit returns HTTP 404."""
150diff --git a/turnip/api/tests/test_helpers.py b/turnip/api/tests/test_helpers.py
151index dac6950..a6035b4 100644
152--- a/turnip/api/tests/test_helpers.py
153+++ b/turnip/api/tests/test_helpers.py
154@@ -4,20 +4,23 @@
155 import contextlib
156 import fnmatch
157 import itertools
158+import logging
159 import os
160+from subprocess import PIPE, Popen, CalledProcessError
161 import uuid
162
163-from six.moves import urllib
164-
165 from pygit2 import (
166 clone_repository,
167- init_repository,
168 GIT_FILEMODE_BLOB,
169- GIT_OBJ_COMMIT,
170 IndexEntry,
171+ init_repository,
172 Repository,
173 Signature,
174 )
175+import six
176+from six.moves import urllib
177+
178+log = logging.getLogger()
179
180
181 def get_revlist(repo):
182@@ -94,14 +97,34 @@ class RepoFactory(object):
183 self.branches.append(branch)
184 return branch
185
186+ def _get_cmd_line_auth_params(self):
187+ return [
188+ '-c', 'user.name={}'.format(self.author.name),
189+ '-c', 'user.email={}'.format(self.author.email),
190+ '-c', 'author.name={}'.format(self.author.name),
191+ '-c', 'author.email={}'.format(self.author.email),
192+ '-c', 'committer.name={}'.format(self.committer.name),
193+ '-c', 'committer.email={}'.format(self.committer.email),
194+ ]
195+
196 def add_tag(self, tag_name, tag_message, oid):
197 """Create a tag from tag_name and oid."""
198- repo = self.repo
199- repo.create_tag(tag_name, oid, GIT_OBJ_COMMIT,
200- self.committer, tag_message)
201+ cmd_line = ['git', '-C', self.repo_path]
202+ cmd_line += self._get_cmd_line_auth_params()
203+ cmd_line += ['tag', '-m', tag_message, tag_name, oid.hex]
204+ subproc = Popen(cmd_line, stderr=PIPE, stdout=PIPE)
205+ retcode = subproc.wait()
206+ if retcode:
207+ log.error(
208+ "Command %s finished with error code %s. stdout/stderr:\n%s",
209+ cmd_line, retcode, subproc.stderr.read())
210+ raise CalledProcessError(retcode, cmd_line)
211
212 def makeSignature(self, name, email, encoding='utf-8'):
213 """Return an author or committer signature."""
214+ # email should always be str on python3, but pygit2
215+ # doesn't enforce the same for name.
216+ email = six.ensure_str(email)
217 return Signature(name, email, encoding=encoding)
218
219 def stage(self, path, content):
220diff --git a/turnip/tests/__init__.py b/turnip/tests/__init__.py
221index e69de29..494f3fd 100644
222--- a/turnip/tests/__init__.py
223+++ b/turnip/tests/__init__.py
224@@ -0,0 +1,13 @@
225+# Copyright 2020 Canonical Ltd. This software is licensed under the
226+# GNU Affero General Public License version 3 (see the file LICENSE).
227+
228+from __future__ import (
229+ absolute_import,
230+ print_function,
231+ unicode_literals,
232+ )
233+
234+from turnip.tests.logging import setupLogger
235+
236+
237+setupLogger()
238diff --git a/turnip/tests/logging.py b/turnip/tests/logging.py
239new file mode 100644
240index 0000000..28b6ef3
241--- /dev/null
242+++ b/turnip/tests/logging.py
243@@ -0,0 +1,16 @@
244+# Copyright 2020 Canonical Ltd. This software is licensed under the
245+# GNU Affero General Public License version 3 (see the file LICENSE).
246+
247+from __future__ import (
248+ absolute_import,
249+ print_function,
250+ unicode_literals,
251+ )
252+
253+import sys
254+import logging
255+
256+
257+def setupLogger():
258+ """Setup our basic logging for tests."""
259+ logging.basicConfig(stream=sys.stdout, level=logging.INFO)

Subscribers

People subscribed via source and target branches