def processor()

in libcloud/common/nttcis.py [0:0]


def processor(mapping, name=None):
    """
    Closure that keeps the deepcopy of the original dict
    converted to XML current.
    :param mapping: The converted XML to dict/lists
    :type mapping: ``dict``
    :param name: (Optional) what becomes the class name if provided
    :type: ``str``
    :return: Nothing
    """
    mapping = mapping
    # the map_copy will have keys deleted after the key and value are processed
    map_copy = deepcopy(mapping)

    def add_items(key, value, name=None):
        """
        Add items to the global attr dict, then delete key, value from map copy
        :param key: from the process function becomes the attribute name
        :type key: ``str``
        :param value: The value of the property and may be a dict
        :type value: ``str``
        :param name: Name of class, often same as key
        :type: name" ``str``
        """
        if name in attrs:
            attrs[name].update({key: value})
        elif name is not None:
            attrs[name] = value

        else:
            attrs.update({key: value})
        # trim the copy of the mapping
        if key in map_copy:
            del map_copy[key]
        elif key in map_copy[name]:
            del map_copy[name][key]
            if len(map_copy[name]) == 0:
                del map_copy[name]

    def handle_map(map, name):
        tmp = {}
        types = [type(x) for x in map.values()]
        if XmlListConfig not in types and XmlDictConfig not in types and dict not in types:
            return map

        elif XmlListConfig in types:
            result = handle_seq(map, name)
            return result
        else:
            for k, v in map.items():
                if isinstance(v, str):
                    tmp.update({k: v})
                if isinstance(v, dict):
                    cls = build_class(k.capitalize(), v)
                    tmp.update({k: cls})
                elif isinstance(v, XmlDictConfig):
                    cls = build_class(k.capitalize(), v)
                    return (k, cls)
            return tmp

    def handle_seq(seq, name):
        tmp = {}
        if isinstance(seq, list):
            tmp = []
            for _ in seq:
                cls = build_class(name.capitalize(), _)
                tmp.append(cls)
            return tmp
        for k, v in seq.items():
            if isinstance(v, MutableSequence):
                for _ in v:
                    if isinstance(_, Mapping):
                        types = [type(x) for x in _.values()]
                        if XmlDictConfig in types:
                            result = handle_map(_, k)
                            if isinstance(result, tuple):
                                tmp.update({result[0]: result[1]})
                            else:
                                tmp.update({k: result})
                        else:
                            tmp_list = [build_class(k.capitalize(), i) for i in v]
                            tmp[k] = tmp_list
            elif isinstance(v, str):
                tmp.update({k: v})
        return tmp

    def build_class(key, value):
        klass = class_factory(key.capitalize(), value)
        return klass(value)

    def process(mapping):
        """
        This function is recursive, creating attributes for the class factory
        by taking apart the elements in the  dictionary.  Thus, the calls to
        handle_seq or handle_map
        :param mapping: the dictionary converted from XML
        :return: itself (recursive)
        """
        for k1, v1 in mapping.items():
            if isinstance(v1, Mapping):
                types = [type(v) for v in v1.values()]
                if MutableSequence not in types and dict not in types:
                    result = handle_map(v1, k1)
                    cls = build_class(k1.capitalize(), result)
                    add_items(k1, cls)
                elif XmlListConfig in types:
                    result = handle_seq(v1, k1)
                    cls = build_class(list(v1)[0], result)
                    add_items(k1, cls)
                elif dict in types:
                    result = handle_map(v1, k1)
                    cls = build_class(k1.capitalize(), result)
                    add_items(k1, cls, k1)
            elif isinstance(v1, list):
                tmp1 = {}
                tmp2 = {}
                tmp2[k1] = []
                for i, j in enumerate(v1):
                    if isinstance(j, dict):
                        key = list(j)[0]
                        result = handle_map(j, key)
                        tmp1[k1 + str(i)] = build_class(k1, result)
                        tmp2[k1].append(tmp1[k1 + str(i)])
                if tmp2:
                    add_items(k1, tmp2[k1], k1)
            elif isinstance(v1, str):
                add_items(k1, v1)

    if len(map_copy) == 0:
        return 1
    return process(mapping)