1 from itertools import filterfalse
4 def unique_everseen(iterable, key=None):
5 "List unique elements, preserving order. Remember all elements ever seen."
6 # unique_everseen('AAAABBBCCDAABBB') --> A B C D
7 # unique_everseen('ABBCcAD', str.lower) --> A B C D
11 for element in filterfalse(seen.__contains__, iterable):
15 for element in iterable:
22 # copied from more_itertools 8.8
23 def always_iterable(obj, base_type=(str, bytes)):
24 """If *obj* is iterable, return an iterator over its items::
27 >>> list(always_iterable(obj))
30 If *obj* is not iterable, return a one-item iterable containing *obj*::
33 >>> list(always_iterable(obj))
36 If *obj* is ``None``, return an empty iterable:
39 >>> list(always_iterable(None))
42 By default, binary and text strings are not considered iterable::
45 >>> list(always_iterable(obj))
48 If *base_type* is set, objects for which ``isinstance(obj, base_type)``
49 returns ``True`` won't be considered iterable.
52 >>> list(always_iterable(obj)) # Iterate over the dict's keys
54 >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit
57 Set *base_type* to ``None`` to avoid any special handling and treat objects
58 Python considers iterable as iterable:
61 >>> list(always_iterable(obj, base_type=None))
67 if (base_type is not None) and isinstance(obj, base_type):