def map_copy_deep(source_map, destiny_map): """ Copies the contents of the source map to the destiny map. This mode provides a deep copy, using a recursive approach. :type source_map: Dictionary :param source_map: The source map of the copy. :type destiny_map: Dictionary :param destiny_map: The destiny map of the copy. """ # copies the current source map to the destiny map map_copy(source_map, destiny_map) # iterates over all the source map items for source_key, source_value in legacy.iteritems(source_map): # retrieves the source value type source_value_type = type(source_value) # in case the source value type is not a dictionary # continues the loop, nothing to be done in the # current iteration if not source_value_type == dict: continue # creates the destiny value map and sets the # destiny value in the destiny map destiny_value = {} destiny_map[source_key] = destiny_value # copies the source value (map) to the destiny value map_copy_deep(source_value, destiny_value)
def map_copy_deep(source_map, destiny_map): """ Copies the contents of the source map to the destiny map. This mode provides a deep copy, using a recursive approach. @type source_map: Dictionary @param source_map: The source map of the copy. @type destiny_map: Dictionary @param destiny_map: The destiny map of the copy. """ # copies the current source map to the destiny map map_copy(source_map, destiny_map) # iterates over all the source map items for source_key, source_value in legacy.iteritems(source_map): # retrieves the source value type source_value_type = type(source_value) # in case the source value type is not a dictionary # continues the loop, nothing to be done in the # current iteration if not source_value_type == dict: continue # creates the destiny value map and sets the # destiny value in the destiny map destiny_value = {} destiny_map[source_key] = destiny_value # copies the source value (map) to the destiny value map_copy_deep(source_value, destiny_value)
def __object_flush_topper(instances_list): """ Flushes (clears) the temporary "topper" map in all the instances in the given list. @type instances_list: List @param instances_list: The list of instances to have the "topper" map cleared. """ # iterates over all the instances in the # instances list (to clear the "topper" map) for instance in instances_list: # in case the instance does not # contain the topper map if not __object_has_attr(instance, TOPPER_VALUE): # continues th loop continue # retrieves the "topper" map for # the current instance _topper = __object_get_attr(instance, TOPPER_VALUE) # iterates over all the "topper" map # items (to set them in the instance) for key, value in legacy.iteritems(_topper): # sets the item in the instance __object_set_attr(instance, key, value) # deletes the (temporary) "topper" # map value __object_del_attr(instance, TOPPER_VALUE)
def url_encode(attributes_map=None, attributes_list=None, plus_encoding=False): """ Encodes the given attributes into url encoding. The attributes may be either provided as a map or alternatively as a sequence of key value tuples. @type attributes_map: Dictionary @param attributes_map: The map of attributes to be encoded using url encoding, if this value is defined the attributes list is not going to be used. @type attributes_list: List @param attributes_list: The list of key and value tuples that are going to be processed as the attributes. @type plus_encoding: bool @param plus_encoding: If the plus encoding should be used. @rtype: String @return: The encoded attributes string. """ # retrieves the quote method to be used quote_method = plus_encoding and quote_plus or quote # creates a string buffer to hold the encoded attribute values string_buffer = string_buffer_util.StringBuffer() # retrieves the reference to the proper items sequence to be used # notice that the attributes map has preference to the list version items = legacy.iteritems( attributes_map) if attributes_map else attributes_list # sets the is first flag, that is going to be used in the iteration # cycle to define the first iteration (exceptional iteration) is_first = True # iterates over all the attribute keys and values to be able to # quote their values and append the value to the buffer for attribute_key, attribute_value in items: # quotes both the attribute key and value attribute_key_quoted = quote_method(attribute_key) attribute_value_quoted = quote_method(attribute_value) # in case it's is the first iteration if is_first: # unsets the is first flag is_first = False else: # writes the and continuation in the string buffer string_buffer.write("&") # adds the quoted key and value strings to the # string buffer string_buffer.write(attribute_key_quoted) string_buffer.write("=") string_buffer.write(attribute_value_quoted) # retrieves the encoded attributes from the string buffer encoded_attributes = string_buffer.get_value() # returns the encoded attributes return encoded_attributes
def _map_flatten_pairs(map): """ Retrieves the complete set of linear key to value pairs of the attributes of the provided map. Any dictionary based value of the provided map will be linearized using an extra recursion step. :type map: Dictionary :param map: The map that is the basis of the recursion step for the retrieval of the key value pairs. :rtype: Generator :return: A generator that yields the various key to value linear relations, using a recursive approach. """ # iterates over the complete set of key value pairs of the # provided map to verify if the pair is map based and if # that's the case run a new depth of recursion with a new # composite name, so that all relations are linearized for key, value in legacy.iteritems(map): is_class = hasattr(value, "__class__") is_map = is_class and issubclass(value.__class__, dict) if not is_map: yield key, value continue pairs = _map_flatten_pairs(value) for _key, _value in pairs: yield key + "." + _key, _value
def __object_flush_topper(instances_list): """ Flushes (clears) the temporary "topper" map in all the instances in the given list. :type instances_list: List :param instances_list: The list of instances to have the "topper" map cleared. """ # iterates over all the instances in the # instances list (to clear the "topper" map) for instance in instances_list: # in case the instance does not # contain the topper map if not __object_has_attr(instance, TOPPER_VALUE): # continues th loop continue # retrieves the "topper" map for # the current instance _topper = __object_get_attr(instance, TOPPER_VALUE) # iterates over all the "topper" map # items (to set them in the instance) for key, value in legacy.iteritems(_topper): # sets the item in the instance __object_set_attr(instance, key, value) # deletes the (temporary) "topper" # map value __object_del_attr(instance, TOPPER_VALUE)
def _map_flatten_pairs(map): """ Retrieves the complete set of linear key to value pairs of the attributes of the provided map. Any dictionary based value of the provided map will be linearized using an extra recursion step. @type map: Dictionary @param map: The map that is the basis of the recursion step for the retrieval of the key value pairs. @rtype: Generator @return: A generator that yields the various key to value linear relations, using a recursive approach. """ # iterates over the complete set of key value pairs of the # provided map to verify if the pair is map based and if # that's the case run a new depth of recursion with a new # composite name, so that all relations are linearized for key, value in legacy.iteritems(map): is_class = hasattr(value, "__class__") is_map = is_class and issubclass(value.__class__, dict) if not is_map: yield key, value; continue pairs = _map_flatten_pairs(value) for _key, _value in pairs: yield key + "." + _key, _value
def url_encode(attributes_map = None, attributes_list = None, plus_encoding = False): """ Encodes the given attributes into url encoding. The attributes may be either provided as a map or alternatively as a sequence of key value tuples. @type attributes_map: Dictionary @param attributes_map: The map of attributes to be encoded using url encoding, if this value is defined the attributes list is not going to be used. @type attributes_list: List @param attributes_list: The list of key and value tuples that are going to be processed as the attributes. @type plus_encoding: bool @param plus_encoding: If the plus encoding should be used. @rtype: String @return: The encoded attributes string. """ # retrieves the quote method to be used quote_method = plus_encoding and quote_plus or quote # creates a string buffer to hold the encoded attribute values string_buffer = string_buffer_util.StringBuffer() # retrieves the reference to the proper items sequence to be used # notice that the attributes map has preference to the list version items = legacy.iteritems(attributes_map) if attributes_map else attributes_list # sets the is first flag, that is going to be used in the iteration # cycle to define the first iteration (exceptional iteration) is_first = True # iterates over all the attribute keys and values to be able to # quote their values and append the value to the buffer for attribute_key, attribute_value in items: # quotes both the attribute key and value attribute_key_quoted = quote_method(attribute_key) attribute_value_quoted = quote_method(attribute_value) # in case it's is the first iteration if is_first: # unsets the is first flag is_first = False else: # writes the and continuation in the string buffer string_buffer.write("&") # adds the quoted key and value strings to the # string buffer string_buffer.write(attribute_key_quoted) string_buffer.write("=") string_buffer.write(attribute_value_quoted) # retrieves the encoded attributes from the string buffer encoded_attributes = string_buffer.get_value() # returns the encoded attributes return encoded_attributes
def map_normalize(item, operation=None): """ Normalizes the provided map/item, applying the reduce operation to each of the items. In case no operation is provided, the default reduce map operation is used. This operation may be used to convert "complex" type based maps into simplified type based maps. :type item: Object :param item: The map/item to be normalized. :type operation: Method :param operation: The operation used for normalization (reduce operation). :rtype: Object :return: The normalized map, resulting from the normalization of each of its items. """ # sets the (reduce) operation, defaulting # to reduce map in case none is defined operation = operation or _map_reduce # retrieves the type for the current # item in order to percolate it appropriately _type = type(item) # in case the current item is a sequence # must normalize all of its elements if _type in (list, tuple): return [map_normalize(value, operation) for value in item] # in case the current item is a map # must create a new map with the result # of the normalization of all the elements elif _type == dict: # creates the item map to be populated # with the normalized values _item = {} # iterates over all the items to normalize # them and sets them in the new items map for key, value in legacy.iteritems(item): _item[key] = map_normalize(value, operation) return _item # otherwise must be a "single" item and the # (reduce) operation must be performed on it else: return operation(item)
def map_normalize(item, operation = None): """ Normalizes the provided map/item, applying the reduce operation to each of the items. In case no operation is provided, the default reduce map operation is used. This operation may be used to convert "complex" type based maps into simplified type based maps. @type item: Object @param item: The map/item to be normalized. @type operation: Method @param operation: The operation used for normalization (reduce operation). @rtype: Object @return: The normalized map, resulting from the normalization of each of its items. """ # sets the (reduce) operation, defaulting # to reduce map in case none is defined operation = operation or _map_reduce # retrieves the type for the current # item in order to percolate it appropriately _type = type(item) # in case the current item is a sequence # must normalize all of its elements if _type in (list, tuple): return [map_normalize(value, operation) for value in item] # in case the current item is a map # must create a new map with the result # of the normalization of all the elements elif _type == dict: # creates the item map to be populated # with the normalized values _item = {} # iterates over all the items to normalize # them and sets them in the new items map for key, value in legacy.iteritems(item): _item[key] = map_normalize(value, operation) return _item # otherwise must be a "single" item and the # (reduce) operation must be performed on it else: return operation(item)
def map_duplicate(item): """ Duplicates the provided item (map) creating a new structure with duplicated references both for sequences (list and tuples) and for maps. This function is useful in order to avoid reference overlapping in data structures. :type item: Object :param item: The item to be used as reference for duplication this should be a map at the initial call of the function. :rtype: item: Object :return: The duplicated data structure with all the references replicated in the sequences and maps. """ # retrieves the type for the current # item in order to percolate it appropriately _type = type(item) # in case the current item is a sequence # must "copy" all of its elements if _type in (list, tuple): return [map_duplicate(value) for value in item] # in case the current item is a map # must create a new map with the result # of the copy of all the elements elif _type == dict: # creates the item map to be populated # with the copied values _item = {} # iterates over all the items to copy # them and sets them in the new items map for key, value in legacy.iteritems(item): _item[key] = map_duplicate(value) return _item # otherwise must be a "single" item and the # (reduce) operation must be performed on it else: return item
def map_duplicate(item): """ Duplicates the provided item (map) creating a new structure with duplicated references both for sequences (list and tuples) and for maps. This function is useful in order to avoid reference overlapping in data structures. @type item: Object @param item: The item to be used as reference for duplication this should be a map at the initial call of the function. @rtype: item: Object @return: The duplicated data structure with all the references replicated in the sequences and maps. """ # retrieves the type for the current # item in order to percolate it appropriately _type = type(item) # in case the current item is a sequence # must "copy" all of its elements if _type in (list, tuple): return [map_duplicate(value) for value in item] # in case the current item is a map # must create a new map with the result # of the copy of all the elements elif _type == dict: # creates the item map to be populated # with the copied values _item = {} # iterates over all the items to copy # them and sets them in the new items map for key, value in legacy.iteritems(item): _item[key] = map_duplicate(value) return _item # otherwise must be a "single" item and the # (reduce) operation must be performed on it else: return item
def __object_flatten_to_one_map(base_map, instance, flattening_map): """ Auxiliary function that provides the mechanism to "map" the "to-one" relations in the instance according to the flattening map. :type base_map: Dictionary :param base_map: The base (top level) map to be used to set the top level attributes. :type instance: Object :param instance: The current concrete instance in the recursion set. :type flattening_map: Dictionary :param flattening_map: Map describing the structure for flattening. """ # iterates over all the keys and values # in the flattening map structure for key, value in legacy.iteritems(flattening_map): # retrieves the value type value_type = type(value) # tries to retrieves the instance value # sets the value to invalid in case there # is no such instance value (attribute) instance_value = __object_has_attr( instance, key) and __object_get_attr(instance, key) or None # in case the instance value is not set if instance_value == None: # continues the loop continue # in case the value if of type string # (a leaf of the flattening structure) if value_type == str: # sets the leaf value in the base map base_map[value] = instance_value # in case the value is of type dictionary # (defined to one relation) elif value_type == dict: # "flattens" the to one instance relation (recursion) __object_flatten_to_one_map(base_map, instance_value, value)
def __object_flatten_to_one_map(base_map, instance, flattening_map): """ Auxiliary function that provides the mechanism to "map" the "to-one" relations in the instance according to the flattening map. @type base_map: Dictionary @param base_map: The base (top level) map to be used to set the top level attributes. @type instance: Object @param instance: The current concrete instance in the recursion set. @type flattening_map: Dictionary @param flattening_map: Map describing the structure for flattening. """ # iterates over all the keys and values # in the flattening map structure for key, value in legacy.iteritems(flattening_map): # retrieves the value type value_type = type(value) # tries to retrieves the instance value # sets the value to invalid in case there # is no such instance value (attribute) instance_value = __object_has_attr(instance, key) and __object_get_attr(instance, key) or None # in case the instance value is not set if instance_value == None: # continues the loop continue # in case the value if of type string # (a leaf of the flattening structure) if value_type == str: # sets the leaf value in the base map base_map[value] = instance_value # in case the value is of type dictionary # (defined to one relation) elif value_type == dict: # "flattens" the to one instance relation (recursion) __object_flatten_to_one_map(base_map, instance_value, value)
def extend(self, map): # iterates over all the map items for key, value in legacy.iteritems(map): # sets the item in the structure self.__setitem__(key, value)
def map_extend(base_map, extension_map, override=True, recursive=False, copy_base_map=True): """ Extends the given map with the extension map, retrieving a map resulting of the merge of both maps. In case the override flag is set the values are overridden in case they already exist in the base map. An optional recursive flag allows the extension to be made recursive in case the value is a map. The base map may be changed or left untouched based on the copy base map flag. :type base_map: Dictionary :param base_map: The map to be used as base for the merge, should contain more values at the end of the merge. :type extension_map: Dictionary :param extension_map: The map to be used to extend the base one, this map may be recursively percolated if requested. :type override: bool :param override: If a value should be overridden in case it already exists in the base map. :type recursive: bool :param recursive: If a value should be extended in case it already exists in the base map (recursive extension). :type copy_base_map: bool :param copy_base_map: If the base map should be copied before being extended in order to avoid loss of data. :rtype: Dictionary :return: The map that result of the merge of both maps. """ # copies the base map to create the initial result map (optional) result_map = copy.copy(base_map) if copy_base_map else base_map # iterates over all the keys and values # in the extension map for key, value in legacy.iteritems(extension_map): # in case the override flag is not set and # the key already exists in the result map # must skip the current iteration loop if not override and key in result_map: continue # retrieves the data type for the current value in # iteration so that it may be used to determine the # need for the recursive percolated copy/merge value_type = type(value) # in case the value is a map and the recursive flag # is set, must try to extend the current item with # the new one, as expected if recursive and value_type == dict: # tries to retrieve the result map value, so # that it's possible to extend the current value # with the previously existing one, a default map # is created in case it does not exists so that # it's possible to used as the base for population result_map_value = result_map.get(key, {}) # extends the map that is currently in the result # map with the new value (recursive step), note # that a new map may have been created to be used # as the placeholder of new map values, this avoids # collision between sub-maps (would cause problems) value = map_extend(result_map_value, value, override=override, recursive=recursive, copy_base_map=copy_base_map) # sets the (extension) value in the result map result_map[key] = value # returns the result map return result_map
def map_extend( base_map, extension_map, override = True, recursive = False, copy_base_map = True ): """ Extends the given map with the extension map, retrieving a map resulting of the merge of both maps. In case the override flag is set the values are overridden in case they already exist in the base map. An optional recursive flag allows the extension to be made recursive in case the value is a map. The base map may be changed or left untouched based on the copy base map flag. @type base_map: Dictionary @param base_map: The map to be used as base for the merge, should contain more values at the end of the merge. @type extension_map: Dictionary @param extension_map: The map to be used to extend the base one, this map may be recursively percolated if requested. @type override: bool @param override: If a value should be overridden in case it already exists in the base map. @type recursive: bool @param recursive: If a value should be extended in case it already exists in the base map (recursive extension). @type copy_base_map: bool @param copy_base_map: If the base map should be copied before being extended in order to avoid loss of data. @rtype: Dictionary @return: The map that result of the merge of both maps. """ # copies the base map to create the initial result map (optional) result_map = copy.copy(base_map) if copy_base_map else base_map # iterates over all the keys and values # in the extension map for key, value in legacy.iteritems(extension_map): # in case the override flag is not set and # the key already exists in the result map # must skip the current iteration loop if not override and key in result_map: continue # retrieves the data type for the current value in # iteration so that it may be used to determine the # need for the recursive percolated copy/merge value_type = type(value) # in case the value is a map and the recursive flag # is set, must try to extend the current item with # the new one, as expected if recursive and value_type == dict: # tries to retrieve the result map value, so # that it's possible to extend the current value # with the previously existing one, a default map # is created in case it does not exists so that # it's possible to used as the base for population result_map_value = result_map.get(key, {}) # extends the map that is currently in the result # map with the new value (recursive step), note # that a new map may have been created to be used # as the placeholder of new map values, this avoids # collision between sub-maps (would cause problems) value = map_extend( result_map_value, value, override = override, recursive = recursive, copy_base_map = copy_base_map ) # sets the (extension) value in the result map result_map[key] = value # returns the result map return result_map