cachette


Namecachette JSON
Version 0.1.8 PyPI version JSON
download
home_pagehttps://github.com/aekasitt/cachette
SummaryCache extension for ASGI frameworks
upload_time2024-02-02 17:36:11
maintainer
docs_urlNone
authorSitt Guruvanich
requires_python>=3.9,<4.0
licenseMIT
keywords starlette fastapi cache redis aioredis dynamodb aiobotocore asynchronous memcached aiomcache mongodb motor pymongo
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Cachette

[![Build status](https://travis-ci.com/aekasitt/cachette.svg?branch=master)](https://app.travis-ci.com/github/aekasitt/cachette)
[![Package vesion](https://img.shields.io/pypi/v/cachette)](https://pypi.org/project/cachette)
[![Format](https://img.shields.io/pypi/format/cachette)](https://pypi.org/project/cachette)
[![Python version](https://img.shields.io/pypi/pyversions/cachette)](https://pypi.org/project/cachette)
[![License](https://img.shields.io/pypi/l/cachette)](https://pypi.org/project/cachette)
[![Top](https://img.shields.io/github/languages/top/aekasitt/cachette)](.)
[![Languages](https://img.shields.io/github/languages/count/aekasitt/cachette)](.)
[![Size](https://img.shields.io/github/repo-size/aekasitt/cachette)](.)
[![Last commit](https://img.shields.io/github/last-commit/aekasitt/cachette/master)](.)

![Cachette banner](static/cachette-banner.svg)

## Features

This is an extension aiming at making cache access on the server
By configuration at startup of the FastAPI App instance, you can set the backend and other 
configuration options and have it remain a class constant when using FastAPI's
intuitive [Dependency Injection](https://fastapi.tiangolo.com/tutorial/dependencies/) system.

The design has built-in limitations like fixed codec and backend once the app has been launched and 
encourage developers to design their applications with this in mind.

Most of the Backend implementation is directly lifted from 
[fastapi-cache](https://github.com/long2ice/fastapi-cache) by 
[@long2ice](https://github.com/long2ice) excluding the MongoDB backend option.

## Configuration Options

The following are the current available configuration keys that can be set on this FastAPI extension
on startup either by using a method which returns a list of tuples or a Pydantic BaseSettings object
(See examples below or in `examples/` folder)

    backend -- optional; must be one of ["dynamodb", "inmemory", "memcached", "mongodb", "pickle",
      "redis"]; defaults to using inmemory option which required no extra package dependencies.
      To use other listed options; See installation guide on the README.md at
      [Repository Page](https://github.com/aekasitt/cachette).
    codec -- optional; serialization and de-serialization format to have cache values stored in
      the cache backend of choice as a string of selected encoding. once fetched, will have their
      decoded values returned of the same format. must be one of ["feather", "msgpack", "parquet",
      "pickle"]; if none is defined, will vanilla codec of basic string conversion will be used.
    ttl -- optional; the time-to-live or amount before this cache item expires within the cache;
      defaults to 60 (seconds) and must be between 1 second to 1 hour (3600 seconds).
    redis_url -- required when backend set to "redis"; the url set to redis-server instance with
      or without provided authentication in such formats "redis://user:password@host:port" and
      "redis://host:port" respectively.
    memcached_host -- required when backend set to "memcached"; the host endpoint to the memcached
      distributed memory caching system.
    table_name -- required when backend set to "dynamodb" or "mongodb"; name of the cache table or
      collection in case of "mongodb" backend to have key-value pairs stored; defaults to
      "cachette".
    region -- required when backend set to "dynamodb" and "dynamodb_url" not set; one of Amazon
      Web Services listed Regions which can be found on this Documentation
      [Page](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones)
    dynamodb_url -- required when backend set to "dynamodb" and "region" not set; this option is
      used when setting up your own DynamoDB Local instance according to this
      [Guide](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal)
    database_name -- required when backend set to "mongodb"; the database name to be automatically
      created if not exists on the MongoDB instance and store the cache table; defaults to
      "cachette-db"
    mongodb_url -- required when backend set to "mongodb"; the url set to MongoDB database
      instance with or without provided authentication in such formats
      "mongodb://user:password@host:port" and "mongodb://host:port" respectively.
    pickle_path -- required when backend set to "pickle"; the file-system path to create local
      store using python pickling on local directory

## Examples

The following shows and example of setting up FastAPI Cachette in its default configuration, which
is an In-Memory cache implementation.

```py
from cachette import Cachette
from fastapi import FastAPI, Depends
from fastapi.responses import PlainTextResponse
from pydantic import BaseModel

app = FastAPI()

### Routing ###
class Payload(BaseModel):
  key: str
  value: str

@app.post('/', response_class=PlainTextResponse)
async def setter(payload: Payload, cachette: Cachette = Depends()):
  await cachette.put(payload.key, payload.value)
  return 'OK'

@app.get('/{key}', response_class=PlainTextResponse, status_code=200)
async def getter(key: str, cachette: Cachette = Depends()):
  value: str = await cachette.fetch(key)
  return value
```

And then this is how you set up a FastAPI Cachette with Redis support enabled.

```py
from cachette import Cachette
from fastapi import FastAPI, Depends
from fastapi.responses import PlainTextResponse
from pydantic import BaseModel

app = FastAPI()

@Cachette.load_config
def get_cachette_config():
  return [('backend', 'redis'), ('redis_url', 'redis://localhost:6379')]

class Payload(BaseModel):
  key: str
  value: str

@app.post('/', response_class=PlainTextResponse)
async def setter(payload: Payload, cachette: Cachette = Depends()):
  await cachette.put(payload.key, payload.value)
  return 'OK'

@app.get('/{key}', response_class=PlainTextResponse, status_code=200)
async def getter(key: str, cachette: Cachette = Depends()):
  value: str = await cachette.fetch(key)
  return value
```

## Upcoming Features (To-Do List)

1. Implement `flush` and `flush_expired` methods on individual backends 
(Not needed for Redis & Memcached backends)

2. Memcached Authentication ([No SASL Support](https://github.com/aio-libs/aiomcache/issues/12))
Change library?

3. DynamoDB Authentication (Add AWS Access Key ID and AWS Access Secret Key to configuration).

4. Boto3 Version Fix; Current version restrictions vulnerable to `aiohttp` bug.

5. Add behaviors responding to "Cache-Control" request header

6. More character validations for URLs and Database/Table/Collection names in configuration options

## Installation

The easiest way to start working with this extension with pip

```bash
pip install cachette
# or
poetry add cachette
```

When you familiarize with the basic structure of how to Dependency Inject Cachette within your
endpoints, please experiment more of using external backends with `extras` installations like

```bash
# Install FastAPI Cachette's extra requirements to Redis support
pip install cachette --install-option "--extras-require=redis"
# or Install FastAPI Cachette's support to Memcached
poetry add cachette[memcached]
# or Special JSON Codec written on Rust at lightning speed
poetry add cachette[orjson]
# or Include PyArrow package making DataFrame serialization much easier
pip install cachette --install-option "--extras-require=dataframe"
# or MongoDB and DynamoDB supports
poetry add cachette[mongodb]
pip install cachette --install-option "--extras-require=dynamodb"
```

## Getting Started

This FastAPI extension utilizes "Dependency Injection" (To be continued)

Configuration of this FastAPI extension must be done at startup using "@Cachette.load_config" 
decorator (To be continued)

These are all available options with explanations and validation requirements (To be continued)

## Examples

The following examples show you how to integrate this extension to a FastAPI App (To be continued)

See "examples/" folders

To run examples, first you must install extra dependencies

Do all in one go with this command...

```bash
pip install aiobotocore aiomcache motor uvicorn redis
# or
poetry install --extras examples
```

Do individual example with this command...

```bash
pip install redis
# or
poetry install --extras redis
```

## Contributions

See features and write tests I guess.

## Test Environment Setup

This project utilizes multiple external backend services namely AWS DynamoDB, Memcached, MongoDB and
Redis as backend service options as well as a possible internal option called InMemoryBackend. In
order to test viability, we must have specific instances of these set up in the background of our
testing environment 

### With Docker-Compose

Utilize orchestration file attached to reposity and `docker-compose` command to set up testing 
instances of backend services using the following command...

```bash
docker-compose up -d
```

When you are finished, you can stop and remove background running backend instances with the
following command...

```bash
docker-compose down
```

### Without Docker-Compose

If you are using `arm64` architecture on your local machine like I am with my fancy MacBook Pro, 
there is a chance that your `docker-compose` (V1) is not properly configured and have caused you 
many headaches. The following commands will allow you to replicate docker-compose orchestration
command given above.


1. AWS DynamoDB Local

    ```bash
    docker run --detach --rm -ti -p 8000:8000 --name cachette-dynamodb amazon/dynamodb-local:latest
    ```

2. Memcached

    ```bash
    docker run --detach --rm -ti -p 11211:11211 --name cachette-memcached memcached:bullseye
    ```

3. MongoDB

    ```bash
    docker run --detach --rm -ti -p 27017:27017 --name cachette-mongodb mongo:latest
    ```

4. Redis

    ```bash
    docker run --detach --rm -ti -p 6379:6379 --name cachette-redis redis:bullseye
    ```

And finally, to stop and remove running instances, run the following command

```bash
[ ! -z $(docker ps -f name="cachette-*" -q | tr -d '\n') ] \
  && docker kill $(docker ps -f name="cachette-*" -q)
```

## Tests

Now that you have background running backend instances, you can proceed with the tests by using
`pytest` command as such...

```bash
pytest
```

Or you can configure the command to run specific tests as such...

```bash
pytest -k test_load_invalid_configs
# or
pytest -k test_set_then_clear
```

All test suites must be placed under `tests/` folder or its subfolders.

## License

This project is licensed under the terms of the MIT license.
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/aekasitt/cachette",
    "name": "cachette",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9,<4.0",
    "maintainer_email": "",
    "keywords": "starlette,fastapi,cache,redis,aioredis,dynamodb,aiobotocore,asynchronous,memcached,aiomcache,mongodb,motor,pymongo",
    "author": "Sitt Guruvanich",
    "author_email": "aekazitt+github@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/1b/cb/bc816bfcdef834474373188aa0f0dbf8847496b0730945bcd47ba93faa95/cachette-0.1.8.tar.gz",
    "platform": null,
    "description": "# Cachette\n\n[![Build status](https://travis-ci.com/aekasitt/cachette.svg?branch=master)](https://app.travis-ci.com/github/aekasitt/cachette)\n[![Package vesion](https://img.shields.io/pypi/v/cachette)](https://pypi.org/project/cachette)\n[![Format](https://img.shields.io/pypi/format/cachette)](https://pypi.org/project/cachette)\n[![Python version](https://img.shields.io/pypi/pyversions/cachette)](https://pypi.org/project/cachette)\n[![License](https://img.shields.io/pypi/l/cachette)](https://pypi.org/project/cachette)\n[![Top](https://img.shields.io/github/languages/top/aekasitt/cachette)](.)\n[![Languages](https://img.shields.io/github/languages/count/aekasitt/cachette)](.)\n[![Size](https://img.shields.io/github/repo-size/aekasitt/cachette)](.)\n[![Last commit](https://img.shields.io/github/last-commit/aekasitt/cachette/master)](.)\n\n![Cachette banner](static/cachette-banner.svg)\n\n## Features\n\nThis is an extension aiming at making cache access on the server\nBy configuration at startup of the FastAPI App instance, you can set the backend and other \nconfiguration options and have it remain a class constant when using FastAPI's\nintuitive [Dependency Injection](https://fastapi.tiangolo.com/tutorial/dependencies/) system.\n\nThe design has built-in limitations like fixed codec and backend once the app has been launched and \nencourage developers to design their applications with this in mind.\n\nMost of the Backend implementation is directly lifted from \n[fastapi-cache](https://github.com/long2ice/fastapi-cache) by \n[@long2ice](https://github.com/long2ice) excluding the MongoDB backend option.\n\n## Configuration Options\n\nThe following are the current available configuration keys that can be set on this FastAPI extension\non startup either by using a method which returns a list of tuples or a Pydantic BaseSettings object\n(See examples below or in `examples/` folder)\n\n    backend -- optional; must be one of [\"dynamodb\", \"inmemory\", \"memcached\", \"mongodb\", \"pickle\",\n      \"redis\"]; defaults to using inmemory option which required no extra package dependencies.\n      To use other listed options; See installation guide on the README.md at\n      [Repository Page](https://github.com/aekasitt/cachette).\n    codec -- optional; serialization and de-serialization format to have cache values stored in\n      the cache backend of choice as a string of selected encoding. once fetched, will have their\n      decoded values returned of the same format. must be one of [\"feather\", \"msgpack\", \"parquet\",\n      \"pickle\"]; if none is defined, will vanilla codec of basic string conversion will be used.\n    ttl -- optional; the time-to-live or amount before this cache item expires within the cache;\n      defaults to 60 (seconds) and must be between 1 second to 1 hour (3600 seconds).\n    redis_url -- required when backend set to \"redis\"; the url set to redis-server instance with\n      or without provided authentication in such formats \"redis://user:password@host:port\" and\n      \"redis://host:port\" respectively.\n    memcached_host -- required when backend set to \"memcached\"; the host endpoint to the memcached\n      distributed memory caching system.\n    table_name -- required when backend set to \"dynamodb\" or \"mongodb\"; name of the cache table or\n      collection in case of \"mongodb\" backend to have key-value pairs stored; defaults to\n      \"cachette\".\n    region -- required when backend set to \"dynamodb\" and \"dynamodb_url\" not set; one of Amazon\n      Web Services listed Regions which can be found on this Documentation\n      [Page](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones)\n    dynamodb_url -- required when backend set to \"dynamodb\" and \"region\" not set; this option is\n      used when setting up your own DynamoDB Local instance according to this\n      [Guide](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal)\n    database_name -- required when backend set to \"mongodb\"; the database name to be automatically\n      created if not exists on the MongoDB instance and store the cache table; defaults to\n      \"cachette-db\"\n    mongodb_url -- required when backend set to \"mongodb\"; the url set to MongoDB database\n      instance with or without provided authentication in such formats\n      \"mongodb://user:password@host:port\" and \"mongodb://host:port\" respectively.\n    pickle_path -- required when backend set to \"pickle\"; the file-system path to create local\n      store using python pickling on local directory\n\n## Examples\n\nThe following shows and example of setting up FastAPI Cachette in its default configuration, which\nis an In-Memory cache implementation.\n\n```py\nfrom cachette import Cachette\nfrom fastapi import FastAPI, Depends\nfrom fastapi.responses import PlainTextResponse\nfrom pydantic import BaseModel\n\napp = FastAPI()\n\n### Routing ###\nclass Payload(BaseModel):\n  key: str\n  value: str\n\n@app.post('/', response_class=PlainTextResponse)\nasync def setter(payload: Payload, cachette: Cachette = Depends()):\n  await cachette.put(payload.key, payload.value)\n  return 'OK'\n\n@app.get('/{key}', response_class=PlainTextResponse, status_code=200)\nasync def getter(key: str, cachette: Cachette = Depends()):\n  value: str = await cachette.fetch(key)\n  return value\n```\n\nAnd then this is how you set up a FastAPI Cachette with Redis support enabled.\n\n```py\nfrom cachette import Cachette\nfrom fastapi import FastAPI, Depends\nfrom fastapi.responses import PlainTextResponse\nfrom pydantic import BaseModel\n\napp = FastAPI()\n\n@Cachette.load_config\ndef get_cachette_config():\n  return [('backend', 'redis'), ('redis_url', 'redis://localhost:6379')]\n\nclass Payload(BaseModel):\n  key: str\n  value: str\n\n@app.post('/', response_class=PlainTextResponse)\nasync def setter(payload: Payload, cachette: Cachette = Depends()):\n  await cachette.put(payload.key, payload.value)\n  return 'OK'\n\n@app.get('/{key}', response_class=PlainTextResponse, status_code=200)\nasync def getter(key: str, cachette: Cachette = Depends()):\n  value: str = await cachette.fetch(key)\n  return value\n```\n\n## Upcoming Features (To-Do List)\n\n1. Implement `flush` and `flush_expired` methods on individual backends \n(Not needed for Redis & Memcached backends)\n\n2. Memcached Authentication ([No SASL Support](https://github.com/aio-libs/aiomcache/issues/12))\nChange library?\n\n3. DynamoDB Authentication (Add AWS Access Key ID and AWS Access Secret Key to configuration).\n\n4. Boto3 Version Fix; Current version restrictions vulnerable to `aiohttp` bug.\n\n5. Add behaviors responding to \"Cache-Control\" request header\n\n6. More character validations for URLs and Database/Table/Collection names in configuration options\n\n## Installation\n\nThe easiest way to start working with this extension with pip\n\n```bash\npip install cachette\n# or\npoetry add cachette\n```\n\nWhen you familiarize with the basic structure of how to Dependency Inject Cachette within your\nendpoints, please experiment more of using external backends with `extras` installations like\n\n```bash\n# Install FastAPI Cachette's extra requirements to Redis support\npip install cachette --install-option \"--extras-require=redis\"\n# or Install FastAPI Cachette's support to Memcached\npoetry add cachette[memcached]\n# or Special JSON Codec written on Rust at lightning speed\npoetry add cachette[orjson]\n# or Include PyArrow package making DataFrame serialization much easier\npip install cachette --install-option \"--extras-require=dataframe\"\n# or MongoDB and DynamoDB supports\npoetry add cachette[mongodb]\npip install cachette --install-option \"--extras-require=dynamodb\"\n```\n\n## Getting Started\n\nThis FastAPI extension utilizes \"Dependency Injection\" (To be continued)\n\nConfiguration of this FastAPI extension must be done at startup using \"@Cachette.load_config\" \ndecorator (To be continued)\n\nThese are all available options with explanations and validation requirements (To be continued)\n\n## Examples\n\nThe following examples show you how to integrate this extension to a FastAPI App (To be continued)\n\nSee \"examples/\" folders\n\nTo run examples, first you must install extra dependencies\n\nDo all in one go with this command...\n\n```bash\npip install aiobotocore aiomcache motor uvicorn redis\n# or\npoetry install --extras examples\n```\n\nDo individual example with this command...\n\n```bash\npip install redis\n# or\npoetry install --extras redis\n```\n\n## Contributions\n\nSee features and write tests I guess.\n\n## Test Environment Setup\n\nThis project utilizes multiple external backend services namely AWS DynamoDB, Memcached, MongoDB and\nRedis as backend service options as well as a possible internal option called InMemoryBackend. In\norder to test viability, we must have specific instances of these set up in the background of our\ntesting environment \n\n### With Docker-Compose\n\nUtilize orchestration file attached to reposity and `docker-compose` command to set up testing \ninstances of backend services using the following command...\n\n```bash\ndocker-compose up -d\n```\n\nWhen you are finished, you can stop and remove background running backend instances with the\nfollowing command...\n\n```bash\ndocker-compose down\n```\n\n### Without Docker-Compose\n\nIf you are using `arm64` architecture on your local machine like I am with my fancy MacBook Pro, \nthere is a chance that your `docker-compose` (V1) is not properly configured and have caused you \nmany headaches. The following commands will allow you to replicate docker-compose orchestration\ncommand given above.\n\n\n1. AWS DynamoDB Local\n\n    ```bash\n    docker run --detach --rm -ti -p 8000:8000 --name cachette-dynamodb amazon/dynamodb-local:latest\n    ```\n\n2. Memcached\n\n    ```bash\n    docker run --detach --rm -ti -p 11211:11211 --name cachette-memcached memcached:bullseye\n    ```\n\n3. MongoDB\n\n    ```bash\n    docker run --detach --rm -ti -p 27017:27017 --name cachette-mongodb mongo:latest\n    ```\n\n4. Redis\n\n    ```bash\n    docker run --detach --rm -ti -p 6379:6379 --name cachette-redis redis:bullseye\n    ```\n\nAnd finally, to stop and remove running instances, run the following command\n\n```bash\n[ ! -z $(docker ps -f name=\"cachette-*\" -q | tr -d '\\n') ] \\\n  && docker kill $(docker ps -f name=\"cachette-*\" -q)\n```\n\n## Tests\n\nNow that you have background running backend instances, you can proceed with the tests by using\n`pytest` command as such...\n\n```bash\npytest\n```\n\nOr you can configure the command to run specific tests as such...\n\n```bash\npytest -k test_load_invalid_configs\n# or\npytest -k test_set_then_clear\n```\n\nAll test suites must be placed under `tests/` folder or its subfolders.\n\n## License\n\nThis project is licensed under the terms of the MIT license.",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Cache extension for ASGI frameworks",
    "version": "0.1.8",
    "project_urls": {
        "Homepage": "https://github.com/aekasitt/cachette",
        "Repository": "https://github.com/aekasitt/cachette"
    },
    "split_keywords": [
        "starlette",
        "fastapi",
        "cache",
        "redis",
        "aioredis",
        "dynamodb",
        "aiobotocore",
        "asynchronous",
        "memcached",
        "aiomcache",
        "mongodb",
        "motor",
        "pymongo"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "81b05a1bcb36b39576ca018fb9f4ed1ef525bcbe1e2944f65199abd79ed01b01",
                "md5": "25c7a6107f10ba3805c99ab59c4112fa",
                "sha256": "360825a52f813851a6a46819079127645830bd68f68000693a596143bad16ce9"
            },
            "downloads": -1,
            "filename": "cachette-0.1.8-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "25c7a6107f10ba3805c99ab59c4112fa",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9,<4.0",
            "size": 25459,
            "upload_time": "2024-02-02T17:36:09",
            "upload_time_iso_8601": "2024-02-02T17:36:09.228419Z",
            "url": "https://files.pythonhosted.org/packages/81/b0/5a1bcb36b39576ca018fb9f4ed1ef525bcbe1e2944f65199abd79ed01b01/cachette-0.1.8-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1bcbbc816bfcdef834474373188aa0f0dbf8847496b0730945bcd47ba93faa95",
                "md5": "7aa8954988deab7f029387f9276ffe07",
                "sha256": "9a28e5c15ef629cb5f466e615af1b29dbf43318628479853968b7096714f23d5"
            },
            "downloads": -1,
            "filename": "cachette-0.1.8.tar.gz",
            "has_sig": false,
            "md5_digest": "7aa8954988deab7f029387f9276ffe07",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9,<4.0",
            "size": 18374,
            "upload_time": "2024-02-02T17:36:11",
            "upload_time_iso_8601": "2024-02-02T17:36:11.159497Z",
            "url": "https://files.pythonhosted.org/packages/1b/cb/bc816bfcdef834474373188aa0f0dbf8847496b0730945bcd47ba93faa95/cachette-0.1.8.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-02-02 17:36:11",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "aekasitt",
    "github_project": "cachette",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "cachette"
}
        
Elapsed time: 0.17316s