82 lines
2.1 KiB
Python
82 lines
2.1 KiB
Python
|
# ABCs for containers were moved to their own module
|
||
|
try:
|
||
|
from collections.abc import Mapping, Set, Sequence
|
||
|
except ImportError:
|
||
|
from collections import Mapping, Set, Sequence
|
||
|
|
||
|
|
||
|
# Python 3 has no basestring, lets test it.
|
||
|
try:
|
||
|
basestring # attempt to evaluate basestring
|
||
|
|
||
|
def isstr(s):
|
||
|
return isinstance(s, basestring)
|
||
|
|
||
|
def to_unicode(s):
|
||
|
return unicode(s)
|
||
|
|
||
|
except NameError:
|
||
|
def isstr(s):
|
||
|
return isinstance(s, str)
|
||
|
|
||
|
def to_unicode(s):
|
||
|
return s
|
||
|
|
||
|
|
||
|
def is_list(obj):
|
||
|
return isinstance(obj, Sequence) and not isstr(obj)
|
||
|
|
||
|
|
||
|
def is_map(obj):
|
||
|
return isinstance(obj, Mapping)
|
||
|
|
||
|
|
||
|
def get_keys(obj):
|
||
|
if is_map(obj):
|
||
|
return obj.keys()
|
||
|
elif is_list(obj):
|
||
|
return range(len(obj))
|
||
|
|
||
|
|
||
|
def get_iter(iterable):
|
||
|
if isinstance(iterable, Mapping):
|
||
|
return iterable.items()
|
||
|
else:
|
||
|
return enumerate(iterable)
|
||
|
|
||
|
|
||
|
def get_subclasses(cls, _subclasses_yielded=None):
|
||
|
"""
|
||
|
Generator recursively yielding all subclasses of the passed class (in
|
||
|
depth-first order).
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
cls : type
|
||
|
Class to find all subclasses of.
|
||
|
_subclasses_yielded : set
|
||
|
Private parameter intended to be passed only by recursive invocations of
|
||
|
this function, containing all previously yielded classes.
|
||
|
"""
|
||
|
|
||
|
if _subclasses_yielded is None:
|
||
|
_subclasses_yielded = set()
|
||
|
|
||
|
# If the passed class is old- rather than new-style, raise an exception.
|
||
|
if not hasattr(cls, '__subclasses__'):
|
||
|
raise TypeError('Old-style class "%s" unsupported.' % cls.__name__)
|
||
|
|
||
|
# For each direct subclass of this class
|
||
|
for subclass in cls.__subclasses__():
|
||
|
# If this subclass has already been yielded, skip to the next.
|
||
|
if subclass in _subclasses_yielded:
|
||
|
continue
|
||
|
|
||
|
# Yield this subclass and record having done so before recursing.
|
||
|
yield subclass
|
||
|
_subclasses_yielded.add(subclass)
|
||
|
|
||
|
# Yield all direct subclasses of this class as well.
|
||
|
for subclass_subclass in get_subclasses(subclass, _subclasses_yielded):
|
||
|
yield subclass_subclass
|