Merge pull request #3535 from nateprewitt/3339_avoid_getvalues

avoid use of getvalues in super_len
This commit is contained in:
Cory Benfield
2016-09-14 08:10:28 +01:00
committed by GitHub
2 changed files with 45 additions and 6 deletions
+17 -6
View File
@@ -45,7 +45,7 @@ def dict_to_sequence(d):
def super_len(o):
total_length = 0
total_length = None
current_position = 0
if hasattr(o, '__len__'):
@@ -54,10 +54,6 @@ def super_len(o):
elif hasattr(o, 'len'):
total_length = o.len
elif hasattr(o, 'getvalue'):
# e.g. BytesIO, cStringIO.StringIO
total_length = len(o.getvalue())
elif hasattr(o, 'fileno'):
try:
fileno = o.fileno()
@@ -87,7 +83,22 @@ def super_len(o):
# is actually a special file descriptor like stdin. In this
# instance, we don't know what the length is, so set it to zero and
# let requests chunk it instead.
current_position = total_length
if total_length is not None:
current_position = total_length
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 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
return max(0, total_length - current_position)
+28
View File
@@ -66,6 +66,34 @@ class TestSuperLen:
assert super_len(fd) == 4
assert len(recwarn) == warnings_num
def test_super_len_with__len__(self):
foo = [1,2,3,4]
len_foo = super_len(foo)
assert len_foo == 4
def test_super_len_with_no__len__(self):
class LenFile(object):
def __init__(self):
self.len = 5
assert super_len(LenFile()) == 5
def test_super_len_with_tell(self):
foo = StringIO.StringIO('12345')
assert super_len(foo) == 5
foo.read(2)
assert super_len(foo) == 3
def test_super_len_with_fileno(self):
with open(__file__, 'rb') as f:
length = super_len(f)
file_data = f.read()
assert length == len(file_data)
def test_super_len_with_no_matches(self):
"""Ensure that objects without any length methods default to 0"""
assert super_len(object()) == 0
class TestToKeyValList: