{"id":13424737,"url":"https://github.com/madkote/fastapi-plugins","last_synced_at":"2025-05-15T01:09:23.056Z","repository":{"id":56085352,"uuid":"222924508","full_name":"madkote/fastapi-plugins","owner":"madkote","description":"FastAPI framework plugins","archived":false,"fork":false,"pushed_at":"2025-02-12T14:58:11.000Z","size":213,"stargazers_count":439,"open_issues_count":2,"forks_count":26,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-13T23:54:06.105Z","etag":null,"topics":["aiojobs","aiomcache","aioredis","async","asyncio","fastapi","fastapi-plugins","healthchecks","json","logging","memcached","openapi","openapi3","python","python3","redis","redis-sentinel"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/madkote.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-20T11:41:50.000Z","updated_at":"2025-04-05T04:43:04.000Z","dependencies_parsed_at":"2024-01-03T02:30:08.347Z","dependency_job_id":"0a77ede8-52a9-415d-bf33-76428927059d","html_url":"https://github.com/madkote/fastapi-plugins","commit_stats":{"total_commits":75,"total_committers":5,"mean_commits":15.0,"dds":"0.053333333333333344","last_synced_commit":"69f16040f7819b629779e4a520ec491c8e6eea26"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madkote%2Ffastapi-plugins","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madkote%2Ffastapi-plugins/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madkote%2Ffastapi-plugins/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madkote%2Ffastapi-plugins/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/madkote","download_url":"https://codeload.github.com/madkote/fastapi-plugins/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254254043,"owners_count":22039792,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aiojobs","aiomcache","aioredis","async","asyncio","fastapi","fastapi-plugins","healthchecks","json","logging","memcached","openapi","openapi3","python","python3","redis","redis-sentinel"],"created_at":"2024-07-31T00:00:58.592Z","updated_at":"2025-05-15T01:09:18.049Z","avatar_url":"https://github.com/madkote.png","language":"Python","readme":"\u003cp align=\"center\"\u003e\n    \u003cem\u003ePlugins for FastAPI framework, high performance, easy to learn, fast to code, ready for production\u003c/em\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://travis-ci.org/madkote/fastapi-plugins\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://travis-ci.org/madkote/fastapi_plugins.svg?branch=master\" alt=\"Build Status\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://codecov.io/gh/madkote/fastapi-plugins\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://codecov.io/gh/madkote/fastapi_plugins/branch/master/graph/badge.svg\" alt=\"Coverage\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://pypi.org/project/fastapi-plugins\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/v/fastapi_plugins.svg\" alt=\"Package version\"\u003e\n\u003c/a\u003e\n\u003ca href=\"https://gitter.im/tiangolo/fastapi?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://badges.gitter.im/tiangolo/fastapi.svg\" alt=\"Join the chat at https://gitter.im/tiangolo/fastapi\"\u003e\n\u003c/a\u003e\n\u003c/p\u003e\n\n# fastapi-plugins\nFastAPI framework plugins - simple way to share `fastapi` code and utilities across applications.\n\nThe concept is `plugin` - plug a functional utility into your application without or with minimal effort.\n\n* [Cache](./docs/cache.md)\n  * [Memcached](./docs/cache.md#memcached)\n  * [Redis](./docs/cache.md#redis)\n* [Scheduler](./docs/scheduler.md)\n* [Control](./docs/control.md)\n  * [Version](./docs/control.md#version)\n  * [Environment](./docs/control.md#environment)\n  * [Health](./docs/control.md#health)\n  * [Heartbeat](./docs/control.md#heartbeat)\n* [Application settings/configuration](./docs/settings.md)\n* [Logging](./docs/logger.md)\n* Celery\n* MQ\n* and much more is already in progress...\n\n## Changes\nSee [release notes](CHANGES.md)\n\n## Installation\n* by default contains\n  * [Redis](./docs/cache.md#redis)\n  * [Scheduler](./docs/scheduler.md)\n  * [Control](./docs/control.md)\n  * [Logging](./docs/logger.md)\n* `memcached` adds [Memcached](#memcached)\n* `all` add everything above\n\n```sh\npip install fastapi-plugins\npip install fastapi-plugins[memcached]\npip install fastapi-plugins[all]\n```\n\n## Quick start\n### Plugin\nAdd information about plugin system.\n### Application settings\nAdd information about settings.\n### Application configuration\nAdd information about configuration of an application\n### Complete example\n```python\nimport fastapi\nimport fastapi_plugins\n\nfrom fastapi_plugins.memcached import MemcachedSettings\nfrom fastapi_plugins.memcached import memcached_plugin, TMemcachedPlugin\n\nimport asyncio\nimport aiojobs\nimport aioredis\nimport contextlib\nimport logging\n\n@fastapi_plugins.registered_configuration\nclass AppSettings(\n        fastapi_plugins.ControlSettings,\n        fastapi_plugins.RedisSettings,\n        fastapi_plugins.SchedulerSettings,\n        fastapi_plugins.LoggingSettings,\n        MemcachedSettings,\n):\n    api_name: str = str(__name__)\n    logging_level: int = logging.DEBUG\n    logging_style: fastapi_plugins.LoggingStyle = fastapi_plugins.LoggingStyle.logjson\n\n\n@fastapi_plugins.registered_configuration(name='sentinel')\nclass AppSettingsSentinel(AppSettings):\n    redis_type = fastapi_plugins.RedisType.sentinel\n    redis_sentinels = 'localhost:26379'\n\n\n@contextlib.asynccontextmanager\nasync def lifespan(app: fastapi.FastAPI):\n    config = fastapi_plugins.get_config()\n    await fastapi_plugins.config_plugin.init_app(app, config)\n    await fastapi_plugins.config_plugin.init()\n    await fastapi_plugins.log_plugin.init_app(app, config, name=__name__)\n    await fastapi_plugins.log_plugin.init()\n    await memcached_plugin.init_app(app, config)\n    await memcached_plugin.init()\n    await fastapi_plugins.redis_plugin.init_app(app, config=config)\n    await fastapi_plugins.redis_plugin.init()\n    await fastapi_plugins.scheduler_plugin.init_app(app=app, config=config)\n    await fastapi_plugins.scheduler_plugin.init()\n    await fastapi_plugins.control_plugin.init_app(\n        app,\n        config=config,\n        version=__version__,\n        environ=config.model_dump()\n    )\n    await fastapi_plugins.control_plugin.init()\n    yield\n    await fastapi_plugins.control_plugin.terminate()\n    await fastapi_plugins.scheduler_plugin.terminate()\n    await fastapi_plugins.redis_plugin.terminate()\n    await memcached_plugin.terminate()\n    await fastapi_plugins.log_plugin.terminate()\n    await fastapi_plugins.config_plugin.terminate()\n\n\napp = fastapi_plugins.register_middleware(fastapi.FastAPI(lifespan=lifespan))\n\n\n@app.get(\"/\")\nasync def root_get(\n        cache: fastapi_plugins.TRedisPlugin,\n        conf: fastapi_plugins.TConfigPlugin,\n        logger: fastapi_plugins.TLoggerPlugin\n) -\u003e typing.Dict:\n    ping = await cache.ping()\n    logger.debug('root_get', extra=dict(ping=ping, api_name=conf.api_name))\n    return dict(ping=ping, api_name=conf.api_name)\n\n\n@app.post(\"/jobs/schedule/\u003ctimeout\u003e\")\nasync def job_post(\n    timeout: int=fastapi.Query(..., title='the job sleep time'),\n    cache: fastapi_plugins.TRedisPlugin,\n    scheduler: fastapi_plugins.TSchedulerPlugin,\n    logger: fastapi_plugins.TLoggerPlugin\n) -\u003e str:\n    async def coro(job_id, timeout, cache):\n        await cache.set(job_id, 'processing')\n        try:\n            await asyncio.sleep(timeout)\n            if timeout == 8:\n                logger.critical('Ugly erred job %s' % job_id)\n                raise Exception('ugly error')\n        except asyncio.CancelledError:\n            await cache.set(job_id, 'canceled')\n            logger.warning('Cancel job %s' % job_id)\n        except Exception:\n            await cache.set(job_id, 'erred')\n            logger.error('Erred job %s' % job_id)\n        else:\n            await cache.set(job_id, 'success')\n            logger.info('Done job %s' % job_id)\n\n    job_id = str(uuid.uuid4()).replace('-', '')\n    logger = await fastapi_plugins.log_adapter(logger, extra=dict(job_id=job_id, timeout=timeout))    # noqa E501\n    logger.info('New job %s' % job_id)\n    await cache.set(job_id, 'pending')\n    logger.debug('Pending job %s' % job_id)\n    await scheduler.spawn(coro(job_id, timeout, cache))\n    return job_id\n\n\n@app.get(\"/jobs/status/\u003cjob_id\u003e\")\nasync def job_get(\n    job_id: str=fastapi.Query(..., title='the job id'),\n    cache: fastapi_plugins.TRedisPlugin,\n) -\u003e typing.Dict:\n    status = await cache.get(job_id)\n    if status is None:\n        raise fastapi.HTTPException(\n            status_code=starlette.status.HTTP_404_NOT_FOUND,\n            detail='Job %s not found' % job_id\n        )\n    return dict(job_id=job_id, status=status)\n\n\n@app.post(\"/memcached/demo/\u003ckey\u003e\")\nasync def memcached_demo_post(\n    key: str=fastapi.Query(..., title='the job id'),\n    cache: fastapi_plugins.TMemcachedPlugin,\n) -\u003e typing.Dict:\n    await cache.set(key.encode(), str(key + '_value').encode())\n    value = await cache.get(key.encode())\n    return dict(ping=(await cache.ping()).decode(), key=key, value=value)\n```\n\n# Development\nIssues and suggestions are welcome through [issues](https://github.com/madkote/fastapi-plugins/issues)\n\n# License\nThis project is licensed under the terms of the MIT license.\n","funding_links":[],"categories":["Third-Party Extensions","Python","Packages","FastAPI Utilities"],"sub_categories":["Utils"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmadkote%2Ffastapi-plugins","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmadkote%2Ffastapi-plugins","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmadkote%2Ffastapi-plugins/lists"}