def non_string_iterable(obj): """Return True if the object is iterable but is not a string type""" return hasattr(obj, '__iter__') and not isinstance(obj, str) def handle_seq_indx(seqtype, indx, lookup_func=None, lookup_args=(), require_inrange=True): if isinstance(indx, int): if indx < 0: indx += len(seqtype) if indx < 0 or indx >= len(seqtype): if require_inrange: raise IndexError("list index out of range") else: indx = max(indx, 0) indx = min(indx, len(seqtype)) return indx else: return indx elif isinstance(indx, slice): return range(*indx.indices(len(seqtype))) elif lookup_func is not None: args = lookup_args + (indx,) int_indx = lookup_func(*args) if int_indx < 0: raise KeyError(indx) else: return int_indx else: raise TypeError("expecting an integer index")