@@ -17,3 +17,57 @@ def unique_everseen(iterable, key=None):
17
17
if k not in seen :
18
18
seen_add (k )
19
19
yield element
20
+
21
+
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::
25
+
26
+ >>> obj = (1, 2, 3)
27
+ >>> list(always_iterable(obj))
28
+ [1, 2, 3]
29
+
30
+ If *obj* is not iterable, return a one-item iterable containing *obj*::
31
+
32
+ >>> obj = 1
33
+ >>> list(always_iterable(obj))
34
+ [1]
35
+
36
+ If *obj* is ``None``, return an empty iterable:
37
+
38
+ >>> obj = None
39
+ >>> list(always_iterable(None))
40
+ []
41
+
42
+ By default, binary and text strings are not considered iterable::
43
+
44
+ >>> obj = 'foo'
45
+ >>> list(always_iterable(obj))
46
+ ['foo']
47
+
48
+ If *base_type* is set, objects for which ``isinstance(obj, base_type)``
49
+ returns ``True`` won't be considered iterable.
50
+
51
+ >>> obj = {'a': 1}
52
+ >>> list(always_iterable(obj)) # Iterate over the dict's keys
53
+ ['a']
54
+ >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit
55
+ [{'a': 1}]
56
+
57
+ Set *base_type* to ``None`` to avoid any special handling and treat objects
58
+ Python considers iterable as iterable:
59
+
60
+ >>> obj = 'foo'
61
+ >>> list(always_iterable(obj, base_type=None))
62
+ ['f', 'o', 'o']
63
+ """
64
+ if obj is None :
65
+ return iter (())
66
+
67
+ if (base_type is not None ) and isinstance (obj , base_type ):
68
+ return iter ((obj ,))
69
+
70
+ try :
71
+ return iter (obj )
72
+ except TypeError :
73
+ return iter ((obj ,))
0 commit comments