FastAPI framework plugins

Overview

Plugins for FastAPI framework, high performance, easy to learn, fast to code, ready for production

Build Status Coverage Package version Join the chat at https://gitter.im/tiangolo/fastapi

fastapi-plugins

FastAPI framework plugins

Changes

See release notes

Installation

pip install fastapi-plugins
pip install fastapi-plugins[memcached]
pip install fastapi-plugins[all]

Plugins

Cache

Memcached

Valid variable are

  • MEMCACHED_HOST - Memcached server host.
  • MEMCACHED_PORT - Memcached server port. Default is 11211.
  • MEMCACHED_POOL_MINSIZE - Minimum number of free connection to create in pool. Default is 1.
  • MEMCACHED_POOL_SIZE - Maximum number of connection to keep in pool. Default is 10. Must be greater than 0. None is disallowed.
  • MEMCACHED_PRESTART_TRIES - The number tries to connect to the a Memcached instance.
  • MEMCACHED_PRESTART_WAIT - The interval in seconds to wait between connection failures on application start.
Example
    # run with `uvicorn demo_app:app`
    import typing
    import fastapi
    import pydantic
    
    from fastapi_plugins.memcached import MemcachedSettings
    from fastapi_plugins.memcached import MemcachedClient
    from fastapi_plugins.memcached import memcached_plugin
    from fastapi_plugins.memcached import depends_memcached
    
    class AppSettings(OtherSettings, MemcachedSettings):
        api_name: str = str(__name__)
    
    app = fastapi.FastAPI()
    config = AppSettings()
    
    @app.get("/")
    async def root_get(
            cache: MemcachedClient=fastapi.Depends(depends_memcached),
    ) -> typing.Dict:
        await cache.set(b'Hello', b'World')
        await cache.get(b'Hello')
        return dict(ping=await cache.ping())
    
    @app.on_event('startup')
    async def on_startup() -> None:
        await memcached_plugin.init_app(app, config=config)
        await memcached_plugin.init()
    
    @app.on_event('shutdown')
    async def on_shutdown() -> None:
        await memcached_plugin.terminate()

Redis

Supports

  • single instance
  • sentinel

Valid variable are

  • REDIS_TYPE
    • redis - single Redis instance
    • sentinel - Redis cluster
  • REDIS_URL - URL to connect to Redis server. Example redis://user:[email protected]:6379/2. Supports protocols redis://, rediss:// (redis over TLS) and unix://.
  • REDIS_HOST - Redis server host.
  • REDIS_PORT - Redis server port. Default is 6379.
  • REDIS_PASSWORD - Redis password for server.
  • REDIS_DB - Redis db (zero-based number index). Default is 0.
  • REDIS_CONNECTION_TIMEOUT - Redis connection timeout. Default is 2.
  • REDIS_POOL_MINSIZE - Minimum number of free connection to create in pool. Default is 1.
  • REDIS_POOL_MAXSIZE - Maximum number of connection to keep in pool. Default is 10. Must be greater than 0. None is disallowed.
  • REDIS_SENTINELS - List or a tuple of Redis sentinel addresses.
  • REDIS_SENTINEL_MASTER - The name of the master server in a sentinel configuration. Default is mymaster.
  • REDIS_PRESTART_TRIES - The number tries to connect to the a Redis instance.
  • REDIS_PRESTART_WAIT - The interval in seconds to wait between connection failures on application start.
Example
    # run with `uvicorn demo_app:app`
    import typing
    import aioredis
    import fastapi
    import pydantic
    import fastapi_plugins
    
    class AppSettings(OtherSettings, fastapi_plugins.RedisSettings):
        api_name: str = str(__name__)
    
    app = fastapi.FastAPI()
    config = AppSettings()
    
    @app.get("/")
    async def root_get(
            cache: aioredis.Redis=fastapi.Depends(fastapi_plugins.depends_redis),
    ) -> typing.Dict:
        return dict(ping=await cache.ping())
    
    @app.on_event('startup')
    async def on_startup() -> None:
        await fastapi_plugins.redis_plugin.init_app(app, config=config)
        await fastapi_plugins.redis_plugin.init()
    
    @app.on_event('shutdown')
    async def on_shutdown() -> None:
        await fastapi_plugins.redis_plugin.terminate()
Example with Docker Compose - Redis
version: '3.7'
services:
  redis:
    image: redis
    ports:
      - "6379:6379"
  demo_fastapi_plugin:
    image:    demo_fastapi_plugin
    environment:
      - REDIS_TYPE=redis
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    ports:
      - "8000:8000"
Example with Docker Compose - Redis Sentinel
version: '3.7'
services:
  ...
  redis-sentinel:
    ports:
      - "26379:26379"
    environment:
      - ...
    links:
      - redis-master
      - redis-slave
  demo_fastapi_plugin:
    image:    demo_fastapi_plugin
    environment:
      - REDIS_TYPE=sentinel
      - REDIS_SENTINELS=redis-sentinel:26379
    ports:
      - "8000:8000"

Scheduler

Simple schedule an awaitable job as a task.

  • long running async functions (e.g. monitor a file a system or events)
  • gracefully cancel spawned tasks

Valid variable are:

  • AIOJOBS_CLOSE_TIMEOUT - The timeout in seconds before canceling a task.
  • AIOJOBS_LIMIT - The number of concurrent tasks to be executed.
  • AIOJOBS_PENDING_LIMIT - The number of pending jobs (waiting fr execution).
# run with `uvicorn demo_app:app`
import ...
import fastapi_plugins

class AppSettings(OtherSettings, fastapi_plugins.RedisSettings, fastapi_plugins.SchedulerSettings):
    api_name: str = str(__name__)

app = fastapi.FastAPI()
config = AppSettings()

@app.post("/jobs/schedule/<timeout>")
async def job_post(
    timeout: int=fastapi.Query(..., title='the job sleep time'),
    cache: aioredis.Redis=fastapi.Depends(fastapi_plugins.depends_redis),
    scheduler: aiojobs.Scheduler=fastapi.Depends(fastapi_plugins.depends_scheduler),  # @IgnorePep8
) -> str:
    async def coro(job_id, timeout, cache):
        await cache.set(job_id, 'processing')
        try:
            await asyncio.sleep(timeout)
            if timeout == 8:
                raise Exception('ugly error')
        except asyncio.CancelledError:
            await cache.set(job_id, 'canceled')
        except Exception:
            await cache.set(job_id, 'erred')
        else:
            await cache.set(job_id, 'success')

    job_id = str(uuid.uuid4()).replace('-', '')
    await cache.set(job_id, 'pending')
    await scheduler.spawn(coro(job_id, timeout, cache))
    return job_id

@app.get("/jobs/status/<job_id>")
async def job_get(
    job_id: str=fastapi.Query(..., title='the job id'),
    cache: aioredis.Redis=fastapi.Depends(fastapi_plugins.depends_redis),
) -> typing.Dict:
    status = await cache.get(job_id)
    if status is None:
        raise fastapi.HTTPException(
            status_code=starlette.status.HTTP_404_NOT_FOUND,
            detail='Job %s not found' % job_id
        )
    return dict(job_id=job_id, status=status)

@app.on_event('startup')
async def on_startup() -> None:
    await fastapi_plugins.redis_plugin.init_app(app, config=config)
    await fastapi_plugins.redis_plugin.init()
    await fastapi_plugins.scheduler_plugin.init_app(app=app, config=config)
    await fastapi_plugins.scheduler_plugin.init()

@app.on_event('shutdown')
async def on_shutdown() -> None:
    await fastapi_plugins.scheduler_plugin.terminate()
    await fastapi_plugins.redis_plugin.terminate()

... more already in progress ...

Development

Issues and suggestions are welcome through issues

License

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

Comments
  • Why are you not closing the database connection before shutdown?

    Why are you not closing the database connection before shutdown?

    We (our team) were trying with your library, and stumbled on this "missing" feature.

    It's important to close the connections for a truly graceful shutdown. Was that a project decision? Didn't you just think about it?

    More important: would you be willing to receive a proposal for this implementation?

    question 
    opened by azisaka 6
  • Fix redis_url ignored

    Fix redis_url ignored

    redis_url setting is currently ignored and DSN is always built by using separate parameters

    This is just a PoC, I will provide a more thorough PR in the next days

    bug 
    opened by yakky 6
  • Remove __all__ in __init__

    Remove __all__ in __init__

    Hi, I noticed this project uses __all__ for most of its modules. However, in fastapi_plugins/__init__.py I see __all__ = [] which causes my editor to warn with things like 'RedisSettings' is not declared in __all__. I decided to simply remove __all__ from there since it is optional. Alternatively, I could combine __all__ from each of the imported modules.

    What do you think?

    bug 
    opened by MatthewScholefield 5
  •  AttributeError: 'State' object has no attribute 'REDIS'

    AttributeError: 'State' object has no attribute 'REDIS'

    Pytest API testing does not work if a function has a cache dependency.

    Here is the example

    @router.post("/login/", response_model=Token)
    async def login(form_data: OAuth2PasswordRequestForm = Depends(),
                    cache: aioredis.Redis = Depends(fastapi_plugins.depends_redis)):
                    ...
                    await cache.setex("SomeKey", 300, "SomeValue")
    
    
        @pytest.mark.asyncio
        async def test_login_view_pass(self, client):
            data = UserInput(**self.__generate_data())
            await user_create(data)
            response = await client.post(f"{settings.API_VERSION}/users/login/",
                                         data={"username": data.username,
                                               "password": data.password},
                                         headers={"Content-Type": "application/x-www-form-urlencoded"})
            assert response.status_code == status.HTTP_200_OK
    
    
    self = <starlette.datastructures.State object at 0x7f10ceccd610>, key = 'REDIS'
    
        def __getattr__(self, key: typing.Any) -> typing.Any:
            try:
                return self._state[key]
            except KeyError:
                message = "'{}' object has no attribute '{}'"
    >           raise AttributeError(message.format(self.__class__.__name__, key))
    E           AttributeError: 'State' object has no attribute 'REDIS'
    
    /usr/local/lib/python3.8/site-packages/starlette/datastructures.py:672: AttributeError
    

    Is there any way to solve this issue ?

    opened by Koshkaj 4
  • aioredis version issue: `AttributeError: module 'aioredis' has no attribute 'create_redis_pool'`

    aioredis version issue: `AttributeError: module 'aioredis' has no attribute 'create_redis_pool'`

    aioredis does not import anymore create_redis_pool method in its __init__ at least after v1.3.1 see here.

    Unfortunately fastapi-plugins is still using that method in _redis.init() and it defines aioredis>=1.3.* in its setup.py see here

    That can cause to raise the following exception in case aioredis > 1.3.1 has been installed in your system

    AttributeError: module 'aioredis' has no attribute 'create_redis_pool'
    
    bug 
    opened by kinderp 3
  • The startup example codes do not work, cannot `Depends`  fastapi_plugins.depends_redis

    The startup example codes do not work, cannot `Depends` fastapi_plugins.depends_redis

    I test fastapi-plugins using the example codes ,but it corrupts with

    fastapi.exceptions.FastAPIError: Invalid args for response field! 
    Hint: check that <class 'starlette.requests.HTTPConnection'> is a valid pydantic field type
    

    the codes all go here

    import fastapi, fastapi_plugins
    import aioredis, pydantic, typing
    
    @fastapi_plugins.registered_configuration
    class AppSettings(
            fastapi_plugins.ControlSettings,
            fastapi_plugins.RedisSettings,
            fastapi_plugins.SchedulerSettings
    ):
        api_name: str = str(__name__)
    
    
    app = fastapi.FastAPI()
    config = fastapi_plugins.get_config()
    
    @app.get("/")
    async def root_get(
            cache: aioredis.Redis=fastapi.Depends(fastapi_plugins.depends_redis), # TODO corrupts here,
            conf: pydantic.BaseSettings=fastapi.Depends(fastapi_plugins.depends_config) # noqa E501
    ) -> typing.Dict:
        return dict(ping=await cache.ping(), api_name=conf.api_name)
    
    @app.on_event('startup')
    async def on_startup() -> None:
        await fastapi_plugins.config_plugin.init_app(app, config)
        await fastapi_plugins.config_plugin.init()
        await fastapi_plugins.redis_plugin.init_app(app, config=config)
        await fastapi_plugins.redis_plugin.init()
        await fastapi_plugins.scheduler_plugin.init_app(app=app, config=config)
        await fastapi_plugins.scheduler_plugin.init()
        await fastapi_plugins.control_plugin.init_app(app, config=config, version="0.0.1", environ=config.dict())
        await fastapi_plugins.control_plugin.init()
    
    
    @app.on_event('shutdown')
    async def on_shutdown() -> None:
        await fastapi_plugins.control_plugin.terminate()
        await fastapi_plugins.scheduler_plugin.terminate()
        await fastapi_plugins.redis_plugin.terminate()
        await fastapi_plugins.config_plugin.terminate()
    

    packages info:

    pip show fastapi-plugins
    #Name: fastapi-plugins
    #Version: 0.8.1
    
    pip show fastapi
    #Name: fastapi
    #Version: 0.54.2
    

    what have I missed?

    opened by tearf001 2
Releases(0.11.0)
Owner
RES
software engineer :: python && c++
RES
Qwerkey is a social media platform for connecting and learning more about mechanical keyboards built on React and Redux in the frontend and Flask in the backend on top of a PostgreSQL database.

Flask React Project This is the backend for the Flask React project. Getting started Clone this repository (only this branch) git clone https://github

Peter Mai 22 Dec 20, 2022
Drop-in MessagePack support for ASGI applications and frameworks

msgpack-asgi msgpack-asgi allows you to add automatic MessagePack content negotiation to ASGI applications (Starlette, FastAPI, Quart, etc.), with a s

Florimond Manca 128 Jan 02, 2023
Cube-CRUD is a simple example of a REST API CRUD in a context of rubik's cube review service.

Cube-CRUD is a simple example of a REST API CRUD in a context of rubik's cube review service. It uses Sqlalchemy ORM to manage the connection and database operations.

Sebastian Andrade 1 Dec 11, 2021
🐍Pywork is a Yeoman generator to scaffold a Bare-bone Python Application

Pywork python app yeoman generator Yeoman | Npm Pywork | Home PyWork is a Yeoman generator for a basic python-worker project that makes use of Pipenv,

Vu Tran 10 Dec 16, 2022
Cookiecutter template for FastAPI projects using: Machine Learning, Poetry, Azure Pipelines and Pytests

cookiecutter-fastapi In order to create a template to FastAPI projects. 🚀 Important To use this project you don't need fork it. Just run cookiecutter

Arthur Henrique 225 Dec 28, 2022
Twitter API monitor with fastAPI + MongoDB

Twitter API monitor with fastAPI + MongoDB You need to have a file .env with the following variables: DB_URL="mongodb+srv://mongodb_path" DB_URL2=

Leonardo Ferreira 3 Apr 08, 2022
A rate limiter for Starlette and FastAPI

SlowApi A rate limiting library for Starlette and FastAPI adapted from flask-limiter. Note: this is alpha quality code still, the API may change, and

Laurent Savaete 562 Jan 01, 2023
Instrument your FastAPI app

Prometheus FastAPI Instrumentator A configurable and modular Prometheus Instrumentator for your FastAPI. Install prometheus-fastapi-instrumentator fro

Tim Schwenke 441 Jan 05, 2023
Lazy package to start your project using FastAPI✨

Fastapi-lazy 🦥 Utilities that you use in various projects made in FastAPI. Source Code: https://github.com/yezz123/fastapi-lazy Install the project:

Yasser Tahiri 95 Dec 29, 2022
Generate Class & Decorators for your FastAPI project ✨🚀

Classes and Decorators to use FastAPI with class based routing. In particular this allows you to construct an instance of a class and have methods of that instance be route handlers for FastAPI & Pyt

Yasser Tahiri 34 Oct 27, 2022
Feature rich robust FastAPI template.

Flexible and Lightweight general-purpose template for FastAPI. Usage ⚠️ Git, Python and Poetry must be installed and accessible ⚠️ Poetry version must

Pavel Kirilin 588 Jan 04, 2023
Voucher FastAPI

Voucher-API Requirement Docker Installed on system Libraries Pandas Psycopg2 FastAPI PyArrow Pydantic Uvicorn How to run Download the repo on your sys

Hassan Munir 1 Jan 26, 2022
A comprehensive CRUD API generator for SQLALchemy.

FastAPI Quick CRUD Introduction Advantage Constraint Getting started Installation Usage Design Path Parameter Query Parameter Request Body Upsert Intr

192 Jan 06, 2023
The template for building scalable web APIs based on FastAPI, Tortoise ORM and other.

FastAPI and Tortoise ORM. Powerful but simple template for web APIs w/ FastAPI (as web framework) and Tortoise-ORM (for working via database without h

prostomarkeloff 95 Jan 08, 2023
SQLAlchemy Admin for Starlette/FastAPI

SQLAlchemy Admin for Starlette/FastAPI SQLAdmin is a flexible Admin interface for SQLAlchemy models. Main features include: SQLAlchemy sync/async engi

Amin Alaee 683 Jan 03, 2023
Пример использования GraphQL Ariadne с FastAPI и сравнение его с GraphQL Graphene FastAPI

FastAPI Ariadne Example Пример использования GraphQL Ariadne с FastAPI и сравнение его с GraphQL Graphene FastAPI - GitHub ###Запуск на локальном окру

ZeBrains Team 9 Nov 10, 2022
FastAPI client generator

FastAPI-based API Client Generator Generate a mypy- and IDE-friendly API client from an OpenAPI spec. Sync and async interfaces are both available Com

David Montague 283 Jan 04, 2023
Toolkit for developing and maintaining ML models

modelkit Python framework for production ML systems. modelkit is a minimalist yet powerful MLOps library for Python, built for people who want to depl

140 Dec 27, 2022
Simple FastAPI Example : Blog API using FastAPI : Beginner Friendly

fastapi_blog FastAPI : Simple Blog API with CRUD operation Steps to run the project: git clone https://github.com/mrAvi07/fastapi_blog.git cd fastapi-

Avinash Alanjkar 1 Oct 08, 2022
Docker Sample Project - FastAPI + NGINX

Docker Sample Project - FastAPI + NGINX Run FastAPI and Nginx using Docker container Installation Make sure Docker is installed on your local machine

1 Feb 11, 2022