Skip to content

Enabling (optional) KeyPath ability to write when path doesn't already exist #16

@thorwhalen

Description

@thorwhalen

Random Notes

Possibly related:

Old dict path get stuff

glom

remap

What we (might) want

Something like collections.defaultdict but where the factory needs to be contextual (because different levels may have different stores.

What happens if I do:

s[1][2][3][4] = val

and s[1] doesn't have the 2 key?

Maybe this:

s[1][2] = EmptyStoreType2()
s[1][2][3] = EmptyStoreType3()
s[1][2][3][4] = val 

and now non of the stores above are empty anymore.

Some code to think of

# NOTE: perhaps use glom and/or remap?

from typing import Mapping
from i2 import mk_sentinel

def is_a_mapping(store, prev_path):
    return isinstance(store, Mapping)


def mk_a_dict(prev_path):  # should we include current_key too?
    return dict()
    
    
def _split_path(
    store, path: tuple, store_to_explore_further=is_a_mapping, prev_path=()
):
    """Separate part of the path that has a value in store and the part that doesn't"""
    if not path:  # path is empty
        return prev_path, (), ()
    # else:
    key, *next_path = path
    val = store.get(key, NoSuchKey)
    if val is NoSuchKey:
        # if key doesn't exist, everything from there on is the store-invalid part
        return prev_path, (key,) + next_path
    else:
        # if key doesn't exist, everything from there on is the store-invalid part
        if store_to_explore_further(val, prev_path):
            return _advance_to_first_non_existing_key(
                val, 
                next_path, 
                store_to_explore_further, 
                prev_path=prev_path + (key,)
            ):
        else:
            return prev_path, key, next_path
            
        
NoSuchKey = mk_sentinel('NoSuchKey')

def default_store(
    store, 
    path: tuple, 
    store_to_explore_further=is_a_mapping, 
    mk_new_store=mk_a_dict  # factory part
):
#     k = k.split(store.path_sep) (if k is string)
    prev_path, problem_path = _advance_to_first_non_existing_key(
        store, path, store_to_explore_further, mk_new_store
    )
    current_path = prev_path
    current_store = store[current_path]
    for key in problem_path:
        current_path = current_path + (key,)
        current_store[key] = mk_new_store(current_path)
        current_store = current_store[key]
        

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions