code: def always_iterable(obj, base_type=(str, bytes)):
      
      if obj is None:
          return iter(())
  
      if (base_type is not None) and isinstance(obj, base_type):
          return iter((obj,))
  
      try:
          return iter(obj)
      except TypeError:
          return iter((obj,))
docs: If *obj* is iterable, return an iterator over its items::
  
          >>> obj = (1, 2, 3)
          >>> list(always_iterable(obj))
          [1, 2, 3]
  
      If *obj* is not iterable, return a one-item iterable containing *obj*::
  
          >>> obj = 1
          >>> list(always_iterable(obj))
          [1]
  
      If *obj* is ``None``, return an empty iterable:
  
          >>> obj = None
          >>> list(always_iterable(None))
          []
  
      By default, binary and text strings are not considered iterable::
  
          >>> obj = 'foo'
          >>> list(always_iterable(obj))
          ['foo']
  
      If *base_type* is set, objects for which ``isinstance(obj, base_type)``
      returns ``True`` won't be considered iterable.
  
          >>> obj = {'a': 1}
          >>> list(always_iterable(obj))  # Iterate over the dict's keys
          ['a']
          >>> list(always_iterable(obj, base_type=dict))  # Treat dicts as a unit
          [{'a': 1}]
  
      Set *base_type* to ``None`` to avoid any special handling and treat objects
      Python considers iterable as iterable:
  
          >>> obj = 'foo'
          >>> list(always_iterable(obj, base_type=None))
          ['f', 'o', 'o']