Skip to content

Decorators that Capture Data

memlist(data, skip=False)

Remembers input/output of a function in python list.

Parameters:

Name Type Description Default
data List

a list to push received data into

required
skip bool

skips the calculation if kwargs appear in data already

False

Example

from memo import memlist

data = []

@memlist(data=data)
def simulate(a, b):
    return {"result": a + b}

# The `@memlist` decorator will allow the inputs/outputs to
# be saved in the provided `data` list.
for a in range(5):
    for b in range(10):
        simulate(a=a, b=b)

assert len(data) == 50

# If we keep running more loops the list will grow.
for a in range(6, 10 + 1):
    for b in range(11, 20 + 1):
        simulate(a=a, b=b)

assert len(data) == 100
Source code in memo/_base.py
def memlist(data: List, skip: bool = False):
    """
    Remembers input/output of a function in python list.

    Arguments:
        data: a list to push received data into
        skip: skips the calculation if kwargs appear in data already

    Example

    ```python
    from memo import memlist

    data = []

    @memlist(data=data)
    def simulate(a, b):
        return {"result": a + b}

    # The `@memlist` decorator will allow the inputs/outputs to
    # be saved in the provided `data` list.
    for a in range(5):
        for b in range(10):
            simulate(a=a, b=b)

    assert len(data) == 50

    # If we keep running more loops the list will grow.
    for a in range(6, 10 + 1):
        for b in range(11, 20 + 1):
            simulate(a=a, b=b)

    assert len(data) == 100
    ```
    """

    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            # We might be able to skip if the parameters
            # already appear in the dataset.
            if skip and _contains(kwargs, data):
                return None
            data.append({**kwargs, **result})
            return result

        return wrapper

    return decorator

memfile(filepath, skip=False)

Remembers input/output of a function in a jsonl file on disk.

Parameters:

Name Type Description Default
filepath str

path to write data to

required
skip bool

skips the calculation if kwargs appear in data already

False
from memo import memfile

@memfile(filepath="tmpfile.jsonl")
def simulate(a, b):
    return {"result": a + b}

for a in range(5):
    for b in range(10):
        simulate(a=a, b=b)
Source code in memo/_base.py
def memfile(filepath: str, skip: bool = False):
    """
    Remembers input/output of a function in a jsonl file on disk.

    Arguments:
        filepath: path to write data to
        skip: skips the calculation if kwargs appear in data already

    ```python
    from memo import memfile

    @memfile(filepath="tmpfile.jsonl")
    def simulate(a, b):
        return {"result": a + b}

    for a in range(5):
        for b in range(10):
            simulate(a=a, b=b)
    ```
    """

    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            if skip:
                if pathlib.Path(filepath).exists():
                    with open(filepath, "r") as f:
                        datalist = [orjson.loads(line) for line in list(f)]
                else:
                    datalist = []
            with open(filepath, "a") as f:
                if skip and _contains(kwargs, datalist):
                    return None
                ser = orjson.dumps(
                    {**kwargs, **result},
                    option=orjson.OPT_NAIVE_UTC | orjson.OPT_SERIALIZE_NUMPY,
                )
                f.write(ser.decode("utf-8") + "\n")
            return result

        return wrapper

    return decorator

memfunc(callback)

Remembers input/output of a function by printing.

Parameters:

Name Type Description Default
callback Callable

callback function that receives a dictionary with logged info

required
from memo import memfunc, memlist

data = []

@memlist(data=data)
@memfunc(callback=print)
def simulate(a, b):
    return {"result": a + b}

for a in range(5):
    for b in range(10):
        simulate(a=a, b=b)

# You should now see print statements, and this holds:
assert len(data) == 50
Source code in memo/_base.py
def memfunc(callback: Callable):
    """
    Remembers input/output of a function by printing.

    Arguments:
        callback: callback function that receives a dictionary with logged info

    ```python
    from memo import memfunc, memlist

    data = []

    @memlist(data=data)
    @memfunc(callback=print)
    def simulate(a, b):
        return {"result": a + b}

    for a in range(5):
        for b in range(10):
            simulate(a=a, b=b)

    # You should now see print statements, and this holds:
    assert len(data) == 50
    ```
    """

    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            callback({**kwargs, **result})
            return result

        return wrapper

    return decorator

memweb(url)

Remembers input/output of a function by sending it over http to an endpoint.

Important

Note that this decorator requires an extra dependeny. Ensure it is installed properly by running either;

python -m pip install "memo[web]"

You can also install it by installing all optional dependencies.

python -m pip install "memo[all]"

Parameters:

Name Type Description Default
url str

web url to post json to

required
Source code in memo/_http.py
def memweb(url: str):
    """
    Remembers input/output of a function by sending it over http to an endpoint.

    Important:
        Note that this decorator requires an extra dependeny. Ensure it is installed
        properly by running either;

        ```
        python -m pip install "memo[web]"
        ```

        You can also install it by installing all optional dependencies.

        ```
        python -m pip install "memo[all]"
        ```

    Arguments:
        url: web url to post json to
    """

    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            with httpx.Client() as client:
                _ = client.post(url, data={**kwargs, **result})
            return result

        return wrapper

    return decorator