Switch to string format to avoid interpolation issues

Convert to using python format to align and interpolate values to
ensure the correct output on python 2 & 3 when dealing with unicode and
str.

Interpolating strings using encode into '%s' and subsequently
interpolating the results into a second string results in the output
printing embedded byte strings on python 3.

 $ git-review -l
 b'226894'  b'master'  b'Add pem key parameter (WIP)'
 b'199225'  b'master'  b'support urls as change-id input

Which occurs because after converting a string to unicode bytes, it was
then interpolated using '%s'.

Switching to using '.format()' method takes care of converting the
output to the correct string format for python 2 & 3 automatically.

Change-Id: Ia962d18bda34e0244fb05636a7be263045ecb256
This commit is contained in:
Darragh Bailey 2016-10-21 13:57:32 +01:00
parent 67dbbc2e59
commit efb5126e67
2 changed files with 23 additions and 12 deletions

View File

@ -1008,8 +1008,8 @@ def list_reviews(remote):
else:
review_field_color = ("", "", "")
color_reset = ""
review_field_format = ["%*s", "%*s", "%*s"]
review_field_justify = [+1, +1, -1] # +1 is justify to right
# > is right justify, < is left, field indices for py26
review_field_format = ["{0:>{1}}", "{2:>{3}}", "{4:<{5}}"]
review_list = [[r[f] for f in REVIEW_FIELDS] for r in reviews]
review_field_width = dict()
@ -1026,20 +1026,15 @@ def list_reviews(remote):
color_reset
for i in FIELDS])
review_field_width = [
review_field_width[i] * review_field_justify[i]
for i in FIELDS]
review_field_width = [review_field_width[i] for i in FIELDS]
for review_value in review_list:
# At this point we have review_field_format
# like "%*s %*s %*s" and we need to supply
# (width1, value1, width2, value2, ...) tuple to print
# It's easy to zip() widths with actual values,
# but we need to flatten the resulting
# ((width1, value1), (width2, value2), ...) map.
# like "{:>{}} {:>{}} {:<{}}" and we need to supply
# (value1, width1, value2, width2, ...) tuple to print
formatted_fields = []
for (width, value) in zip(review_field_width, review_value):
formatted_fields.extend([width, value.encode('utf-8')])
print(review_field_format % tuple(formatted_fields))
formatted_fields.extend([value, width])
print(review_field_format.format(*formatted_fields))
print("Found %d items for review" % len(reviews))
return 0

View File

@ -102,6 +102,22 @@ class GitReviewConsole(testtools.TestCase, fixtures.TestWithFixtures):
self.run_cmd_patcher.stop()
super(GitReviewConsole, self).tearDown()
@mock.patch('git_review.cmd.query_reviews')
@mock.patch('git_review.cmd.get_remote_url', mock.MagicMock)
@mock.patch('git_review.cmd._has_color', False)
def test_list_reviews_output(self, mock_query):
mock_query.return_value = self.reviews
with mock.patch('sys.stdout', new_callable=io.StringIO) as output:
cmd.list_reviews(None)
console_output = output.getvalue().split('\n')
self.assertEqual(
['1010101 master A simple short subject',
' 9877 stable/codeword A longer and slightly more wordy '
'subject'],
console_output[:2])
@mock.patch('git_review.cmd.query_reviews')
@mock.patch('git_review.cmd.get_remote_url', mock.MagicMock)
@mock.patch('git_review.cmd._has_color', False)