summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-05-10 08:29:17 +0000
committerCoprDistGit <infra@openeuler.org>2023-05-10 08:29:17 +0000
commit35cf12bf007ea533c23f61ef33da91f6a12250d4 (patch)
tree567a534a40af605398f8d55119c06b1e5f88b79e
parent1781242da20c34d324900b0518fa7af78410ec07 (diff)
automatic import of python-fastapi-plugins
-rw-r--r--.gitignore1
-rw-r--r--python-fastapi-plugins.spec857
-rw-r--r--sources1
3 files changed, 859 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..e232e03 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/fastapi-plugins-0.12.0.tar.gz
diff --git a/python-fastapi-plugins.spec b/python-fastapi-plugins.spec
new file mode 100644
index 0000000..c6567b2
--- /dev/null
+++ b/python-fastapi-plugins.spec
@@ -0,0 +1,857 @@
+%global _empty_manifest_terminate_build 0
+Name: python-fastapi-plugins
+Version: 0.12.0
+Release: 1
+Summary: Plugins for FastAPI framework
+License: MIT License
+URL: https://github.com/madkote/fastapi-plugins
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/d3/7d/bf07f02f24bc2c397ebca6835d6c72b17bea3d7b95bf984610751c92e0a4/fastapi-plugins-0.12.0.tar.gz
+BuildArch: noarch
+
+Requires: python3-fastapi
+Requires: python3-pydantic
+Requires: python3-tenacity
+Requires: python3-json-logger
+Requires: python3-redis[hiredis]
+Requires: python3-aiojobs
+Requires: python3-aiomcache
+Requires: python3-aiomcache
+Requires: python3-fakeredis[lua]
+Requires: python3-bandit
+Requires: python3-docker-compose
+Requires: python3-flake8
+Requires: python3-pytest
+Requires: python3-pytest-asyncio
+Requires: python3-pytest-cov
+Requires: python3-tox
+Requires: python3-twine
+Requires: python3-fastapi[all]
+Requires: python3-fakeredis[lua]
+Requires: python3-aiomcache
+
+%description
+<p align="center">
+ <em>Plugins for FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
+</p>
+<p align="center">
+<a href="https://travis-ci.org/madkote/fastapi-plugins" target="_blank">
+ <img src="https://travis-ci.org/madkote/fastapi_plugins.svg?branch=master" alt="Build Status">
+</a>
+<a href="https://codecov.io/gh/madkote/fastapi-plugins" target="_blank">
+ <img src="https://codecov.io/gh/madkote/fastapi_plugins/branch/master/graph/badge.svg" alt="Coverage">
+</a>
+<a href="https://pypi.org/project/fastapi-plugins" target="_blank">
+ <img src="https://img.shields.io/pypi/v/fastapi_plugins.svg" alt="Package version">
+</a>
+<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
+ <img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
+</a>
+</p>
+
+# important
+Aioredis is about to merge into [redis-py](https://github.com/redis/redis-py).
+So waiting for release and first benchmarks. Version `1.3.1` remains the fastest.
+
+# fastapi-plugins
+FastAPI framework plugins - simple way to share `fastapi` code and utilities across applications.
+
+The concept is `plugin` - plug a functional utility into your application without or with minimal effort.
+
+* [Cache](./docs/cache.md)
+ * [Memcached](./docs/cache.md#memcached)
+ * [Redis](./docs/cache.md#redis)
+* [Scheduler](./docs/scheduler.md)
+* [Control](./docs/control.md)
+ * [Version](./docs/control.md#version)
+ * [Environment](./docs/control.md#environment)
+ * [Health](./docs/control.md#health)
+ * [Heartbeat](./docs/control.md#heartbeat)
+* [Application settings/configuration](./docs/settings.md)
+* [Logging](./docs/logger.md)
+* Celery
+* MQ
+* and much more is already in progress...
+
+## Changes
+See [release notes](CHANGES.md)
+
+## Installation
+* by default contains
+ * [Redis](./docs/cache.md#redis)
+ * [Scheduler](./docs/scheduler.md)
+ * [Control](./docs/control.md)
+ * [Logging](./docs/logger.md)
+* `memcached` adds [Memcached](#memcached)
+* `all` add everything above
+
+```sh
+pip install fastapi-plugins
+pip install fastapi-plugins[memcached]
+pip install fastapi-plugins[all]
+```
+
+## Quick start
+### Plugin
+Add information about plugin system.
+### Application settings
+Add information about settings.
+### Application configuration
+Add information about configuration of an application
+### Complete example
+```python
+import fastapi
+import fastapi_plugins
+
+from fastapi_plugins.memcached import MemcachedSettings
+from fastapi_plugins.memcached import memcached_plugin, TMemcachedPlugin
+
+import asyncio
+import aiojobs
+import aioredis
+import contextlib
+import logging
+
+@fastapi_plugins.registered_configuration
+class AppSettings(
+ fastapi_plugins.ControlSettings,
+ fastapi_plugins.RedisSettings,
+ fastapi_plugins.SchedulerSettings,
+ fastapi_plugins.LoggingSettings,
+ MemcachedSettings,
+):
+ api_name: str = str(__name__)
+ logging_level: int = logging.DEBUG
+ logging_style: fastapi_plugins.LoggingStyle = fastapi_plugins.LoggingStyle.logjson
+
+
+@fastapi_plugins.registered_configuration(name='sentinel')
+class AppSettingsSentinel(AppSettings):
+ redis_type = fastapi_plugins.RedisType.sentinel
+ redis_sentinels = 'localhost:26379'
+
+
+@contextlib.asynccontextmanager
+async def lifespan(app: fastapi.FastAPI):
+ config = fastapi_plugins.get_config()
+ await fastapi_plugins.config_plugin.init_app(app, config)
+ await fastapi_plugins.config_plugin.init()
+ await fastapi_plugins.log_plugin.init_app(app, config, name=__name__)
+ await fastapi_plugins.log_plugin.init()
+ await memcached_plugin.init_app(app, config)
+ await memcached_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=__version__,
+ environ=config.dict()
+ )
+ await fastapi_plugins.control_plugin.init()
+ yield
+ await fastapi_plugins.control_plugin.terminate()
+ await fastapi_plugins.scheduler_plugin.terminate()
+ await fastapi_plugins.redis_plugin.terminate()
+ await memcached_plugin.terminate()
+ await fastapi_plugins.log_plugin.terminate()
+ await fastapi_plugins.config_plugin.terminate()
+
+
+app = fastapi_plugins.register_middleware(fastapi.FastAPI(lifespan=lifespan))
+
+
+@app.get("/")
+async def root_get(
+ cache: fastapi_plugins.TRedisPlugin,
+ conf: fastapi_plugins.TConfigPlugin,
+ logger: fastapi_plugins.TLoggerPlugin
+) -> typing.Dict:
+ ping = await cache.ping()
+ logger.debug('root_get', extra=dict(ping=ping, api_name=conf.api_name))
+ return dict(ping=ping, api_name=conf.api_name)
+
+
+@app.post("/jobs/schedule/<timeout>")
+async def job_post(
+ timeout: int=fastapi.Query(..., title='the job sleep time'),
+ cache: fastapi_plugins.TRedisPlugin,
+ scheduler: fastapi_plugins.TSchedulerPlugin,
+ logger: fastapi_plugins.TLoggerPlugin
+) -> str:
+ async def coro(job_id, timeout, cache):
+ await cache.set(job_id, 'processing')
+ try:
+ await asyncio.sleep(timeout)
+ if timeout == 8:
+ logger.critical('Ugly erred job %s' % job_id)
+ raise Exception('ugly error')
+ except asyncio.CancelledError:
+ await cache.set(job_id, 'canceled')
+ logger.warning('Cancel job %s' % job_id)
+ except Exception:
+ await cache.set(job_id, 'erred')
+ logger.error('Erred job %s' % job_id)
+ else:
+ await cache.set(job_id, 'success')
+ logger.info('Done job %s' % job_id)
+
+ job_id = str(uuid.uuid4()).replace('-', '')
+ logger = await fastapi_plugins.log_adapter(logger, extra=dict(job_id=job_id, timeout=timeout)) # noqa E501
+ logger.info('New job %s' % job_id)
+ await cache.set(job_id, 'pending')
+ logger.debug('Pending job %s' % job_id)
+ 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: fastapi_plugins.TRedisPlugin,
+) -> 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.post("/memcached/demo/<key>")
+async def memcached_demo_post(
+ key: str=fastapi.Query(..., title='the job id'),
+ cache: fastapi_plugins.TMemcachedPlugin,
+) -> typing.Dict:
+ await cache.set(key.encode(), str(key + '_value').encode())
+ value = await cache.get(key.encode())
+ return dict(ping=(await cache.ping()).decode(), key=key, value=value)
+```
+
+# Development
+Issues and suggestions are welcome through [issues](https://github.com/madkote/fastapi-plugins/issues)
+
+# License
+This project is licensed under the terms of the MIT license.
+
+
+# Changes
+## 0.12.0 (2023-03-24)
+- `[feature]` `Annotated` support
+## 0.11.0 (2022-09-19)
+- `[feature]` `redis-py` replaces `aioredis`
+## 0.10.0 (2022-07-07)
+- `[feature]` Update `aioredis` to `2.x.x`
+- `[feature]` Add `fakeredis` optionally for development purpose
+## 0.9.1 (2022-06-16)
+- `[fix]` Fix empty router prefix for control plugin
+## 0.9.0 (2021-09-27)
+- `[feature]` Logging plugin
+- `[feature]` Middleware interface - register middleware at application
+## 0.8.2 (2021-09-23)
+- `[fix]` Fix dependency for aioredis
+## 0.8.1 (2021-03-31)
+- `[fix]` Fix settings for Python 3.7
+## 0.8.0 (2021-03-31)
+- `[feature]` Settings plugin
+## 0.7.0 (2021-03-29)
+- `[feature]` Control plugin with Health, Heartbeat, Environment and Version
+## 0.6.1 (2021-03-24)
+- `[fix]` Bump `aiojobs`to get rid of not required dependencies
+## 0.6.0 (2020-11-26)
+- `[feature]` Memcached
+## 0.5.0 (2020-11-25)
+- [bug] remove `__all__` since no API as such ([#6][i6]).
+- [typo] Fix typos in README ([#7][i7]).
+- [feature] Add Redis TTL ([#8][i8]).
+## 0.4.2 (2020-11-24)
+- [bug] Fix Redis URL ([#4][i4]).
+## 0.4.1 (2020-06-16)
+- Refactor requirements
+## 0.4.0 (2020-04-09)
+- structure and split dependencies to `extra`
+## 0.3.0 (2020-04-07)
+- Scheduler: tasks scheduler based on `aiojobs`
+## 0.2.1 (2020-04-06)
+- Redis: pre-start
+## 0.2.0 (2019-12-11)
+- Redis: sentinels
+## 0.1.0 (2019-11-20)
+- Initial release: simple redis pool client
+
+[i4]: https://github.com/madkote/fastapi-plugins/pull/4
+[i6]: https://github.com/madkote/fastapi-plugins/pull/6
+[i7]: https://github.com/madkote/fastapi-plugins/pull/7
+[i8]: https://github.com/madkote/fastapi-plugins/issues/8
+
+
+%package -n python3-fastapi-plugins
+Summary: Plugins for FastAPI framework
+Provides: python-fastapi-plugins
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-fastapi-plugins
+<p align="center">
+ <em>Plugins for FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
+</p>
+<p align="center">
+<a href="https://travis-ci.org/madkote/fastapi-plugins" target="_blank">
+ <img src="https://travis-ci.org/madkote/fastapi_plugins.svg?branch=master" alt="Build Status">
+</a>
+<a href="https://codecov.io/gh/madkote/fastapi-plugins" target="_blank">
+ <img src="https://codecov.io/gh/madkote/fastapi_plugins/branch/master/graph/badge.svg" alt="Coverage">
+</a>
+<a href="https://pypi.org/project/fastapi-plugins" target="_blank">
+ <img src="https://img.shields.io/pypi/v/fastapi_plugins.svg" alt="Package version">
+</a>
+<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
+ <img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
+</a>
+</p>
+
+# important
+Aioredis is about to merge into [redis-py](https://github.com/redis/redis-py).
+So waiting for release and first benchmarks. Version `1.3.1` remains the fastest.
+
+# fastapi-plugins
+FastAPI framework plugins - simple way to share `fastapi` code and utilities across applications.
+
+The concept is `plugin` - plug a functional utility into your application without or with minimal effort.
+
+* [Cache](./docs/cache.md)
+ * [Memcached](./docs/cache.md#memcached)
+ * [Redis](./docs/cache.md#redis)
+* [Scheduler](./docs/scheduler.md)
+* [Control](./docs/control.md)
+ * [Version](./docs/control.md#version)
+ * [Environment](./docs/control.md#environment)
+ * [Health](./docs/control.md#health)
+ * [Heartbeat](./docs/control.md#heartbeat)
+* [Application settings/configuration](./docs/settings.md)
+* [Logging](./docs/logger.md)
+* Celery
+* MQ
+* and much more is already in progress...
+
+## Changes
+See [release notes](CHANGES.md)
+
+## Installation
+* by default contains
+ * [Redis](./docs/cache.md#redis)
+ * [Scheduler](./docs/scheduler.md)
+ * [Control](./docs/control.md)
+ * [Logging](./docs/logger.md)
+* `memcached` adds [Memcached](#memcached)
+* `all` add everything above
+
+```sh
+pip install fastapi-plugins
+pip install fastapi-plugins[memcached]
+pip install fastapi-plugins[all]
+```
+
+## Quick start
+### Plugin
+Add information about plugin system.
+### Application settings
+Add information about settings.
+### Application configuration
+Add information about configuration of an application
+### Complete example
+```python
+import fastapi
+import fastapi_plugins
+
+from fastapi_plugins.memcached import MemcachedSettings
+from fastapi_plugins.memcached import memcached_plugin, TMemcachedPlugin
+
+import asyncio
+import aiojobs
+import aioredis
+import contextlib
+import logging
+
+@fastapi_plugins.registered_configuration
+class AppSettings(
+ fastapi_plugins.ControlSettings,
+ fastapi_plugins.RedisSettings,
+ fastapi_plugins.SchedulerSettings,
+ fastapi_plugins.LoggingSettings,
+ MemcachedSettings,
+):
+ api_name: str = str(__name__)
+ logging_level: int = logging.DEBUG
+ logging_style: fastapi_plugins.LoggingStyle = fastapi_plugins.LoggingStyle.logjson
+
+
+@fastapi_plugins.registered_configuration(name='sentinel')
+class AppSettingsSentinel(AppSettings):
+ redis_type = fastapi_plugins.RedisType.sentinel
+ redis_sentinels = 'localhost:26379'
+
+
+@contextlib.asynccontextmanager
+async def lifespan(app: fastapi.FastAPI):
+ config = fastapi_plugins.get_config()
+ await fastapi_plugins.config_plugin.init_app(app, config)
+ await fastapi_plugins.config_plugin.init()
+ await fastapi_plugins.log_plugin.init_app(app, config, name=__name__)
+ await fastapi_plugins.log_plugin.init()
+ await memcached_plugin.init_app(app, config)
+ await memcached_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=__version__,
+ environ=config.dict()
+ )
+ await fastapi_plugins.control_plugin.init()
+ yield
+ await fastapi_plugins.control_plugin.terminate()
+ await fastapi_plugins.scheduler_plugin.terminate()
+ await fastapi_plugins.redis_plugin.terminate()
+ await memcached_plugin.terminate()
+ await fastapi_plugins.log_plugin.terminate()
+ await fastapi_plugins.config_plugin.terminate()
+
+
+app = fastapi_plugins.register_middleware(fastapi.FastAPI(lifespan=lifespan))
+
+
+@app.get("/")
+async def root_get(
+ cache: fastapi_plugins.TRedisPlugin,
+ conf: fastapi_plugins.TConfigPlugin,
+ logger: fastapi_plugins.TLoggerPlugin
+) -> typing.Dict:
+ ping = await cache.ping()
+ logger.debug('root_get', extra=dict(ping=ping, api_name=conf.api_name))
+ return dict(ping=ping, api_name=conf.api_name)
+
+
+@app.post("/jobs/schedule/<timeout>")
+async def job_post(
+ timeout: int=fastapi.Query(..., title='the job sleep time'),
+ cache: fastapi_plugins.TRedisPlugin,
+ scheduler: fastapi_plugins.TSchedulerPlugin,
+ logger: fastapi_plugins.TLoggerPlugin
+) -> str:
+ async def coro(job_id, timeout, cache):
+ await cache.set(job_id, 'processing')
+ try:
+ await asyncio.sleep(timeout)
+ if timeout == 8:
+ logger.critical('Ugly erred job %s' % job_id)
+ raise Exception('ugly error')
+ except asyncio.CancelledError:
+ await cache.set(job_id, 'canceled')
+ logger.warning('Cancel job %s' % job_id)
+ except Exception:
+ await cache.set(job_id, 'erred')
+ logger.error('Erred job %s' % job_id)
+ else:
+ await cache.set(job_id, 'success')
+ logger.info('Done job %s' % job_id)
+
+ job_id = str(uuid.uuid4()).replace('-', '')
+ logger = await fastapi_plugins.log_adapter(logger, extra=dict(job_id=job_id, timeout=timeout)) # noqa E501
+ logger.info('New job %s' % job_id)
+ await cache.set(job_id, 'pending')
+ logger.debug('Pending job %s' % job_id)
+ 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: fastapi_plugins.TRedisPlugin,
+) -> 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.post("/memcached/demo/<key>")
+async def memcached_demo_post(
+ key: str=fastapi.Query(..., title='the job id'),
+ cache: fastapi_plugins.TMemcachedPlugin,
+) -> typing.Dict:
+ await cache.set(key.encode(), str(key + '_value').encode())
+ value = await cache.get(key.encode())
+ return dict(ping=(await cache.ping()).decode(), key=key, value=value)
+```
+
+# Development
+Issues and suggestions are welcome through [issues](https://github.com/madkote/fastapi-plugins/issues)
+
+# License
+This project is licensed under the terms of the MIT license.
+
+
+# Changes
+## 0.12.0 (2023-03-24)
+- `[feature]` `Annotated` support
+## 0.11.0 (2022-09-19)
+- `[feature]` `redis-py` replaces `aioredis`
+## 0.10.0 (2022-07-07)
+- `[feature]` Update `aioredis` to `2.x.x`
+- `[feature]` Add `fakeredis` optionally for development purpose
+## 0.9.1 (2022-06-16)
+- `[fix]` Fix empty router prefix for control plugin
+## 0.9.0 (2021-09-27)
+- `[feature]` Logging plugin
+- `[feature]` Middleware interface - register middleware at application
+## 0.8.2 (2021-09-23)
+- `[fix]` Fix dependency for aioredis
+## 0.8.1 (2021-03-31)
+- `[fix]` Fix settings for Python 3.7
+## 0.8.0 (2021-03-31)
+- `[feature]` Settings plugin
+## 0.7.0 (2021-03-29)
+- `[feature]` Control plugin with Health, Heartbeat, Environment and Version
+## 0.6.1 (2021-03-24)
+- `[fix]` Bump `aiojobs`to get rid of not required dependencies
+## 0.6.0 (2020-11-26)
+- `[feature]` Memcached
+## 0.5.0 (2020-11-25)
+- [bug] remove `__all__` since no API as such ([#6][i6]).
+- [typo] Fix typos in README ([#7][i7]).
+- [feature] Add Redis TTL ([#8][i8]).
+## 0.4.2 (2020-11-24)
+- [bug] Fix Redis URL ([#4][i4]).
+## 0.4.1 (2020-06-16)
+- Refactor requirements
+## 0.4.0 (2020-04-09)
+- structure and split dependencies to `extra`
+## 0.3.0 (2020-04-07)
+- Scheduler: tasks scheduler based on `aiojobs`
+## 0.2.1 (2020-04-06)
+- Redis: pre-start
+## 0.2.0 (2019-12-11)
+- Redis: sentinels
+## 0.1.0 (2019-11-20)
+- Initial release: simple redis pool client
+
+[i4]: https://github.com/madkote/fastapi-plugins/pull/4
+[i6]: https://github.com/madkote/fastapi-plugins/pull/6
+[i7]: https://github.com/madkote/fastapi-plugins/pull/7
+[i8]: https://github.com/madkote/fastapi-plugins/issues/8
+
+
+%package help
+Summary: Development documents and examples for fastapi-plugins
+Provides: python3-fastapi-plugins-doc
+%description help
+<p align="center">
+ <em>Plugins for FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
+</p>
+<p align="center">
+<a href="https://travis-ci.org/madkote/fastapi-plugins" target="_blank">
+ <img src="https://travis-ci.org/madkote/fastapi_plugins.svg?branch=master" alt="Build Status">
+</a>
+<a href="https://codecov.io/gh/madkote/fastapi-plugins" target="_blank">
+ <img src="https://codecov.io/gh/madkote/fastapi_plugins/branch/master/graph/badge.svg" alt="Coverage">
+</a>
+<a href="https://pypi.org/project/fastapi-plugins" target="_blank">
+ <img src="https://img.shields.io/pypi/v/fastapi_plugins.svg" alt="Package version">
+</a>
+<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
+ <img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
+</a>
+</p>
+
+# important
+Aioredis is about to merge into [redis-py](https://github.com/redis/redis-py).
+So waiting for release and first benchmarks. Version `1.3.1` remains the fastest.
+
+# fastapi-plugins
+FastAPI framework plugins - simple way to share `fastapi` code and utilities across applications.
+
+The concept is `plugin` - plug a functional utility into your application without or with minimal effort.
+
+* [Cache](./docs/cache.md)
+ * [Memcached](./docs/cache.md#memcached)
+ * [Redis](./docs/cache.md#redis)
+* [Scheduler](./docs/scheduler.md)
+* [Control](./docs/control.md)
+ * [Version](./docs/control.md#version)
+ * [Environment](./docs/control.md#environment)
+ * [Health](./docs/control.md#health)
+ * [Heartbeat](./docs/control.md#heartbeat)
+* [Application settings/configuration](./docs/settings.md)
+* [Logging](./docs/logger.md)
+* Celery
+* MQ
+* and much more is already in progress...
+
+## Changes
+See [release notes](CHANGES.md)
+
+## Installation
+* by default contains
+ * [Redis](./docs/cache.md#redis)
+ * [Scheduler](./docs/scheduler.md)
+ * [Control](./docs/control.md)
+ * [Logging](./docs/logger.md)
+* `memcached` adds [Memcached](#memcached)
+* `all` add everything above
+
+```sh
+pip install fastapi-plugins
+pip install fastapi-plugins[memcached]
+pip install fastapi-plugins[all]
+```
+
+## Quick start
+### Plugin
+Add information about plugin system.
+### Application settings
+Add information about settings.
+### Application configuration
+Add information about configuration of an application
+### Complete example
+```python
+import fastapi
+import fastapi_plugins
+
+from fastapi_plugins.memcached import MemcachedSettings
+from fastapi_plugins.memcached import memcached_plugin, TMemcachedPlugin
+
+import asyncio
+import aiojobs
+import aioredis
+import contextlib
+import logging
+
+@fastapi_plugins.registered_configuration
+class AppSettings(
+ fastapi_plugins.ControlSettings,
+ fastapi_plugins.RedisSettings,
+ fastapi_plugins.SchedulerSettings,
+ fastapi_plugins.LoggingSettings,
+ MemcachedSettings,
+):
+ api_name: str = str(__name__)
+ logging_level: int = logging.DEBUG
+ logging_style: fastapi_plugins.LoggingStyle = fastapi_plugins.LoggingStyle.logjson
+
+
+@fastapi_plugins.registered_configuration(name='sentinel')
+class AppSettingsSentinel(AppSettings):
+ redis_type = fastapi_plugins.RedisType.sentinel
+ redis_sentinels = 'localhost:26379'
+
+
+@contextlib.asynccontextmanager
+async def lifespan(app: fastapi.FastAPI):
+ config = fastapi_plugins.get_config()
+ await fastapi_plugins.config_plugin.init_app(app, config)
+ await fastapi_plugins.config_plugin.init()
+ await fastapi_plugins.log_plugin.init_app(app, config, name=__name__)
+ await fastapi_plugins.log_plugin.init()
+ await memcached_plugin.init_app(app, config)
+ await memcached_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=__version__,
+ environ=config.dict()
+ )
+ await fastapi_plugins.control_plugin.init()
+ yield
+ await fastapi_plugins.control_plugin.terminate()
+ await fastapi_plugins.scheduler_plugin.terminate()
+ await fastapi_plugins.redis_plugin.terminate()
+ await memcached_plugin.terminate()
+ await fastapi_plugins.log_plugin.terminate()
+ await fastapi_plugins.config_plugin.terminate()
+
+
+app = fastapi_plugins.register_middleware(fastapi.FastAPI(lifespan=lifespan))
+
+
+@app.get("/")
+async def root_get(
+ cache: fastapi_plugins.TRedisPlugin,
+ conf: fastapi_plugins.TConfigPlugin,
+ logger: fastapi_plugins.TLoggerPlugin
+) -> typing.Dict:
+ ping = await cache.ping()
+ logger.debug('root_get', extra=dict(ping=ping, api_name=conf.api_name))
+ return dict(ping=ping, api_name=conf.api_name)
+
+
+@app.post("/jobs/schedule/<timeout>")
+async def job_post(
+ timeout: int=fastapi.Query(..., title='the job sleep time'),
+ cache: fastapi_plugins.TRedisPlugin,
+ scheduler: fastapi_plugins.TSchedulerPlugin,
+ logger: fastapi_plugins.TLoggerPlugin
+) -> str:
+ async def coro(job_id, timeout, cache):
+ await cache.set(job_id, 'processing')
+ try:
+ await asyncio.sleep(timeout)
+ if timeout == 8:
+ logger.critical('Ugly erred job %s' % job_id)
+ raise Exception('ugly error')
+ except asyncio.CancelledError:
+ await cache.set(job_id, 'canceled')
+ logger.warning('Cancel job %s' % job_id)
+ except Exception:
+ await cache.set(job_id, 'erred')
+ logger.error('Erred job %s' % job_id)
+ else:
+ await cache.set(job_id, 'success')
+ logger.info('Done job %s' % job_id)
+
+ job_id = str(uuid.uuid4()).replace('-', '')
+ logger = await fastapi_plugins.log_adapter(logger, extra=dict(job_id=job_id, timeout=timeout)) # noqa E501
+ logger.info('New job %s' % job_id)
+ await cache.set(job_id, 'pending')
+ logger.debug('Pending job %s' % job_id)
+ 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: fastapi_plugins.TRedisPlugin,
+) -> 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.post("/memcached/demo/<key>")
+async def memcached_demo_post(
+ key: str=fastapi.Query(..., title='the job id'),
+ cache: fastapi_plugins.TMemcachedPlugin,
+) -> typing.Dict:
+ await cache.set(key.encode(), str(key + '_value').encode())
+ value = await cache.get(key.encode())
+ return dict(ping=(await cache.ping()).decode(), key=key, value=value)
+```
+
+# Development
+Issues and suggestions are welcome through [issues](https://github.com/madkote/fastapi-plugins/issues)
+
+# License
+This project is licensed under the terms of the MIT license.
+
+
+# Changes
+## 0.12.0 (2023-03-24)
+- `[feature]` `Annotated` support
+## 0.11.0 (2022-09-19)
+- `[feature]` `redis-py` replaces `aioredis`
+## 0.10.0 (2022-07-07)
+- `[feature]` Update `aioredis` to `2.x.x`
+- `[feature]` Add `fakeredis` optionally for development purpose
+## 0.9.1 (2022-06-16)
+- `[fix]` Fix empty router prefix for control plugin
+## 0.9.0 (2021-09-27)
+- `[feature]` Logging plugin
+- `[feature]` Middleware interface - register middleware at application
+## 0.8.2 (2021-09-23)
+- `[fix]` Fix dependency for aioredis
+## 0.8.1 (2021-03-31)
+- `[fix]` Fix settings for Python 3.7
+## 0.8.0 (2021-03-31)
+- `[feature]` Settings plugin
+## 0.7.0 (2021-03-29)
+- `[feature]` Control plugin with Health, Heartbeat, Environment and Version
+## 0.6.1 (2021-03-24)
+- `[fix]` Bump `aiojobs`to get rid of not required dependencies
+## 0.6.0 (2020-11-26)
+- `[feature]` Memcached
+## 0.5.0 (2020-11-25)
+- [bug] remove `__all__` since no API as such ([#6][i6]).
+- [typo] Fix typos in README ([#7][i7]).
+- [feature] Add Redis TTL ([#8][i8]).
+## 0.4.2 (2020-11-24)
+- [bug] Fix Redis URL ([#4][i4]).
+## 0.4.1 (2020-06-16)
+- Refactor requirements
+## 0.4.0 (2020-04-09)
+- structure and split dependencies to `extra`
+## 0.3.0 (2020-04-07)
+- Scheduler: tasks scheduler based on `aiojobs`
+## 0.2.1 (2020-04-06)
+- Redis: pre-start
+## 0.2.0 (2019-12-11)
+- Redis: sentinels
+## 0.1.0 (2019-11-20)
+- Initial release: simple redis pool client
+
+[i4]: https://github.com/madkote/fastapi-plugins/pull/4
+[i6]: https://github.com/madkote/fastapi-plugins/pull/6
+[i7]: https://github.com/madkote/fastapi-plugins/pull/7
+[i8]: https://github.com/madkote/fastapi-plugins/issues/8
+
+
+%prep
+%autosetup -n fastapi-plugins-0.12.0
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-fastapi-plugins -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Wed May 10 2023 Python_Bot <Python_Bot@openeuler.org> - 0.12.0-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..e7b946d
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+33b1132e57aeaaddc96dec4cc862b763 fastapi-plugins-0.12.0.tar.gz