def test(): '''Test basic workings of `is_iterable`.''' iterables = [ [1, 2, 3], (1, 2), {}, (), [[1]], 'asdfasdf', '' ] non_iterables = [ dict, list, type, None, True, False, Exception, lambda x: x ] for iterable in iterables: assert is_iterable(iterable) for non_iterable in non_iterables: assert not is_iterable(non_iterable)
def reverse_with_set_values(d, sort=False): ''' Reverse the dict, with the values of the new dict being sets. Example: reverse_with_set_values({1: 2, 3: 4, 'meow': 2}) == \ {2: {1, 'meow'}, 4: {3}} Instead of a dict you may also input a tuple in which the first item is an iterable and the second item is either a key function or an attribute name. A dict will be constructed from these and used. If you'd like the result dict to be sorted, pass `sort=True`, and you'll get a sorted `OrderedDict`. You can also specify the sorting key function or attribute name as the `sort` argument. ''' ### Pre-processing input: ################################################# # # if hasattr(d, 'items'): # `d` is a dict fixed_dict = d else: # `d` is not a dict assert cute_iter_tools.is_iterable(d) and len(d) == 2 iterable, key_function_or_attribute_name = d assert cute_iter_tools.is_iterable(iterable) key_function = comparison_tools.process_key_function_or_attribute_name( key_function_or_attribute_name ) fixed_dict = {key: key_function(key) for key in iterable} # # ### Finished pre-processing input. ######################################## new_dict = {} for key, value in fixed_dict.items(): if value not in new_dict: new_dict[value] = [] new_dict[value].append(key) # Making into sets: for key, value in new_dict.copy().items(): new_dict[key] = set(value) if sort: from python_toolbox import nifty_collections ordered_dict = nifty_collections.OrderedDict(new_dict) if isinstance(sort, (collections.Callable, str)): key_function = comparison_tools. \ process_key_function_or_attribute_name(sort) else: assert sort is True key_function = None ordered_dict.sort(key_function) return ordered_dict else: return new_dict
def reverse_with_set_values(d, sort=False): ''' Reverse the dict, with the values of the new dict being sets. Example: reverse_with_set_values({1: 2, 3: 4, 'meow': 2}) == \ {2: {1, 'meow'}, 4: {3}} Instead of a dict you may also input a tuple in which the first item is an iterable and the second item is either a key function or an attribute name. A dict will be constructed from these and used. If you'd like the result dict to be sorted, pass `sort=True`, and you'll get a sorted `OrderedDict`. You can also specify the sorting key function or attribute name as the `sort` argument. ''' ### Pre-processing input: ################################################# # # if hasattr(d, 'items'): # `d` is a dict fixed_dict = d else: # `d` is not a dict assert cute_iter_tools.is_iterable(d) and len(d) == 2 iterable, key_function_or_attribute_name = d assert cute_iter_tools.is_iterable(iterable) key_function = comparison_tools.process_key_function_or_attribute_name( key_function_or_attribute_name ) fixed_dict = {key: key_function(key) for key in iterable} # # ### Finished pre-processing input. ######################################## new_dict = {} for key, value in fixed_dict.iteritems(): if value not in new_dict: new_dict[value] = [] new_dict[value].append(key) # Making into sets: for key, value in new_dict.copy().iteritems(): new_dict[key] = set(value) if sort: from python_toolbox import nifty_collections ordered_dict = nifty_collections.OrderedDict(new_dict) if isinstance(sort, (collections.Callable, basestring)): key_function = comparison_tools. \ process_key_function_or_attribute_name(sort) else: assert sort is True key_function = None ordered_dict.sort(key_function) return ordered_dict else: return new_dict
def __init__(self, function): ''' Construct the `TempFunctionCallCounter`. For `function`, you may pass in either a function object, or a `(parent_object, function_name)` pair, or a `(getter, setter)` pair. ''' if cute_iter_tools.is_iterable(function): first, second = function if isinstance(second, str): actual_function = getattr(first, second) else: assert callable(first) and callable(second) actual_function = first( ) # `first` is the getter in this case. else: # not cute_iter_tools.is_iterable(function) assert callable(function) actual_function = function try: address = address_tools.object_to_string.get_address(function) parent_object_address, function_name = address.rsplit('.', 1) parent_object = address_tools.resolve(parent_object_address) except Exception: raise Exception("Couldn't obtain parent/name pair from " "function; supply one manually or " "alternatively supply a getter/setter pair.") first, second = parent_object, function_name self.call_counting_function = count_calls(actual_function) TempValueSetter.__init__(self, (first, second), value=self.call_counting_function)
def __init__(self, function): """ Construct the `TempFunctionCallCounter`. For `function`, you may pass in either a function object, or a `(parent_object, function_name)` pair, or a `(getter, setter)` pair. """ if cute_iter_tools.is_iterable(function): first, second = function if isinstance(second, basestring): actual_function = getattr(first, second) else: assert callable(first) and callable(second) actual_function = first() # `first` is the getter in this case. else: # not cute_iter_tools.is_iterable(function) assert callable(function) actual_function = function try: address = address_tools.object_to_string.get_address(function) parent_object_address, function_name = address.rsplit(".", 1) parent_object = address_tools.resolve(parent_object_address) except Exception: raise Exception( "Couldn't obtain parent/name pair from " "function; supply one manually or " "alternatively supply a getter/setter pair." ) first, second = parent_object, function_name self.call_counting_function = count_calls(actual_function) TempValueSetter.__init__(self, (first, second), value=self.call_counting_function)
def __init__(self, inputs=(), outputs=(), name=None): ''' Construct the emitter. `inputs` is a list of inputs, all of them must be emitters. `outputs` is a list of outputs, they must be either emitters or callables. `name` is a string name for the emitter. ''' assert cute_iter_tools.is_iterable(inputs) and \ cute_iter_tools.is_iterable(outputs) self._inputs = set() '''The emitter's inputs.''' self._outputs = set() '''The emitter's inputs.''' for output in outputs: self.add_output(output) self.__total_callable_outputs_cache = None ''' A cache of total callable outputs. This means the callable outputs of this emitter and any output emitters. ''' self._recalculate_total_callable_outputs() # We made sure to create the callable outputs cache before we add # inputs, so when we update their cache, it could use ours. for input in inputs: self.add_input(input) self.name = name '''The emitter's name.'''
def is_subclass(candidate, base_class): ''' Check if `candidate` is a subclass of `base_class`. You may pass in a tuple of base classes instead of just one, and it will check whether `candidate` is a subclass of any of these base classes. This has the advantage that it doesn't throw an exception if `candidate` is not a type. (Python issue 10569.) ''' # todo: disable ability to use nested iterables. if cute_iter_tools.is_iterable(base_class): return any(is_subclass(candidate, single_base_class) for single_base_class in base_class) elif not isinstance(candidate, (type, types.ClassType)): return False else: return issubclass(candidate, base_class)
def is_subclass(candidate, base_class): ''' Check if `candidate` is a subclass of `base_class`. You may pass in a tuple of base classes instead of just one, and it will check whether `candidate` is a subclass of any of these base classes. This has the advantage that it doesn't throw an exception if `candidate` is not a type. (Python issue 10569.) ''' # todo: disable ability to use nested iterables. if cute_iter_tools.is_iterable(base_class): return any( is_subclass(candidate, single_base_class) for single_base_class in base_class) elif not isinstance(candidate, type): return False else: return issubclass(candidate, base_class)
def get_equivalence_classes(iterable, key=None, container=set, *, use_ordered_dict=False, sort_ordered_dict=False): ''' Divide items in `iterable` to equivalence classes, using the key function. Each item will be put in a set with all other items that had the same result when put through the `key` function. Example: >>> get_equivalence_classes(range(10), lambda x: x % 3) {0: {0, 9, 3, 6}, 1: {1, 4, 7}, 2: {8, 2, 5}} Returns a `dict` with keys being the results of the function, and the values being the sets of items with those values. Alternate usages: Instead of a key function you may pass in an attribute name as a string, and that attribute will be taken from each item as the key. Instead of an iterable and a key function you may pass in a `dict` (or similar mapping) into `iterable`, without specifying a `key`, and the value of each item in the `dict` will be used as the key. Example: >>> get_equivalence_classes({1: 2, 3: 4, 'meow': 2}) {2: {1, 'meow'}, 4: {3}} If you'd like the result to be in an `OrderedDict`, specify `use_ordered_dict=True`, and the items will be ordered according to insertion order. If you'd like that `OrderedDict` to be sorted, pass in `sort_ordered_dict=True`. (It automatically implies `use_ordered_dict=True`.) You can also pass in a sorting key function or attribute name as the `sort_ordered_dict` argument. ''' from python_toolbox import comparison_tools ### Pre-processing input: ################################################# # # if key is None: if isinstance(iterable, collections.abc.Mapping): d = iterable else: try: d = dict(iterable) except ValueError: raise Exception( "You can't put in a non-dict without also supplying a " "`key` function. We need to know which key to use." ) else: # key is not None assert cute_iter_tools.is_iterable(iterable) key_function = comparison_tools.process_key_function_or_attribute_name( key ) d = {key: key_function(key) for key in iterable} # # ### Finished pre-processing input. ######################################## if use_ordered_dict or sort_ordered_dict: from python_toolbox import nifty_collections new_dict = nifty_collections.OrderedDict() else: new_dict = {} for key, value in d.items(): new_dict.setdefault(value, []).append(key) # Making into desired container: for key, value in new_dict.copy().items(): new_dict[key] = container(value) if sort_ordered_dict: if isinstance(sort_ordered_dict, (collections.abc.Callable, str)): key_function = comparison_tools. \ process_key_function_or_attribute_name(sort_ordered_dict) new_dict.sort(key_function) elif sort_ordered_dict is True: new_dict.sort() return new_dict else: return new_dict
def get_equivalence_classes(iterable, key=None, container=set, use_ordered_dict=False, sort_ordered_dict=False): ''' Divide items in `iterable` to equivalence classes, using the key function. Each item will be put in a set with all other items that had the same result when put through the `key` function. Example: >>> get_equivalence_classes(range(10), lambda x: x % 3) {0: {0, 9, 3, 6}, 1: {1, 4, 7}, 2: {8, 2, 5}} Returns a `dict` with keys being the results of the function, and the values being the sets of items with those values. Alternate usages: Instead of a key function you may pass in an attribute name as a string, and that attribute will be taken from each item as the key. Instead of an iterable and a key function you may pass in a `dict` (or similar mapping) into `iterable`, without specifying a `key`, and the value of each item in the `dict` will be used as the key. Example: >>> get_equivalence_classes({1: 2, 3: 4, 'meow': 2}) {2: {1, 'meow'}, 4: {3}} If you'd like the result to be in an `OrderedDict`, specify `use_ordered_dict=True`, and the items will be ordered according to insertion order. If you'd like that `OrderedDict` to be sorted, pass in `sort_ordered_dict=True`. (It automatically implies `use_ordered_dict=True`.) You can also pass in a sorting key function or attribute name as the `sort_ordered_dict` argument. ''' from python_toolbox import comparison_tools ### Pre-processing input: ################################################# # # if key is None: if isinstance(iterable, collections.Mapping): d = iterable else: try: d = dict(iterable) except ValueError: raise Exception( "You can't put in a non-dict without also supplying a " "`key` function. We need to know which key to use." ) else: # key is not None assert cute_iter_tools.is_iterable(iterable) key_function = comparison_tools.process_key_function_or_attribute_name( key ) d = dict((key, key_function(key)) for key in iterable) # # ### Finished pre-processing input. ######################################## if use_ordered_dict or sort_ordered_dict: from python_toolbox import nifty_collections new_dict = nifty_collections.OrderedDict() else: new_dict = {} for key, value in d.items(): new_dict.setdefault(value, []).append(key) # Making into desired container: for key, value in new_dict.copy().items(): new_dict[key] = container(value) if sort_ordered_dict: if isinstance(sort_ordered_dict, (collections.Callable, str)): key_function = comparison_tools. \ process_key_function_or_attribute_name(sort_ordered_dict) new_dict.sort(key_function) elif sort_ordered_dict is True: new_dict.sort() return new_dict else: return new_dict