diff --git a/requests/__init__.py b/requests/__init__.py index 3d8188a7..f7924dc8 100644 --- a/requests/__init__.py +++ b/requests/__init__.py @@ -62,7 +62,8 @@ from .sessions import session, Session from .status_codes import codes from .exceptions import ( RequestException, Timeout, URLRequired, - TooManyRedirects, HTTPError, ConnectionError + TooManyRedirects, HTTPError, ConnectionError, + FileModeWarning, ) # Set default logging handler to avoid "No handler found" warnings. @@ -75,3 +76,8 @@ except ImportError: pass logging.getLogger(__name__).addHandler(NullHandler()) + +import warnings + +# FileModeWarnings go off per the default. +warnings.simplefilter('default', FileModeWarning, append=True) diff --git a/requests/exceptions.py b/requests/exceptions.py index 89135a80..ba0b910e 100644 --- a/requests/exceptions.py +++ b/requests/exceptions.py @@ -97,3 +97,18 @@ class StreamConsumedError(RequestException, TypeError): class RetryError(RequestException): """Custom retries logic failed""" + + +# Warnings + + +class RequestsWarning(Warning): + """Base warning for Requests.""" + pass + + +class FileModeWarning(RequestsWarning, DeprecationWarning): + """ + A file was opened in text mode, but Requests determined its binary length. + """ + pass diff --git a/requests/utils.py b/requests/utils.py index 4a8c6d7e..5975d0f1 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -29,7 +29,7 @@ from .compat import (quote, urlparse, bytes, str, OrderedDict, unquote, is_py2, basestring) from .cookies import RequestsCookieJar, cookiejar_from_dict from .structures import CaseInsensitiveDict -from .exceptions import InvalidURL +from .exceptions import InvalidURL, FileModeWarning _hush_pyflakes = (RequestsCookieJar,) @@ -60,7 +60,22 @@ def super_len(o): except io.UnsupportedOperation: pass else: - return os.fstat(fileno).st_size + filesize = os.fstat(fileno).st_size + + # Having used fstat to determine the file length, we need to + # confirm that this file was opened up in binary mode. + if 'b' not in o.mode: + warnings.warn(( + "Requests has determined the content-length for this " + "request using the binary size of the file: however, the " + "file has been opened in text mode (i.e. without the 'b' " + "flag in the mode). This may lead to an incorrect " + "content-length. In Requests 3.0, support will be removed " + "for files in text mode."), + FileModeWarning + ) + + return filesize if hasattr(o, 'getvalue'): # e.g. BytesIO, cStringIO.StringIO