def _listlike_guard(obj, name, iterable_only=False, log_warning=True):
required_type = (_Iterable,) if iterable_only else (_Container, _Iterable)<EOL>required_type_name = '<STR_LIT>'.join(t.__name__ for t in required_type)<EOL>if not isinstance(obj, required_type):<EOL><INDENT>raise ValueError('<STR_LIT>'.format(name, required_type_name))<EOL><DEDENT>if isinstance(obj, str):<EOL><INDENT>if log_warning:<EOL><INDENT>_logger.warning('<STR_LIT>'.format(name))<EOL><DEDENT>return (obj,)<EOL><DEDENT>return obj<EOL>
We frequently require passed objects to support iteration or
containment expressions, but not be strings. (Of course, strings
support iteration and containment, but not usefully.)  If the passed
object is a string, we'll wrap it in a tuple and return it. If it's
already an iterable, we'll return it as-is. Otherwise, we'll raise a
TypeError.