diff --git a/requests/utils.py b/requests/utils.py index 3b43ad7d..227f7c4b 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -86,17 +86,17 @@ def super_len(o): # let requests chunk it instead. if total_length is not None: current_position = total_length + else: + if hasattr(o, 'seek') and total_length is None: + # StringIO and BytesIO have seek but no useable fileno - if hasattr(o, 'seek') and total_length is None: - # StringIO and BytesIO have seek but no useable fileno + # seek to end of file + o.seek(0, 2) + total_length = o.tell() - # seek to end of file - o.seek(0, 2) - total_length = o.tell() - - # seek back to current position to support - # partially read file-like objects - o.seek(current_position or 0) + # seek back to current position to support + # partially read file-like objects + o.seek(current_position or 0) if total_length is None: total_length = 0 diff --git a/tests/test_utils.py b/tests/test_utils.py index 7e0b4f28..9fd0bcf4 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -51,6 +51,18 @@ class TestSuperLen: assert super_len(BoomFile()) == 0 + @pytest.mark.parametrize('error', [IOError, OSError]) + def test_super_len_tell_ioerror(self, error): + """Ensure that if tell gives an IOError super_len doesn't fail""" + class NoLenBoomFile(object): + def tell(self): + raise error() + + def seek(self, offset, whence): + pass + + assert super_len(NoLenBoomFile()) == 0 + def test_string(self): assert super_len('Test') == 4