diff options
author | Lee Ball <43632885+catleeball@users.noreply.github.com> | 2019-03-27 15:00:56 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-27 15:00:56 -0700 |
commit | fbc316ec97c68033ef6a0ac4b9cadefecfcea4b8 (patch) | |
tree | cdf91b070d130e678779097acce0b1c42d711696 | |
parent | 62cb1573ff5de8513623c43b4b291045af6e88b4 (diff) | |
parent | 9e1cd3bd76e738d80630f1bd9160fd87c8eab865 (diff) | |
download | boto-fbc316ec97c68033ef6a0ac4b9cadefecfcea4b8.tar.gz |
Merge branch 'develop' into replace-get-utf8
-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 173594e2..12223849 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 @@ -1109,3 +1112,82 @@ def get_utf8able_str(s, errors='strict'): return s raise TypeError('not expecting type "%s"' % type(s)) + +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) |