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
Async and Sync wrapper client around httpx, fastapi, date stuff

lazyapi Async and Sync wrapper client around httpx, fastapi, and datetime stuff. Motivation This library is forked from an internal project that works

2 Apr 19, 2022
FastAPI构建的API服务

使用FastAPI 构建的商城项目API 学习FastAPI 构建项目目录 构建项目接口: 对应博客:https://www.charmcode.cn/article/2020-06-08_vue_mall_api 声明 此项目已经不再维护, 可以参考我另外一个项目https://github.co

王小右 64 Oct 04, 2022
Example of using FastAPI and MongoDB database.

FastAPI Todo Application Example of using FastAPI and MangoDB database. 💡 Prerequisites Python ⚙️ Build & Run The first thing to do is to clone the r

Bobynets Ivan 1 Oct 29, 2021
Twitter API with fastAPI

Twitter API with fastAPI Content Forms Cookies and headers management Files edition Status codes HTTPExceptions Docstrings or documentation Deprecate

Juan Agustin Di Pasquo 1 Dec 21, 2021
sample web application built with FastAPI + uvicorn

SPARKY Sample web application built with FastAPI & Python 3.8 shows simple Flask-like structure with a Bootstrap template index.html also has a backgr

mrx 21 Jan 03, 2022
FastAPI Skeleton App to serve machine learning models production-ready.

FastAPI Model Server Skeleton Serving machine learning models production-ready, fast, easy and secure powered by the great FastAPI by Sebastián Ramíre

268 Jan 01, 2023
Analytics service that is part of iter8. Robust analytics and control to unleash cloud-native continuous experimentation.

iter8-analytics iter8 enables statistically robust continuous experimentation of microservices in your CI/CD pipelines. For in-depth information about

16 Oct 14, 2021
Admin Panel for GinoORM - ready to up & run (just add your models)

Gino-Admin Docs (state: in process): Gino-Admin docs Play with Demo (current master 0.2.3) Gino-Admin demo (login: admin, pass: 1234) Admin

Iuliia Volkova 46 Nov 02, 2022
Backend, modern REST API for obtaining match and odds data crawled from multiple sites. Using FastAPI, MongoDB as database, Motor as async MongoDB client, Scrapy as crawler and Docker.

Introduction Apiestas is a project composed of a backend powered by the awesome framework FastAPI and a crawler powered by Scrapy. This project has fo

Fran Lozano 54 Dec 13, 2022
Adds integration of the Jinja template language to FastAPI.

fastapi-jinja Adds integration of the Jinja template language to FastAPI. This is inspired and based off fastapi-chamelon by Mike Kennedy. Check that

Marc Brooks 58 Nov 29, 2022
First API using FastApi

First API using FastApi Made this Simple Api to store and Retrive Student Data of My College Ncc-Bim To View All the endpoits Visit /docs To Run Local

Sameer Joshi 2 Jun 21, 2022
🤪 FastAPI + Vue构建的Mall项目后台管理

Mall项目后台管理 前段时间学习Vue写了一个移动端项目 https://www.charmcode.cn/app/mall/home 然后教程到此就结束了, 我就总感觉少点什么,计划自己着手写一套后台管理。 相关项目 移动端Mall项目源码(Vue构建): https://github.com/

王小右 131 Jan 01, 2023
python template private service

Template for private python service This is a cookiecutter template for an internal REST API service, written in Python, inspired by layout-golang. Th

UrvanovCompany 15 Oct 02, 2022
All of the ad-hoc things you're doing to manage incidents today, done for you, and much more!

About What's Dispatch? Put simply, Dispatch is: All of the ad-hoc things you’re doing to manage incidents today, done for you, and a bunch of other th

Netflix, Inc. 3.7k Jan 05, 2023
基于Pytorch的脚手架项目,Celery+FastAPI+Gunicorn+Nginx+Supervisor实现服务部署,支持Docker发布

cookiecutter-pytorch-fastapi 基于Pytorch的 脚手架项目 按规范添加推理函数即可实现Celery+FastAPI+Gunicorn+Nginx+Supervisor+Docker的快速部署 Requirements Python = 3.6 with pip in

17 Dec 23, 2022
signal-cli-rest-api is a wrapper around signal-cli and allows you to interact with it through http requests

signal-cli-rest-api signal-cli-rest-api is a wrapper around signal-cli and allows you to interact with it through http requests. Features register/ver

Sebastian Noel Lübke 31 Dec 09, 2022
Web Inventory tool, takes screenshots of webpages using Pyppeteer (headless Chrome/Chromium) and provides some extra bells & whistles to make life easier.

WitnessMe WitnessMe is primarily a Web Inventory tool inspired by Eyewitness, its also written to be extensible allowing you to create custom function

byt3bl33d3r 648 Jan 05, 2023
官方文档已经有翻译的人在做了,

FastAPI 框架,高性能,易学,快速编码,随时可供生产 文档:https://fastapi.tiangolo.com 源码:https://github.com/tiangolo/fastapi FastAPI 是一个现代、快速(高性能)的 Web 框架,基于标准 Python 类型提示,使用

ApacheCN 27 Nov 11, 2022
Recommend recipes based on what ingredients you have at home

🌱 MyChef 📦 Overview MyChef is an application that helps you decide what meal to make based on what you have at home. Simply enter in ingredients you

Logan Connolly 44 Nov 08, 2022
A simple api written in python/fastapi that serves movies from a cassandra table.

A simple api written in python/fastapi that serves movies from a cassandra table. 1)clone the repo 2)rename sample_global_config_.py to global_config.

Sreeraj 1 Aug 26, 2021