Skip to content

Commit

Permalink
Full docs refactor, setup is done
Browse files Browse the repository at this point in the history
  • Loading branch information
Galtozzy committed Oct 2, 2024
1 parent cad6287 commit a5e3177
Show file tree
Hide file tree
Showing 49 changed files with 2,776 additions and 718 deletions.
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ site_build
venv
docs.zip
archive.zip

.zed
.zed/*
# vim temporary files
*~
.*.sw?
Expand Down Expand Up @@ -56,6 +57,8 @@ wheels/
*.egg-info/
.installed.cfg
*.egg
pyrightconfig.json
.zed

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down Expand Up @@ -320,4 +323,3 @@ Control.system-ca-bundle
# Visual Studio Code #
.vscode/
.history

145 changes: 110 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,54 +1,90 @@
# 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)
[![Documentation Status](https://readthedocs.org/projects/py-cachify/badge/?version=latest)](https://py-cachify.readthedocs.io/en/latest/?badge=latest)
[![Build Status](https://github.com/EzyGang/py-cachify/actions/workflows/checks.yml/badge.svg)]()
[![Tests Status](https://github.com/EzyGang/py-cachify/actions/workflows/integration-tests.yml/badge.svg)]()
[![Coverage Status](https://coveralls.io/repos/github/EzyGang/py-cachify/badge.png?branch=main)](https://coveralls.io/github/EzyGang/py-cachify?branch=main)
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=EzyGang_py-cachify&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=EzyGang_py-cachify)
<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>

---

**Documentation**: <a href="https://py-cachify.readthedocs.io/latest/" target="_blank">https://py-cachify.readthedocs.io/latest/</a>

**Source Code**: <a href="https://github.com/EzyGang/py-cachify" target="_blank">https://github.com/EzyGang/py-cachify</a>

---

py-cachify is a small library that provides useful cache-based utilities (caching, distributes locks) that are
enhanced versions of those provided by similar packages.

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.

py-cachify is a library that provides small but useful cache utilities.
It offers distributed (cache-based) locks and decorators to lock function executions,
and also caching utilities and decorators for storing results in the cache.

Some parts were heavily inspired by [douglasfarinelli's python-cachelock](https://github.com/douglasfarinelli/python-cachelock) lib,
which is sadly no longer maintained.
The key features are:

py-cachify works well in both sync and async environments, has 100% test coverage,
is backend agnostic (you can provide your own client as long as it matches the signature), and supports Python from 3.8 and upward.
* **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+

It offers distributed (cache based) locks and decorators for securing function executions and storing their results in the cache.
---

## Table of Contents

- [Documentation](#documentation)
- [Installation](#installation)
- [Examples](#examples)
- [How to use](#how-to-use)
- [Basic examples](#basic-examples)
- [Contributing](#contributing)
- [License](#license)

## Documentation

Detailed documentation can be found at https://py-cachify.readthedocs.io/en/latest/.

## Installation
To install:

<!-- termynal -->
```bash
pip install py-cachify
$ pip install py-cachify

# or if using poetry
poetry add py-cachify
---> 100%
Successfully installed py-cachify
```

## Examples
## How to use

You can read more in-depth tutorial [here](https://py-cachify.readthedocs.io/latest/tutorial/).

To start working with it, you'll have to initialize it using `init_cachify`:
First, to start working with the library, you will have to initialize it by using provided `init_cachify` function:
```python
from py_cachify import init_cachify

init_cachify()
```
By default, it will use an in-memory cache.


If you want to use Redis:
```python
from py_cachify import init_cachify
Expand All @@ -59,26 +95,65 @@ init_cachify(sync_client=from_url(redis_url), async_client=async_from_url(async_
```
Normally you wouldn't have to use both sync and async clients since an application usually works in a single mode i.e. sync/async.

Once initialized you can use everything that the library provides straight up without being worried about managing the cache yourself.
Once initialized you can use everything that the library provides straight up without being worried about managing the cache yourself.

❗ If you forgot to call `init_cachify` the `CachifyInitError` will be raised during runtime.

## Basic examples

### Caching

Caching by using `@cached` decorator utilizing the flexibility of a dynamic key:

If you forgot to call `init_cachify` the `CachifyInitError` will be raised during runtime.
```python
from py_cachify import once
# Cache the result of the following function with dynamic 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
```

Read more about `@cached` [here](https://py-cachify.readthedocs.io/latest/reference/cached/).

### Locking

# Make sure there is just one copy of a function running at a time
@once(key='long_running_function')
async def long_running_function() -> str:
# Executing long-running operation...
pass
Locking through context manager:

```python
from py_cachify import lock

# Use it within an asynchronous context
async with lock('resource_key'):
# Your critical section here
print('Critical section code')


# Use it within a synchronous context
with lock('resource_key'):
# Your critical section here
print('Critical section code')
```

Locking via decorator:

```python

from py_cachify import lock

@lock(key='critical_function_lock-{arg}', nowait=False, timeout=10)
def critical_function(arg: int) -> None:
# critical code
```

For more detailed documentation and examples please visit https://py-cachify.readthedocs.io/en/latest/.
Read more about `lock` [here](https://py-cachify.readthedocs.io/latest/reference/lock/).

For more detailed tutorial visit [Tutorial](https://py-cachify.readthedocs.io/latest/tutorial/) or [full API reference](https://py-cachify.readthedocs.io/latest/reference).

## 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](LICENSE) file for details.
This project is licensed under the MIT License - see the [LICENSE](https://github.com/EzyGang/py-cachify/blob/main/LICENSE) file for details.
70 changes: 0 additions & 70 deletions docs/cached-decorator.md

This file was deleted.

27 changes: 19 additions & 8 deletions docs/examples.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# Examples

Here's a small list of possible usage applications.

## `async_lock` / `lock`
```python
Remember to make sure to call `init_cachify`

from py_cachify.asyncio import async_lock
from py_cachify.sync import lock
## ///lock/// as context manager
```python
from py_cachify import lock


# Use it within an asynchronous context
async with async_lock('resource_key'):
async with lock('resource_key'):
# Your critical section here
print('Critical section code')

Expand All @@ -21,8 +22,18 @@ with lock('resource_key'):

```

## ///lock/// as decorator

```python

from py_cachify import lock

@lock(key='critical_function_lock-{arg}', nowait=False, timeout=10)
def critical_function(arg: int) -> None:
# critical code
```

## `once` decorator
## ///once/// decorator

```python
from datetime import date
Expand Down Expand Up @@ -56,7 +67,7 @@ def one_more_long_running_function() -> None:
pass
```

## `cached` decorator
## ///cached/// decorator
```python
from py_cachify import cached

Expand All @@ -72,7 +83,7 @@ def async_expensive_function(arg_a: int, arg_b: int) -> int:

```

## `cached` decorator with encoder/decoder
## ///cached/// decorator with encoder/decoder
```python
from py_cachify import cached

Expand Down
Binary file added docs/img/type-annotations-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/type-annotations-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/type-annotations.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit a5e3177

Please sign in to comment.