Beispiel #1
0
    def _get_source(data, source_path):
        #print(source_path, target_path)
        source_prefixes = source_path[:-1]
        source_key = source_path[-1]
        yield source_key  # yield this because we don't know if move or copy
        source = data
        for node_key in source_prefixes:
            if node_key in source:
                source = source[node_key]
            else:
                # don't move if no source
                msg = f'did not find {node_key!r} in {tuple(source.keys())}'
                raise exc.NoSourcePathError(msg)

        # for move
        yield (node_key
               if source_prefixes else AtomicDictOperations.__empty_node_key)

        if source_key not in source:
            try:
                msg = f'did not find {source_key!r} in {tuple(source.keys())}'
                raise exc.NoSourcePathError(msg)
            except AttributeError as e:
                raise TypeError(
                    f'value at {source_path} has wrong type!{lj(source)}'
                ) from e
                #log.debug(f'{source_path}')

        yield source
Beispiel #2
0
    def _derive(data, derives, source_key_optional=True, allow_empty=False):
        # OLD
        """ derives is a list with the following structure
            [[[source-path, ...], derive-function, [target-path, ...]], ...]

        """
        # TODO this is an implementaiton of copy that has semantics for handling lists
        for source_path, function, target_paths in derives:
            source_prefixes = source_path[:-1]
            source_key = source_path[-1]
            source = data
            failed = False
            for i, node_key in enumerate(source_prefixes):
                log.debug(lj(source))
                if node_key in source:
                    source = source[node_key]
                else:
                    msg = f'did not find {node_key} in {source.keys()}'
                    if not i:
                        log.error(msg)
                        failed = True
                        break
                    raise exc.NoSourcePathError(msg)
                if isinstance(source, list) or isinstance(source, tuple):
                    new_source_path = source_prefixes[i + 1:] + [source_key]
                    new_target_paths = [tp[i + 1:] for tp in target_paths]
                    new_derives = [(new_source_path, function, new_target_paths)]
                    for sub_source in source:
                        _DictTransformer.derive(sub_source, new_derives,
                                                source_key_optional=source_key_optional)

                    return  # no more to do here

            if failed:
                continue  # sometimes things are missing we continue to others

            if source_key not in source:
                msg = f'did not find {source_key} in {source.keys()}'
                if source_key_optional:
                    return logd.info(msg)
                else:
                    raise exc.NoSourcePathError(msg)

            source_value = source[source_key]

            new_values = function(source_value)
            if len(new_values) != len(target_paths):
                log.debug(f'{source_paths} {target_paths}')
                raise TypeError(f'wrong number of values returned for {function}\n'
                                f'was {len(new_values)} expect {len(target_paths)}')
            #temp = b'__temporary'
            #data[temp] = {}  # bytes ensure no collisions
            for target_path, value in zip(target_paths, new_values):
                if (not allow_empty and
                    (value is None or
                     hasattr(value, '__iter__') and not len(value))):
                    raise ValueError(f'value to add to {target_path} may not be empty!')
                adops.add(data, target_path, value, fail_on_exists=True)
Beispiel #3
0
    def _get_source(data, source_path):
        #print(source_path, target_path)
        source_prefixes = source_path[:-1]
        source_key = source_path[-1]
        yield source_key  # yield this because we don't know if move or copy
        source = data
        for node_key in source_prefixes:
            if isinstance(source, dict):
                if node_key in source:
                    source = source[node_key]
                else:
                    # don't move if no source
                    msg = f'did not find {node_key!r} in {tuple(source.keys())}'
                    raise exc.NoSourcePathError(msg)
            elif is_list_or_tuple(source):
                if not isinstance(node_key, int):
                    raise TypeError(
                        f'Wrong type for node_key {type(node_key)} {node_key}. '
                        'Expected int.')
                source = source[
                    node_key]  # good good let the index errors flow through you
            else:
                raise TypeError(
                    f'Unsupported type {type(source)} for {lj(source)}')

        # for move
        yield (node_key
               if source_prefixes else AtomicDictOperations.__empty_node_key)

        if isinstance(source, dict):
            if source_key not in source:
                try:
                    msg = f'did not find {source_key!r} in {tuple(source.keys())}'
                    raise exc.NoSourcePathError(msg)
                except AttributeError as e:
                    raise TypeError(
                        f'value at {source_path} has wrong type!{lj(source)}'
                    ) from e
                    #log.debug(f'{source_path}')

        elif is_list_or_tuple(source):
            try:
                source[source_key]
            except IndexError as e:
                msg = f'There is not a {source_key}th value in {lj(source)}'
                raise exc.NoSourcePathError(msg) from e

        else:
            raise TypeError(
                f'Unsupported type {type(source)} for {lj(source)}')

        yield source