|  | """ | 
|  | Providing iterator functions that are not in all version of Python we support. | 
|  | Where possible, we try to use the system-native version and only fall back to | 
|  | these implementations if necessary. | 
|  | """ | 
|  |  | 
|  | import collections | 
|  | import itertools | 
|  | import sys | 
|  | import warnings | 
|  |  | 
|  |  | 
|  | def is_iterable(x): | 
|  | "A implementation independent way of checking for iterables" | 
|  | try: | 
|  | iter(x) | 
|  | except TypeError: | 
|  | return False | 
|  | else: | 
|  | return True | 
|  |  | 
|  | def is_iterator(x): | 
|  | """An implementation independent way of checking for iterators | 
|  |  | 
|  | Python 2.6 has a different implementation of collections.Iterator which | 
|  | accepts anything with a `next` method. 2.7+ requires and `__iter__` method | 
|  | as well. | 
|  | """ | 
|  | if sys.version_info >= (2, 7): | 
|  | return isinstance(x, collections.Iterator) | 
|  | return isinstance(x, collections.Iterator) and hasattr(x, '__iter__') | 
|  |  | 
|  | def product(*args, **kwds): | 
|  | warnings.warn("django.utils.itercompat.product is deprecated; use the native version instead", | 
|  | PendingDeprecationWarning) | 
|  | return itertools.product(*args, **kwds) | 
|  |  | 
|  | def all(iterable): | 
|  | warnings.warn("django.utils.itercompat.all is deprecated; use the native version instead", | 
|  | DeprecationWarning) | 
|  | return builtins.all(iterable) | 
|  |  | 
|  | def any(iterable): | 
|  | warnings.warn("django.utils.itercompat.any is deprecated; use the native version instead", | 
|  | DeprecationWarning) | 
|  | return builtins.any(iterable) |