diff options
author | Mike Schwartz <mfschwartz@google.com> | 2019-03-26 18:07:03 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-26 18:07:03 -0700 |
commit | 9e1cd3bd76e738d80630f1bd9160fd87c8eab865 (patch) | |
tree | 8eaf0e0f477b7e11e85cb0e5f9b33844789d0c86 | |
parent | acd6a95ad953a4f1ac72adfc354a6c5aec74fbb0 (diff) | |
parent | 2b9fd4f699ae5d40b4773f19ea61489928ea2a22 (diff) | |
download | boto-9e1cd3bd76e738d80630f1bd9160fd87c8eab865.tar.gz |
Merge pull request #3859 from catleeball/fd-writer
Added print_to_fd to utils.py
-rw-r--r-- | boto/s3/key.py | 4 | ||||
-rw-r--r-- | boto/utils.py | 82 |
2 files changed, 84 insertions, 2 deletions
diff --git a/boto/s3/key.py b/boto/s3/key.py index 35f04c9f..f9260258 100644 --- a/boto/s3/key.py +++ b/boto/s3/key.py @@ -46,7 +46,7 @@ import boto.utils from boto.utils import compute_md5, compute_hash from boto.utils import find_matching_headers from boto.utils import merge_headers_by_name - +from boto.utils import print_to_fd class Key(object): """ @@ -1553,7 +1553,7 @@ class Key(object): cb(data_len, cb_size) try: for key_bytes in self: - print(key_bytes, file=fp, end='') + print_to_fd(six.ensure_binary(key_bytes), file=fp, end=b'') data_len += len(key_bytes) for alg in digesters: digesters[alg].update(key_bytes) diff --git a/boto/utils.py b/boto/utils.py index 531a72d3..35637772 100644 --- a/boto/utils.py +++ b/boto/utils.py @@ -44,11 +44,13 @@ import time import logging.handlers import boto import boto.provider +import collections import tempfile import random import smtplib import datetime import re +import io import email.mime.multipart import email.mime.base import email.mime.text @@ -57,6 +59,7 @@ import email.encoders import gzip import threading import locale +import sys from boto.compat import six, StringIO, urllib, encodebytes from contextlib import contextmanager @@ -1098,3 +1101,82 @@ def parse_host(hostname): else: return hostname.split(':', 1)[0] +def print_to_fd(*objects, **kwargs): + """A Python 2/3 compatible analogue to the print function. + + This function writes text to a file descriptor as the + builtin print function would, favoring utf-8 encoding. + Arguments and return values are the same as documented in + the Python 2 print function. + """ + def _get_args(**kwargs): + """Validates keyword arguments that would be used in Print + Valid keyword arguments, mirroring print(), are 'sep', + 'end', and 'file'. These must be of types string, string, + and file / file interface respectively. + Returns the above kwargs of the above types. + """ + expected_keywords = collections.OrderedDict([ + ('sep', ' '), + ('end', '\n'), + ('file', sys.stdout)]) + + for key, value in kwargs.items(): + if key not in expected_keywords: + error_msg = ( + '{} is not a valid keyword argument. ' + 'Please use one of: {}') + raise KeyError( + error_msg.format( + key, + ' '.join(expected_keywords.keys()))) + else: + expected_keywords[key] = value + + return expected_keywords.values() + + def _get_byte_strings(*objects): + """Gets a `bytes` string for each item in list of printable objects.""" + byte_objects = [] + for item in objects: + if not isinstance(item, (six.binary_type, six.text_type)): + # If the item wasn't bytes or unicode, its __str__ method + # should return one of those types. + item = str(item) + + if isinstance(item, six.binary_type): + byte_objects.append(item) + else: + # The item should be unicode. If it's not, ensure_binary() + # will throw a TypeError. + byte_objects.append(six.ensure_binary(item)) + return byte_objects + + sep, end, file = _get_args(**kwargs) + sep = six.ensure_binary(sep) + end = six.ensure_binary(end) + data = _get_byte_strings(*objects) + data = sep.join(data) + data += end + write_to_fd(file, data) + + +def write_to_fd(fd, data): + """Write given data to given file descriptor, doing any conversions needed""" + if six.PY2: + fd.write(data) + return + # PY3 logic: + if isinstance(data, bytes): + if ((hasattr(fd, 'mode') and 'b' in fd.mode) or + isinstance(fd, io.BytesIO)): + fd.write(data) + elif hasattr(fd, 'buffer'): + fd.buffer.write(data) + else: + fd.write(six.ensure_text(data)) + elif 'b' in fd.mode: + fd.write(six.ensure_binary(data)) + else: + fd.write(data) + |