-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
35 changed files
with
1,612 additions
and
324 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,68 @@ | ||
# py-cachify | ||
# Py-Cachify | ||
|
||
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) | ||
[![PyPI version](https://badge.fury.io/py/py-cachify.svg)](https://badge.fury.io/py/py-cachify) | ||
[![Coverage Status](https://coveralls.io/repos/github/EzyGang/py-cachify/badge.png?branch=main)](https://coveralls.io/github/EzyGang/py-cachify?branch=main) | ||
<p align="center"> | ||
<a href="https://opensource.org/licenses/MIT" target="_blank"> | ||
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"> | ||
</a> | ||
<a href="https://badge.fury.io/py/py-cachify" target="_blank"> | ||
<img src="https://badge.fury.io/py/py-cachify.svg" alt="PyPI version"> | ||
</a> | ||
<a href="https://py-cachify.readthedocs.io/en/latest/?badge=latest" target="_blank"> | ||
<img src="https://readthedocs.org/projects/py-cachify/badge/?version=latest" alt="Documentation Status"> | ||
</a> | ||
</p> | ||
<p align="center"> | ||
<a href="https://github.com/EzyGang/py-cachify/actions/workflows/checks.yml/badge.svg" target="_blank"> | ||
<img src="https://github.com/EzyGang/py-cachify/actions/workflows/checks.yml/badge.svg" alt="Pre-build checks and Tests"> | ||
</a> | ||
<a href="https://github.com/EzyGang/py-cachify/actions/workflows/integration-tests.yml/badge.svg" target="_blank"> | ||
<img src="https://github.com/EzyGang/py-cachify/actions/workflows/integration-tests.yml/badge.svg" alt="Tests Status"> | ||
</a> | ||
<a href="https://coveralls.io/github/EzyGang/py-cachify?branch=main" target="_blank"> | ||
<img src="https://coveralls.io/repos/github/EzyGang/py-cachify/badge.png?branch=main" alt="Coverage Status"> | ||
</a> | ||
<a href="https://sonarcloud.io/summary/new_code?id=EzyGang_py-cachify" target="_blank"> | ||
<img src="https://sonarcloud.io/api/project_badges/measure?project=EzyGang_py-cachify&metric=reliability_rating" alt="Reliability Rating"> | ||
</a> | ||
</p> | ||
|
||
[![Homepage](https://github.githubassets.com/favicons/favicon-dark.png)](https://github.com/EzyGang/py-cachify) | ||
--- | ||
|
||
py-cachify is a library that provides small but useful cache-based utilities. | ||
**Documentation**: <a href="https://py-cachify.readthedocs.io/latest/" target="_blank">https://py-cachify.readthedocs.io/latest/</a> | ||
|
||
Some parts were heavily inspired by [douglasfarinelli's python-cachelock](https://github.com/douglasfarinelli/python-cachelock) lib, | ||
which is sadly no longer maintained. | ||
**Source Code**: <a href="https://github.com/EzyGang/py-cachify" target="_blank">https://github.com/EzyGang/py-cachify</a> | ||
|
||
## Features | ||
* Offers distributed cache-based locks and decorators around them | ||
* Offers convenient decorators to store function results in the cache | ||
* Works well in both sync and async environments | ||
* Fully type annotated | ||
* Has 100% test coverage | ||
* Has integration tests in place for the common scenarios | ||
* Backend agnostic (you can provide your own client as long as it matches the signature) | ||
* Supports Python from 3.8 and upward | ||
--- | ||
|
||
py-cachify is a small library that provides useful cache based utilities (caching, locks). | ||
|
||
py-cachify works well in both sync and async environments, has 100% test coverage, fully type annotated, | ||
is backend agnostic (you can provide your own client as long as it matches the signature), and supports Python from 3.8 and upward. | ||
|
||
It offers distributed (cache based) locks and decorators to lock function executions and storing their results in the cache. | ||
|
||
The key features are: | ||
|
||
* **Intuitive to write**: Great editor support. When applying decorators your IDE will still be able to autocomplete and highlight inline errors for applied functions. | ||
* **Fully type annotated**: You don't have to constantly look into the docs. Everything is type annotated and easy to understand out of the box. | ||
* **Short**: Minimize code duplication. Add just one line of code to implement a cache or lock on your function. | ||
* **Start simple**: The simplest example adds only a couple of lines of code: initialize a library and use the needed utility. | ||
* **Backend agnostic**: Use whatever cache-backend you want to use. Py-cachify is not forcing you into anything. | ||
* **Test coverage**: Has 100% test coverage and supports Python 3.8+ | ||
|
||
--- | ||
|
||
## Quick navigation | ||
To help you get started, see [Initial setup](setup.md). | ||
To help you get started, see [Initial setup](setup.md) and [Tutorial](tutorial/index.md). | ||
|
||
Examples can be found [here](examples.md). | ||
|
||
More information about [`cached` decorator](cached-decorator.md), [`once` decorator](once-decorator.md), | ||
and [locks](locks.md) can be found on linked pages. | ||
For a detailed API reference [API] | ||
|
||
## Contributing | ||
|
||
If you'd like to contribute, please first discuss the changes using Issues, and then don't hesitate to shoot a PR which will be reviewed shortly. | ||
|
||
## License | ||
|
||
This project is licensed under the MIT License - see the [LICENSE](https://github.com/EzyGang/py-cachify/blob/main/LICENSE) file for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import re | ||
|
||
from mkdocs import plugins | ||
from mkdocs.config.defaults import MkDocsConfig | ||
from mkdocs.structure.nav import Navigation | ||
from paginate import Page | ||
|
||
|
||
@plugins.event_priority(-100) | ||
def on_post_page(output_content: str, page: Page, config: MkDocsConfig) -> str: | ||
|
||
return re.sub( | ||
r'(\/(.+\(\))\/)', r'<code style="background-color: var(--md-code-bg-color);padding: 0 .2941176471em;">\2</code>', | ||
output_content, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# Cached - Dynamic cache key arguments | ||
|
||
Continuing our previous example, we'll customize the key in the decorator. | ||
|
||
The full code will look like this: | ||
|
||
```python | ||
import asyncio | ||
|
||
from py_cachify import init_cachify, cached | ||
|
||
|
||
# here we are initializing py-cachify to use an in-memory cache | ||
init_cachify() | ||
|
||
|
||
# notice that we now have {a} and {b} in the cache key | ||
@cached(key='sum_two-{a}-{b}') | ||
async def sum_two(a: int, b: int) -> int: | ||
# Let's put print here to see what was the function called with | ||
print(f'Called with {a} {b}') | ||
return a + b | ||
|
||
|
||
async def main() -> None: | ||
# Call the function first time with (5, 5) | ||
print(f'First call result: {await sum_two(5, 5)}') | ||
|
||
# And we will call it again to make sure it's not called but the result is the same | ||
print(f'Second call result: {await sum_two(5, 5)}') | ||
|
||
# Now we will call it with different args to make sure the function is indeed called for another set of arguments | ||
print(f'Third call result: {await sum_two(5, 10)}') | ||
|
||
|
||
if __name__ == '__main__': | ||
asyncio.run(main()) | ||
``` | ||
|
||
|
||
## Understanding what has changed | ||
|
||
As you can see, we now have `{a}` and `{b}` inside our key, | ||
what it allows py-cachify to do is dynamically craft a key for a function the decorator is being applied to. | ||
|
||
This way it will cache the result for each set of arguments instead of creating just one key. | ||
|
||
Note, that in this current example key `'sum_two-{}-{}'` will have the same effect. | ||
Providing a not named placeholders is supported to allow creating dynamic cache keys even for the functions that accept `*args, **kwargs` as its arguments. | ||
|
||
We have also modified our main function to showcase the introduced changes. | ||
|
||
## Let's run our code | ||
|
||
After running the example: | ||
<!-- termynal --> | ||
```bash | ||
# Run our example | ||
$ python main.py | ||
|
||
# The ouput will be | ||
Called with 5 5 | ||
First call result: 10 | ||
Second call result: 10 | ||
Called with 5 10 | ||
Third call result: 15 | ||
|
||
``` | ||
|
||
As you can see, the function result is being cached based on the arguments provided. | ||
|
||
## What's next | ||
|
||
In the next chapter we'll learn what other parameters `@cached()` decorator has. |
Oops, something went wrong.