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
diff --git a/turnip/api/store.py b/turnip/api/store.py
index 11b4756..934dd71 100644
--- a/turnip/api/store.py
+++ b/turnip/api/store.py
@@ -2,10 +2,6 @@
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4import base644import base64
5from contextlib2 import (
6 contextmanager,
7 ExitStack,
8 )
9import itertools5import itertools
10import os6import os
11import re7import re
@@ -13,14 +9,18 @@ import shutil
13import subprocess9import subprocess
14import uuid10import uuid
1511
12from contextlib2 import (
13 contextmanager,
14 ExitStack,
15 )
16from pygit2 import (16from pygit2 import (
17 GitError,
18 GIT_OBJ_BLOB,17 GIT_OBJ_BLOB,
19 GIT_OBJ_COMMIT,18 GIT_OBJ_COMMIT,
20 GIT_OBJ_TREE,
21 GIT_OBJ_TAG,19 GIT_OBJ_TAG,
20 GIT_OBJ_TREE,
22 GIT_REF_OID,21 GIT_REF_OID,
23 GIT_SORT_TOPOLOGICAL,22 GIT_SORT_TOPOLOGICAL,
23 GitError,
24 IndexEntry,24 IndexEntry,
25 init_repository,25 init_repository,
26 Oid,26 Oid,
@@ -335,12 +335,14 @@ def get_refs(repo_store, repo_name, exclude_prefixes=None):
335 """Return all refs for a git repository."""335 """Return all refs for a git repository."""
336 with open_repo(repo_store, repo_name) as repo:336 with open_repo(repo_store, repo_name) as repo:
337 refs = {}337 refs = {}
338 for ref in repo.listall_references():338 for ref_obj in repo.listall_reference_objects():
339 git_object = repo.references[ref].peel()
340 # Filter non-unicode refs, as refs are treated as unicode339 # Filter non-unicode refs, as refs are treated as unicode
341 # given json is unable to represent arbitrary byte strings.340 # given json is unable to represent arbitrary byte strings.
342 try:341 try:
343 ref = ref.decode('utf-8')342 ref = ref_obj.name
343 if isinstance(ref, bytes):
344 ref = ref.decode('utf-8')
345 git_object = repo.references[ref].peel()
344 except UnicodeDecodeError:346 except UnicodeDecodeError:
345 pass347 pass
346 else:348 else:
diff --git a/turnip/api/tests/test_api.py b/turnip/api/tests/test_api.py
index 2ff34d0..396369b 100644
--- a/turnip/api/tests/test_api.py
+++ b/turnip/api/tests/test_api.py
@@ -10,16 +10,13 @@ import os
10import subprocess10import subprocess
11from textwrap import dedent11from textwrap import dedent
12import unittest12import unittest
13try:
14 from urllib.parse import quote
15except ImportError:
16 from urllib import quote
17import uuid13import uuid
1814
19from fixtures import (15from fixtures import (
20 EnvironmentVariable,16 EnvironmentVariable,
21 TempDir,17 TempDir,
22 )18 )
19from six.moves.urllib.parse import quote
23from testtools import TestCase20from testtools import TestCase
24from testtools.matchers import (21from testtools.matchers import (
25 Equals,22 Equals,
@@ -217,7 +214,7 @@ class ApiTestCase(TestCase):
217 """Ensure non-unicode refs are dropped from ref collection."""214 """Ensure non-unicode refs are dropped from ref collection."""
218 factory = RepoFactory(self.repo_store)215 factory = RepoFactory(self.repo_store)
219 commit_oid = factory.add_commit('foo', 'foobar.txt')216 commit_oid = factory.add_commit('foo', 'foobar.txt')
220 tag = '\xe9\xe9\xe9' # latin-1217 tag = b'\xe9\xe9\xe9' # latin-1
221 tag_message = 'tag message'218 tag_message = 'tag message'
222 factory.add_tag(tag, tag_message, commit_oid)219 factory.add_tag(tag, tag_message, commit_oid)
223220
@@ -335,7 +332,7 @@ class ApiTestCase(TestCase):
335 def test_repo_diff_non_unicode_commits(self):332 def test_repo_diff_non_unicode_commits(self):
336 """Ensure non utf-8 chars are handled but stripped from diff."""333 """Ensure non utf-8 chars are handled but stripped from diff."""
337 factory = RepoFactory(self.repo_store)334 factory = RepoFactory(self.repo_store)
338 message = 'not particularly sensible latin-1: \xe9\xe9\xe9.'335 message = b'not particularly sensible latin-1: \xe9\xe9\xe9.'
339 oid = factory.add_commit(message, 'foo.py')336 oid = factory.add_commit(message, 'foo.py')
340 oid2 = factory.add_commit('a sensible commit message', 'foo.py', [oid])337 oid2 = factory.add_commit('a sensible commit message', 'foo.py', [oid])
341338
@@ -406,7 +403,7 @@ class ApiTestCase(TestCase):
406 self.repo_path, quote('{}^'.format(c2)), c2)403 self.repo_path, quote('{}^'.format(c2)), c2)
407 resp = self.app.get(path)404 resp = self.app.get(path)
408 self.assertIn(405 self.assertIn(
409 b'diff --git a/foo.txt b/bar.txt\n', resp.json_body['patch'])406 'diff --git a/foo.txt b/bar.txt\n', resp.json_body['patch'])
410407
411 def test_repo_diff_rename_and_change_content_conflict(self):408 def test_repo_diff_rename_and_change_content_conflict(self):
412 # Create repo1 with foo.txt.409 # Create repo1 with foo.txt.
@@ -576,7 +573,7 @@ class ApiTestCase(TestCase):
576 resp = self.app.get('/repo/{}/compare-merge/{}:{}'.format(573 resp = self.app.get('/repo/{}/compare-merge/{}:{}'.format(
577 self.repo_path, c1, c2))574 self.repo_path, c1, c2))
578 self.assertIn(575 self.assertIn(
579 b'diff --git a/foo.txt b/bar.txt\n', resp.json_body['patch'])576 'diff --git a/foo.txt b/bar.txt\n', resp.json_body['patch'])
580577
581 def test_repo_get_commit(self):578 def test_repo_get_commit(self):
582 factory = RepoFactory(self.repo_store)579 factory = RepoFactory(self.repo_store)
@@ -671,7 +668,7 @@ class ApiTestCase(TestCase):
671 def test_repo_get_non_unicode_log(self):668 def test_repo_get_non_unicode_log(self):
672 """Ensure that non-unicode data is discarded."""669 """Ensure that non-unicode data is discarded."""
673 factory = RepoFactory(self.repo_store)670 factory = RepoFactory(self.repo_store)
674 message = '\xe9\xe9\xe9' # latin-1671 message = b'\xe9\xe9\xe9' # latin-1
675 oid = factory.add_commit(message, 'foo.py')672 oid = factory.add_commit(message, 'foo.py')
676 resp = self.app.get('/repo/{}/log/{}'.format(self.repo_path, oid))673 resp = self.app.get('/repo/{}/log/{}'.format(self.repo_path, oid))
677 self.assertEqual(message.decode('utf-8', 'replace'),674 self.assertEqual(message.decode('utf-8', 'replace'),
@@ -809,15 +806,15 @@ class ApiTestCase(TestCase):
809 factory.add_commit('b\n', 'dir/file', parents=[c1])806 factory.add_commit('b\n', 'dir/file', parents=[c1])
810 resp = self.app.get('/repo/{}/blob/dir/file'.format(self.repo_path))807 resp = self.app.get('/repo/{}/blob/dir/file'.format(self.repo_path))
811 self.assertEqual(2, resp.json['size'])808 self.assertEqual(2, resp.json['size'])
812 self.assertEqual('b\n', base64.b64decode(resp.json['data']))809 self.assertEqual(b'b\n', base64.b64decode(resp.json['data']))
813 resp = self.app.get('/repo/{}/blob/dir/file?rev=master'.format(810 resp = self.app.get('/repo/{}/blob/dir/file?rev=master'.format(
814 self.repo_path))811 self.repo_path))
815 self.assertEqual(2, resp.json['size'])812 self.assertEqual(2, resp.json['size'])
816 self.assertEqual('b\n', base64.b64decode(resp.json['data']))813 self.assertEqual(b'b\n', base64.b64decode(resp.json['data']))
817 resp = self.app.get('/repo/{}/blob/dir/file?rev={}'.format(814 resp = self.app.get('/repo/{}/blob/dir/file?rev={}'.format(
818 self.repo_path, c1.hex))815 self.repo_path, c1.hex))
819 self.assertEqual(2, resp.json['size'])816 self.assertEqual(2, resp.json['size'])
820 self.assertEqual('a\n', base64.b64decode(resp.json['data']))817 self.assertEqual(b'a\n', base64.b64decode(resp.json['data']))
821818
822 def test_repo_blob_missing_commit(self):819 def test_repo_blob_missing_commit(self):
823 """Trying to get a blob from a non-existent commit returns HTTP 404."""820 """Trying to get a blob from a non-existent commit returns HTTP 404."""
@@ -861,7 +858,7 @@ class ApiTestCase(TestCase):
861 resp = self.app.get('/repo/{}/blob/dir/file?rev=tag-name'.format(858 resp = self.app.get('/repo/{}/blob/dir/file?rev=tag-name'.format(
862 self.repo_path))859 self.repo_path))
863 self.assertEqual(2, resp.json['size'])860 self.assertEqual(2, resp.json['size'])
864 self.assertEqual('a\n', base64.b64decode(resp.json['data']))861 self.assertEqual(b'a\n', base64.b64decode(resp.json['data']))
865862
866 def test_repo_blob_from_non_commit(self):863 def test_repo_blob_from_non_commit(self):
867 """Trying to get a blob from a non-commit returns HTTP 404."""864 """Trying to get a blob from a non-commit returns HTTP 404."""
diff --git a/turnip/api/tests/test_helpers.py b/turnip/api/tests/test_helpers.py
index dac6950..a6035b4 100644
--- a/turnip/api/tests/test_helpers.py
+++ b/turnip/api/tests/test_helpers.py
@@ -4,20 +4,23 @@
4import contextlib4import contextlib
5import fnmatch5import fnmatch
6import itertools6import itertools
7import logging
7import os8import os
9from subprocess import PIPE, Popen, CalledProcessError
8import uuid10import uuid
911
10from six.moves import urllib
11
12from pygit2 import (12from pygit2 import (
13 clone_repository,13 clone_repository,
14 init_repository,
15 GIT_FILEMODE_BLOB,14 GIT_FILEMODE_BLOB,
16 GIT_OBJ_COMMIT,
17 IndexEntry,15 IndexEntry,
16 init_repository,
18 Repository,17 Repository,
19 Signature,18 Signature,
20 )19 )
20import six
21from six.moves import urllib
22
23log = logging.getLogger()
2124
2225
23def get_revlist(repo):26def get_revlist(repo):
@@ -94,14 +97,34 @@ class RepoFactory(object):
94 self.branches.append(branch)97 self.branches.append(branch)
95 return branch98 return branch
9699
100 def _get_cmd_line_auth_params(self):
101 return [
102 '-c', 'user.name={}'.format(self.author.name),
103 '-c', 'user.email={}'.format(self.author.email),
104 '-c', 'author.name={}'.format(self.author.name),
105 '-c', 'author.email={}'.format(self.author.email),
106 '-c', 'committer.name={}'.format(self.committer.name),
107 '-c', 'committer.email={}'.format(self.committer.email),
108 ]
109
97 def add_tag(self, tag_name, tag_message, oid):110 def add_tag(self, tag_name, tag_message, oid):
98 """Create a tag from tag_name and oid."""111 """Create a tag from tag_name and oid."""
99 repo = self.repo112 cmd_line = ['git', '-C', self.repo_path]
100 repo.create_tag(tag_name, oid, GIT_OBJ_COMMIT,113 cmd_line += self._get_cmd_line_auth_params()
101 self.committer, tag_message)114 cmd_line += ['tag', '-m', tag_message, tag_name, oid.hex]
115 subproc = Popen(cmd_line, stderr=PIPE, stdout=PIPE)
116 retcode = subproc.wait()
117 if retcode:
118 log.error(
119 "Command %s finished with error code %s. stdout/stderr:\n%s",
120 cmd_line, retcode, subproc.stderr.read())
121 raise CalledProcessError(retcode, cmd_line)
102122
103 def makeSignature(self, name, email, encoding='utf-8'):123 def makeSignature(self, name, email, encoding='utf-8'):
104 """Return an author or committer signature."""124 """Return an author or committer signature."""
125 # email should always be str on python3, but pygit2
126 # doesn't enforce the same for name.
127 email = six.ensure_str(email)
105 return Signature(name, email, encoding=encoding)128 return Signature(name, email, encoding=encoding)
106129
107 def stage(self, path, content):130 def stage(self, path, content):
diff --git a/turnip/tests/__init__.py b/turnip/tests/__init__.py
index e69de29..494f3fd 100644
--- a/turnip/tests/__init__.py
+++ b/turnip/tests/__init__.py
@@ -0,0 +1,13 @@
1# Copyright 2020 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4from __future__ import (
5 absolute_import,
6 print_function,
7 unicode_literals,
8 )
9
10from turnip.tests.logging import setupLogger
11
12
13setupLogger()
diff --git a/turnip/tests/logging.py b/turnip/tests/logging.py
0new file mode 10064414new file mode 100644
index 0000000..28b6ef3
--- /dev/null
+++ b/turnip/tests/logging.py
@@ -0,0 +1,16 @@
1# Copyright 2020 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4from __future__ import (
5 absolute_import,
6 print_function,
7 unicode_literals,
8 )
9
10import sys
11import logging
12
13
14def setupLogger():
15 """Setup our basic logging for tests."""
16 logging.basicConfig(stream=sys.stdout, level=logging.INFO)

Subscribers

People subscribed via source and target branches