meshed.scrap.cached_dag

class meshed.scrap.cached_dag.CachedDag(dag, cache=True, name=None)[source]

Wraps a DAG, using it to compute any of it’s var nodes from it’s dependents, with the capability of caching intermediate var nodes for later reuse.

>>> def add(a, b=1):
...     return a + b
>>> def mult(x, y=2):
...     return x * y
>>> def subtract(a, b=4):
...     return a - b
>>> from meshed import code_to_dag
>>>
>>> @code_to_dag(func_src=locals())
... def dag(w, ww, www):
...     x = mult(w, ww)
...     y = add(x, www)
...     z = subtract(x, y)
>>> print(dag.dot_digraph_ascii())  
            │
            │
            ▼
          ┌──────────┐
ww=   ──▶ │   mult   │
          └──────────┘
            │
            │
            ▼

               x       ─┐
                        │
            │           │
            │           │
            ▼           │
          ┌──────────┐  │
www=  ──▶ │   add    │  │
          └──────────┘  │
            │           │
            │           │
            ▼           │
                        │
               y=       │
                        │
            │           │
            │           │
            ▼           │
          ┌──────────┐  │
          │ subtract │ ◀┘
          └──────────┘
            │
            │
            ▼

               z
>>> from inspect import signature
>>> g = CachedDag(dag)
>>> signature(g)
<Signature (k, /, **input_kwargs)>

We can get ww because it has a default:

(TODO: This (and further tests) stopped working since code_to_dag was enhanced with the ability to use the wrapped function’s signature to determine the signature of the output dag. Need to fix this.)

>>> g('ww')
2

But we can’t get y because we don’t have what it depends on:

>>> g('y')
Traceback (most recent call last):
    ...
TypeError: The input_kwargs of a dag call is missing 1 required argument: 'w'

It needs a w?! No, it needs an x! But to get an x you need a w, and…

>>> g('x')
Traceback (most recent call last):
    ...
TypeError: The input_kwargs of a dag call is missing 1 required argument: 'w'

So let’s give it a w!

>>> g('x', w=3)  # == 3 * 2 ==
6

And now this works:

>>> g('x')
6

because

>>> g.cache
{'x': 6}

and this will work too:

>>> g('y')
7
>>> g.cache
{'x': 6, 'y': 7}

But this is something we need to handle better!

>>> g('x', w=10)
6

This is happending because there’s already a x in the cache, and it takes precedence. This would be okay if consider CachedDag as a low level object that is never actually used by a user. But we need to protect the user from such effects!

First, we probably should cache inputs too.

The we can: - Make computation take precedence over cache, overwriting the existing cache

with the new resulting values

  • Allow the user to declare the entire cache, or just some variables in it,

as write-once, to avoid creating bugs with the above proposal.

  • Cache multiple paths (lru_cache style) for different input combinations

roots_for(node)[source]

The set of roots that lead to node.

>>> from meshed.makers import code_to_dag
>>> @code_to_dag
... def dag():
...     x = mult(w, ww)
...     y = add(x, www)
...     z = subtract(x, y)
>>> print(dag.synopsis_string())
w,ww -> mult -> x
x,www -> add -> y
x,y -> subtract -> z
>>> g = CachedDag(dag)
>>> sorted(g.roots_for('x'))
['w', 'ww']
>>> sorted(g.roots_for('y'))
['w', 'ww', 'www']
class meshed.scrap.cached_dag.NoOverwritesDict[source]

A dict where you’re not allowed to write to a key that already has a value in it.

>>> d = NoOverwritesDict(a=1, b=2)
>>> d
{'a': 1, 'b': 2}

Writing is allowed, in new keys

>>> d['c'] = 3
>>> d
{'a': 1, 'b': 2, 'c': 3}

It’s also okay to write into an existing key if the value it holds is identical. In fact, the write doesn’t even happen.

>>> d['b'] = 2

But if we try to write a different value…

>>> d['b'] = 22  
Traceback (most recent call last):
    ...
cached_dag.OverWritesNotAllowedError: The b key already exists and you're not allowed to change its value
exception meshed.scrap.cached_dag.NotAllowed[source]

To use to indicate that something is not allowed

exception meshed.scrap.cached_dag.OverWritesNotAllowedError[source]

Error to raise when a writes to existing keys are not allowed

meshed.scrap.cached_dag.cached_dag_test()[source]

Covering issue https://github.com/i2mint/meshed/issues/34 about “CachedDag.cache should be populated with inputs that it was called on”