From e0a7105c2d47f4c71043b8028b484a9e1a1c6700 Mon Sep 17 00:00:00 2001 From: Adrian Likins Date: Mon, 24 Apr 2017 10:09:03 -0400 Subject: [PATCH] Use sys.stdout.buffer to write vault bytes to stdout on py3 (#23760) * Use sys.stdout.buffer to write vault bytes to stdout on py3 We need sys.stdout.buffer on py3 so we can write bytes to it since the plaintext of the vaulted object could be anything/binary/etc Before, attempting to write bytes to stdout on py3 would cause: TypeError: write() argument must be str, not bytes --- lib/ansible/parsing/vault/__init__.py | 29 +++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/ansible/parsing/vault/__init__.py b/lib/ansible/parsing/vault/__init__.py index 0c424e2684..bb863201f9 100644 --- a/lib/ansible/parsing/vault/__init__.py +++ b/lib/ansible/parsing/vault/__init__.py @@ -533,19 +533,36 @@ class VaultEditor: # TODO: add docstrings for arg types since this code is picky about that def write_data(self, data, filename, shred=True): - """write data to given path + """Write the data bytes to given path - :arg data: the encrypted and hexlified data as a utf-8 byte string + This is used to write a byte string to a file or stdout. It is used for + writing the results of vault encryption or decryption. It is used for + saving the ciphertext after encryption and it is also used for saving the + plaintext after decrypting a vault. The type of the 'data' arg should be bytes, + since in the plaintext case, the original contents can be of any text encoding + or arbitrary binary data. + + When used to write the result of vault encryption, the val of the 'data' arg + should be a utf-8 encoded byte string and not a text typ and not a text type.. + + When used to write the result of vault decryption, the val of the 'data' arg + should be a byte string and not a text type. + + :arg data: the byte string (bytes) data :arg filename: filename to save 'data' to. - :arg shred: if shred==True, make sure that the original data is first shredded so - that is cannot be recovered. + :arg shred: if shred==True, make sure that the original data is first shredded so that is cannot be recovered. + :returns: None """ # FIXME: do we need this now? data_bytes should always be a utf-8 byte string b_file_data = to_bytes(data, errors='strict') + # get a ref to either sys.stdout.buffer for py3 or plain old sys.stdout for py2 + # We need sys.stdout.buffer on py3 so we can write bytes to it since the plaintext + # of the vaulted object could be anything/binary/etc + output = getattr(sys.stdout, 'buffer', sys.stdout) + if filename == '-': - file_data = to_text(b_file_data, encoding='utf-8', errors='strict', nonstring='strict') - sys.stdout.write(file_data) + output.write(b_file_data) else: if os.path.isfile(filename): if shred: