add doc for misc.super_len

This commit is contained in:
Prodesire 2017-12-14 20:18:32 +08:00
parent 613a1f3404
commit d7250ae7c8
2 changed files with 25 additions and 13 deletions

View File

@ -89,3 +89,15 @@ Miscellanea
>>> foo()
>>> foo()
>>>
.. py:function:: pydu.misc.super_len(obj)
Get length of object which has attribute named `__len__`, `len`, `fileno`, `tell`,
such as `list`, `tuple`, `dict`, `file` and so on.
>>> from pydu.misc import super_len
>>> super_len([1, 2])
2
>>> super_len(open('test', 'w'))
0

View File

@ -162,27 +162,27 @@ def memoize_when_activated(fun):
# https://github.com/requests/requests/blob/master/requests/utils.py
def super_len(o):
def super_len(obj):
total_length = None
current_position = 0
if hasattr(o, '__len__'):
total_length = len(o)
if hasattr(obj, '__len__'):
total_length = len(obj)
elif hasattr(o, 'len'):
total_length = o.len
elif hasattr(obj, 'len'):
total_length = obj.len
elif hasattr(o, 'fileno'):
elif hasattr(obj, 'fileno'):
try:
fileno = o.fileno()
fileno = obj.fileno()
except io.UnsupportedOperation:
pass
else:
total_length = os.fstat(fileno).st_size
if hasattr(o, 'tell'):
if hasattr(obj, 'tell'):
try:
current_position = o.tell()
current_position = obj.tell()
except (OSError, IOError):
# This can happen in some weird situations, such as when the file
# is actually a special file descriptor like stdin. In this
@ -191,16 +191,16 @@ def super_len(o):
if total_length is not None:
current_position = total_length
else:
if hasattr(o, 'seek') and total_length is None:
if hasattr(obj, 'seek') and total_length is None:
# StringIO and BytesIO have seek but no useable fileno
try:
# seek to end of file
o.seek(0, 2)
total_length = o.tell()
obj.seek(0, 2)
total_length = obj.tell()
# seek back to current position to support
# partially read file-like objects
o.seek(current_position or 0)
obj.seek(current_position or 0)
except (OSError, IOError):
total_length = 0