Skip to content

Commit

Permalink
feat: conditional_data_trans, instance_checker, and an issue #10.
Browse files Browse the repository at this point in the history
  • Loading branch information
thorwhalen committed Jun 11, 2022
1 parent 008d7b4 commit b2e8dac
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 10 deletions.
1 change: 1 addition & 0 deletions dol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def ihead(store, n=1):
regroupby,
igroupby,
not_a_mac_junk_path,
instance_checker,
)

from dol.trans import (
Expand Down
30 changes: 20 additions & 10 deletions dol/trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -2069,6 +2069,22 @@ class for it's purpose of transforming stores more conveniently.
}


def _conditional_data_trans(v, condition, data_trans):
if condition(v):
return data_trans(v)
return v


from dol.util import Pipe

@store_decorator
def conditional_data_trans(store=None, *, condition, data_trans):
_data_trans = partial(
_conditional_data_trans, condition=condition, data_trans=data_trans
)
return Pipe(data_trans, wrap_kvs(store, obj_of_data=_data_trans))


@store_decorator
def add_path_get(store=None, *, name=None, path_type: type = tuple):
"""
Expand Down Expand Up @@ -2181,9 +2197,7 @@ def __getitem__(self, k):
return store_cls

# TODO: Should we keep add_path_get, or add "read_only" flag to add_path_access?
# TODO: store['a','b','c'] works, but store['a']['b','c'] doesn't because the "path
# accessibility" doesn't carry on to values by default. See doctest on how to make it
# happen an integrate here with one argument only: value condition.
# TODO: See https://github.com/i2mint/dol/issues/10
@store_decorator
def add_path_access(store=None, *, name=None, path_type: type = tuple):
"""Make nested stores (read/write) accessible through key paths (iterable of keys).
Expand Down Expand Up @@ -2317,14 +2331,10 @@ def add_path_access(store=None, *, name=None, path_type: type = tuple):
For example, if you wanted to wrap all mappings recursively, you could:
>>> from typing import Mapping
>>> from dol.trans import wrap_kvs
>>> def add_path_access_if_mapping(v):
... if isinstance(v, Mapping):
... return wrap_kvs(
... add_path_access(v),
... obj_of_data=add_path_access_if_mapping
>>> from dol.util import instance_checker
>>> add_path_access_if_mapping = conditional_data_trans(
... condition=instance_checker(Mapping), data_trans=add_path_access
... )
... return v
>>> s = add_path_access_if_mapping({'a': {'b': {'c': 42}}})
>>> s['a', 'b', 'c']
42
Expand Down
22 changes: 22 additions & 0 deletions dol/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,35 @@
from functools import partialmethod, partial, WRAPPER_ASSIGNMENTS
from types import MethodType


# monkey patching WRAPPER_ASSIGNMENTS to get "proper" wrapping (adding defaults and kwdefaults
wrapper_assignments = (*WRAPPER_ASSIGNMENTS, '__defaults__', '__kwdefaults__')

update_wrapper = partial(_update_wrapper, assigned=wrapper_assignments)
wraps = partial(_wraps, assigned=wrapper_assignments)


def _isinstance(obj, class_or_tuple):
"""The same as the builtin isinstance, but without the position only restriction,
allowing us to use partial to define filter functions for specific types
"""
return isinstance(obj, class_or_tuple)


def instance_checker(*types):
"""Makes a filter function that checks the type of an object.
>>> f = instance_checker(int, float)
>>> f(1)
True
>>> f(1.0)
True
>>> f('1.0')
False
"""
return partial(_isinstance, class_or_tuple=types)


def not_a_mac_junk_path(path: str):
"""A function that will tell you if the path is not a mac junk path/
More precisely, doesn't end with '.DS_Store' or have a `__MACOSX` folder somewhere
Expand Down

0 comments on commit b2e8dac

Please sign in to comment.