Metadata-Version: 2.5
Name: Cachalot
Version: 2.0.0
Summary: Minimal persistent memoization cache
Project-URL: Homepage, https://radek-sprta.gitlab.io/Cachalot/
Project-URL: Repository, https://gitlab.com/radek-sprta/Cachalot
Project-URL: Documentation, https://radek-sprta.gitlab.io/Cachalot/
Author-email: Radek Sprta <mail@radeksprta.eu>
License: MIT
License-File: LICENSE
Keywords: cache,memoization
Classifier: Development Status :: 5 - Production/Stable
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.11
Requires-Dist: jsonpickle
Requires-Dist: tinydb>=4
Description-Content-Type: text/markdown

# Cachalot [![PyPI version](https://badge.fury.io/py/cachalot.svg)](https://badge.fury.io/py/cachalot) [![Pipeline status](https://gitlab.com/radek-sprta/cachalot/badges/master/pipeline.svg)](https://gitlab.com/radek-sprta/cachalot/commits/master) [![Coverage report](https://gitlab.com/radek-sprta/cachalot/badges/master/coverage.svg)](https://gitlab.com/radek-sprta/cachalot/commits/master)[![Downloads](http://pepy.tech/badge/cachalot)](http://pepy.tech/project/cachalot)

Cachalot is a minimal persistent memoization cache. It provides a decorator, that stores function result for future use. Perfect for heavy computations and I/O operation (such as web requests). On backend, it uses TinyDB for storage.

## Features
- Simple usage via decorator
- Persistent caching
- Optional in-memory caching
- Key expiration
- Maximum cache size, to prevent bloat

## Installation
Cachalot requires Python 3.11 or newer to run.

**Python package**

You can easily install Cachalot using pip:

`pip3 install cachalot`

**Manual**

Alternatively, to get the latest development version, you can clone this repository and then manually install it:

```
git clone git@gitlab.com:radek-sprta/cachalot.git
cd cachalot
pip install .
```

## Usage
```python
from cachalot import Cache


@Cache()
def expensive_function():
    return expensive_calculation()
```

### Advanced usage
```python
from cachalot import Cache


@Cache(
    path="cache.json",
    timeout=3600,
    size=5000,
    filesize=1_000_000,
    retry=True,
    renew_on_read=True,
)
def expensive_function():
    return expensive_calculation()
```

- `path`: Path to the database file. Defaults to .cache.json. If None, the cache is kept in memory.
- `timeout`: How long should the data be cached in seconds. Defaults to 0 (infinite).
- `size`: Maximum number of keys cached. Defaults to 0 (infinite).
- `filesize`: Maximum size of database file in bytes. Defaults to 0 (infinite). Cannot be used with an in-memory cache.
- `retry`: Retry if the cached result is None. Defaults to False.
- `renew_on_read`: Renew the entry, i.e refresh the entry timestamp on reads. Defaults to True.

### Caveats
- Cache keys are the function's module and qualified name plus positional and keyword arguments (keyword order irrelevant). Defaults are not applied: `f(1)` and `f(1, b=2)` differ even if `2` is the default, and so do positional and keyword calls. For methods, `self` is intentionally excluded, so all instances share results.
- Functions with the same qualified name share a key: lambdas in the same scope, and functions made by the same factory (e.g. `make_scaler(2)` and `make_scaler(3)`). Closure state is not part of the key; use named top-level functions instead.
- Arguments are encoded with jsonpickle, which is not canonical: sets may encode in a different order between processes, causing misses.
- When `size` is exceeded, the least recently used entry is evicted. Use is the last read with `renew_on_read=True`, otherwise the last write.
- Results larger than `filesize` bytes are not cached (the entry is skipped, not stored).
- Cache objects on the same file within one process share one database. The file is still not locked; do not share it between concurrent processes or threads.
- Values are stored with jsonpickle; loading a cache file can execute code. Only use cache files from trusted sources.

### Manually deleting entries
If you want to manually invalidate an entry, you can calculate the hash of the function call and then pass it to the `remove` method.

```python
cache = Cache()


@cache
def expensive_function(arg):
    return expensive_calculation(arg)


key = cache.calculate_hash(expensive_function)("arg")
cache.remove(key)
```

For more information, see [documentation][documentation].

## Contributing
For information on how to contribute to the project, please check the [Contributor's Guide][contributing]

## Contact
[mail@radeksprta.eu](mailto:mail@radeksprta.eu)

[incoming+radek-sprta/cachalot@gitlab.com](mailto:incoming+radek-sprta/cachalot@gitlab.com)

## License
MIT License

## Credits
This package was created with [Cookiecutter][cookiecutter] and the [python-cookiecutter][python-cookiecutter] project template. Inspired by [Cashier][cachier]

## Contributors ✨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tr>
    <td align="center"><a href="https://gitlab.com/Evidlo"><img src="https://secure.gravatar.com/avatar/2670a8eba83e9233eb254fa48a12249f?s=80&d=identicon?s=100" width="100px;" alt=""/><br /><sub><b>Evan Widloski</b></sub></a><br /><a href="https://gitlab.com/radek-sprta/Cachalot/commits/master" title="Code">💻</a></td>
    <td align="center"><a href="https://gitlab.com/sasa-tomic"><img src="https://assets.gitlab-static.net/uploads/-/system/user/avatar/4715393/avatar.png?s=100" width="100px;" alt=""/><br /><sub><b>Saša Tomić</b></sub></a><br /><a href="https://gitlab.com/radek-sprta/Cachalot/commits/master" title="Code">💻</a></td>
  </tr>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

[cachier]: https://github.com/atmb4u/cashier
[contributing]: https://gitlab.com/radek-sprta/cachalot/blob/master/CONTRIBUTING.md
[cookiecutter]: https://github.com/audreyr/cookiecutter
[documentation]: https://radek-sprta.gitlab.io/cachalot
[python-cookiecutter]: https://gitlab.com/radek-sprta/python-cookiecutter
