Before writing object data to stdout, re-open it in binary mode

Otherwise, you can hit TypeErrors on Python3.

Change-Id: I9a891508886feddac3982ce593bd95130392e035
Closes-Bug: 1775482
This commit is contained in:
Tim Burke 2018-06-07 16:40:58 -07:00 committed by Dean Troyer
parent c53de3214e
commit 415b48056d
3 changed files with 29 additions and 4 deletions

View File

@ -378,8 +378,9 @@ class APIv1(api.BaseAPI):
)
if response.status_code == 200:
if file == '-':
with os.fdopen(sys.stdout.fileno(), 'wb') as f:
for chunk in response.iter_content(64 * 1024):
sys.stdout.write(chunk)
f.write(chunk)
else:
if not os.path.exists(os.path.dirname(file)):
if len(os.path.dirname(file)) > 0:

View File

@ -241,7 +241,25 @@ class TestObjectSave(TestObjectAll):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch('sys.stdout', new=six.BytesIO()) as fake_stdout:
class FakeStdout(six.BytesIO):
def __init__(self):
six.BytesIO.__init__(self)
self.context_manager_calls = []
def __enter__(self):
self.context_manager_calls.append('__enter__')
return self
def __exit__(self, *a):
self.context_manager_calls.append('__exit__')
with mock.patch('sys.stdout') as fake_stdout, mock.patch(
'os.fdopen', return_value=FakeStdout()) as fake_fdopen:
fake_stdout.fileno.return_value = 123
self.cmd.take_action(parsed_args)
self.assertEqual(fake_stdout.getvalue(), object_fakes.object_1_content)
self.assertEqual(fake_fdopen.return_value.getvalue(),
object_fakes.object_1_content)
self.assertEqual(fake_fdopen.mock_calls, [mock.call(123, 'wb')])
self.assertEqual(fake_fdopen.return_value.context_manager_calls,
['__enter__', '__exit__'])

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Re-open stdout in binary mode before writing object data in
``object save --file -`` command.
[Bug `1775482 <https://bugs.launchpad.net/python-openstackclient/+bug/1775482>`_]