semvec/pypi-packages huggingface dataset:
jundo 0.1.2
A general purpose library to help implement undo.
License: MIT
Requires Python: >=3.6

# jundo

A general purpose library to help implement undo for existing objects.

The main idea is that if one limits oneself to objects that can be viewed as
JSON-like data structures (ie. are composed of strings, numbers, lists and
dictionaries) it is possible to record changes in a completely generic way,
and use these recordings to reconstruct objects or to roll back changes, for
example to implement undo.

A key requirement was that the model objects must be completely decoupled from
the recording mechanism, and will not need any awareness of it.

The way this is implemented here is through proxy objects: instead of modifying
the original model objects directly, one uses proxy objects that mimic the
model object, allowing the proxy to pass on change information (deltas) to an
undo manager.

The undo manager collects change deltas (and their inverses), and can apply
them to the original model object when undo or redo is requested.

The model object is passed to the undo manager with the
`undoManager.setModel(model)`, which returns a proxy for the model. Client code
must use the proxy object instead of the model to modify the model. Here is an
example:

    >>> model = [1, 2, 3, {"a": 123}]
    >>> um = UndoManager()
    >>> proxy = um.setModel(model)
    >>> # Modifications must be done within a change set context:
    >>> with um.changeSet(title="replace list item"):
    ...     proxy[1] = 2000
    ...
    >>> model[1]
    2000
    >>> um.undo()
    >>> model[1]
    2
    >>> um.redo()
    >>> model[1]
    2000
    >>> with um.changeSet(title="replace nested dict item"):
    ...     proxy[3]["a"] = 456
    ...
    >>> model[3]["a"]
    456
    >>> um.undo()
    >>> model[3]["a"]
    123

In this example, only Python list and dict objects are used as containers, but
any type of Mapping or Sequence (in the collections.abc-sense) can be used, or
any object type that uses attribute access to modify its model data. See the
Examples folder for more elaborate examples.

Sets are also supported.

To support model objects that are not JSON-like, custom proxy classes can be
registered via the `registerUndoProxy()` function. 

### Acknowledgments

The approach implemented here is inspired by Raph Levien's ideas, as he wrote
them down [here](https://github.com/trufont/trufont/pull/614#issuecomment-446309637).
It also draws inspiration from [jsonpatch](http://jsonpatch.com/).
thornfield 1.5.1
Advanced caching in python
License: MIT
Requires Python: >=3.7

# `thornfield`: Advanced caching in python

[![Build Status](https://travis-ci.com/drorvinkler/thornfield.svg?branch=main)](https://travis-ci.com/drorvinkler/thornfield)
[![codecov](https://codecov.io/gh/drorvinkler/thornfield/branch/main/graph/badge.svg)](https://codecov.io/gh/drorvinkler/thornfield)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

## Installation
```pip install thornfield```

## Usage
Choose the cache storage you want to use - in-memory, redis and postgresql are currently implemented.
You can use a different storage by implementing the `Cache` interface.

Then, use the `cached` decorator to annotate the function being cached:
```
cacher = Cacher(cache_factory_func)

@cacher.cached
def foo():
    ...
```

The decorator supports:
* Setting an expiration time for the cached values.
* Caching only values that match a constraint (e.g. not `None`).
* Using only some of the function parameters as keys for the cache.
* Caching async functions.

#### Caching only some parameters
In case you don't want to use all the parameters of the function as cache key,
you can the `Cached` or `NotCached` types:
```
from thornfield.typing import Cached, NotCached

@cached
def request(url: str, token: str, timeout: NotCached[int]):
    ...


@cached
async def request_async(url: Cached[str], timeout: int, callback):
    ...
```

#### Caching abstract methods
In order to avoid adding the same decorator to all implementations of an
abstract method, you can use `cache_method` as follows:
```
class Base(ABC):
    def __init__(self):
        cacher.cache_method(do_something)

    @abstractmethod
    def do_something(self):
        pass
```

## Cache Factories
In the `cache_factories` package you can find cache factories for Redis and PostgreSQL.
They both cache each function to a different table (in PostgreSQL, db in Redis).

Their `create` method can be passed as `cache_impl` to the constructor of `Cacher`.