diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | python-facet.spec | 697 | ||||
| -rw-r--r-- | sources | 1 |
3 files changed, 699 insertions, 0 deletions
@@ -0,0 +1 @@ +/facet-0.9.1.tar.gz diff --git a/python-facet.spec b/python-facet.spec new file mode 100644 index 0000000..3e5238c --- /dev/null +++ b/python-facet.spec @@ -0,0 +1,697 @@ +%global _empty_manifest_terminate_build 0 +Name: python-facet +Version: 0.9.1 +Release: 1 +Summary: service manager for asyncio +License: MIT +URL: https://github.com/pohmelie/facet +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/9d/f8/e6145b20485d8ea77a10a338c35069a37a96a2d7a608abd2cd1e189dd835/facet-0.9.1.tar.gz +BuildArch: noarch + +Requires: python3-pytest +Requires: python3-pytest-asyncio +Requires: python3-pytest-cov +Requires: python3-flake8 + +%description +# Facet +[](https://travis-ci.com/pohmelie/facet) +[](https://codecov.io/gh/pohmelie/facet) +[](https://pypi.org/project/facet/) +[](https://pypi.org/project/facet/) + +Service manager for asyncio. + +# Reason +[`mode`](https://github.com/ask/mode) tries to do too much job: +- Messy callbacks (`on_start`, `on_started`, `on_crashed`, etc.). +- Inheritance restrict naming and forces `super()` calls. +- Forced logging module and logging configuration. + +# Features +- Simple (`start`, `stop`, `dependencies` and `add_task`). +- Configurable via inheritance (graceful shutdown timeout). +- Mixin (no `super()` required). +- Requires no runner engine (`Worker`, `Runner`, etc.) just plain `await` or `async with`. + +# License +`facet` is offered under MIT license. + +# Requirements +* python 3.6+ + +# Usage +``` python +import asyncio +import logging + +from facet import ServiceMixin + + +class B(ServiceMixin): + + def __init__(self): + self.value = 0 + + async def start(self): + self.value += 1 + logging.info("b started") + + async def stop(self): + self.value -= 1 + logging.info("b stopped") + + +class A(ServiceMixin): + + def __init__(self): + self.b = B() + + @property + def dependencies(self): + return [self.b] + + async def start(self): + logging.info("a started") + + async def stop(self): + logging.info("a stopped") + + +logging.basicConfig(level=logging.DEBUG) +asyncio.run(A().run()) +``` +This will produce: +``` +INFO:root:b started +INFO:root:a started +``` +Start and stop order determined by strict rule: **dependencies must be started first and stopped last**. That is why `B` starts before `A`. Since `A` may use `B` in `start` routine. + +Hit `ctrl-c` and you will see: +``` +INFO:root:a stopped +INFO:root:b stopped +Traceback (most recent call last): + ... +KeyboardInterrupt +``` +Stop order is reversed, since `A` may use `B` in `stop` routine. Any raised exception propagates to upper context. `facet` do not trying to be too smart. + +Service can be used as a context manager. Instead of +``` python +asyncio.run(A().run()) +``` +Code can look like: +``` python +async def main(): + async with A() as a: + assert a.b.value == 1 + await a.wait() + +asyncio.run(main()) +``` + +Another service feature is `add_task` method: +``` python +class A(ServiceMixin): + + async def task(self): + await asyncio.sleep(1) + logging.info("task done") + + async def start(self): + self.add_task(self.task()) + logging.info("start done") + + +logging.basicConfig(level=logging.DEBUG) +asyncio.run(A().run()) +``` +This will lead to background task creation and handling: +``` +INFO:root:start done +INFO:root:task done +``` +Any non-handled exception on background task will lead the whole service stack crashed. This is also a key feature to fall down fast and loud. + +All background tasks will be cancelled and awaited on service stop. + +You can manage dependencies start/stop to start sequently, parallel or mixed. Like this: +``` python +class A(ServiceMixin): + + def __init__(self): + self.b = B() + self.c = C() + self.d = D() + + @property + def dependencies(self): + return [ + [self.b, self.c], + self.d, + ] +``` +This leads to first `b` and `c` starts parallel, after they successfully started `d` will try to start, and then `a` itself start will be called. And on stop routine `a` stop called first, then `d` stop, then both `b` and `c` stops parallel. + +The rule here is **first nesting level is sequential, second nesting level is parallel** + +# API +Here is public methods you get on inheritance/mixin: +## `wait` +``` python +async def wait(self): +``` +Wait for service stop. Service must be started. This is useful when you use service as a context manager. + +## `run` +``` python +async def run(self): +``` +Run service and wait until it stop. + +## `graceful_shutdown_timeout` +``` python +@property +def graceful_shutdown_timeout(self): + return 10 +``` +How much total time in seconds wait for stop routines. This property can be overriden with subclass: +``` python +class CustomServiceMixin(ServiceMixin): + @property + def graceful_shutdown_timeout(self): + return 60 +``` + +## `dependencies` +``` python +@property +def dependencies(self): + return [] +``` +Should return iterable of current service dependencies instances. + +## `running` +``` python +@property +def running(self) -> bool: +``` +Check if service is running + +## `add_task` +``` python +def add_task(self, coro) -> asyncio.Task: +``` +Add background task. + +## `start` +``` python +async def start(self): + pass +``` +Start routine. + +## `stop` +``` python +async def stop(self): + pass +``` +Stop routine. + + + + +%package -n python3-facet +Summary: service manager for asyncio +Provides: python-facet +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-facet +# Facet +[](https://travis-ci.com/pohmelie/facet) +[](https://codecov.io/gh/pohmelie/facet) +[](https://pypi.org/project/facet/) +[](https://pypi.org/project/facet/) + +Service manager for asyncio. + +# Reason +[`mode`](https://github.com/ask/mode) tries to do too much job: +- Messy callbacks (`on_start`, `on_started`, `on_crashed`, etc.). +- Inheritance restrict naming and forces `super()` calls. +- Forced logging module and logging configuration. + +# Features +- Simple (`start`, `stop`, `dependencies` and `add_task`). +- Configurable via inheritance (graceful shutdown timeout). +- Mixin (no `super()` required). +- Requires no runner engine (`Worker`, `Runner`, etc.) just plain `await` or `async with`. + +# License +`facet` is offered under MIT license. + +# Requirements +* python 3.6+ + +# Usage +``` python +import asyncio +import logging + +from facet import ServiceMixin + + +class B(ServiceMixin): + + def __init__(self): + self.value = 0 + + async def start(self): + self.value += 1 + logging.info("b started") + + async def stop(self): + self.value -= 1 + logging.info("b stopped") + + +class A(ServiceMixin): + + def __init__(self): + self.b = B() + + @property + def dependencies(self): + return [self.b] + + async def start(self): + logging.info("a started") + + async def stop(self): + logging.info("a stopped") + + +logging.basicConfig(level=logging.DEBUG) +asyncio.run(A().run()) +``` +This will produce: +``` +INFO:root:b started +INFO:root:a started +``` +Start and stop order determined by strict rule: **dependencies must be started first and stopped last**. That is why `B` starts before `A`. Since `A` may use `B` in `start` routine. + +Hit `ctrl-c` and you will see: +``` +INFO:root:a stopped +INFO:root:b stopped +Traceback (most recent call last): + ... +KeyboardInterrupt +``` +Stop order is reversed, since `A` may use `B` in `stop` routine. Any raised exception propagates to upper context. `facet` do not trying to be too smart. + +Service can be used as a context manager. Instead of +``` python +asyncio.run(A().run()) +``` +Code can look like: +``` python +async def main(): + async with A() as a: + assert a.b.value == 1 + await a.wait() + +asyncio.run(main()) +``` + +Another service feature is `add_task` method: +``` python +class A(ServiceMixin): + + async def task(self): + await asyncio.sleep(1) + logging.info("task done") + + async def start(self): + self.add_task(self.task()) + logging.info("start done") + + +logging.basicConfig(level=logging.DEBUG) +asyncio.run(A().run()) +``` +This will lead to background task creation and handling: +``` +INFO:root:start done +INFO:root:task done +``` +Any non-handled exception on background task will lead the whole service stack crashed. This is also a key feature to fall down fast and loud. + +All background tasks will be cancelled and awaited on service stop. + +You can manage dependencies start/stop to start sequently, parallel or mixed. Like this: +``` python +class A(ServiceMixin): + + def __init__(self): + self.b = B() + self.c = C() + self.d = D() + + @property + def dependencies(self): + return [ + [self.b, self.c], + self.d, + ] +``` +This leads to first `b` and `c` starts parallel, after they successfully started `d` will try to start, and then `a` itself start will be called. And on stop routine `a` stop called first, then `d` stop, then both `b` and `c` stops parallel. + +The rule here is **first nesting level is sequential, second nesting level is parallel** + +# API +Here is public methods you get on inheritance/mixin: +## `wait` +``` python +async def wait(self): +``` +Wait for service stop. Service must be started. This is useful when you use service as a context manager. + +## `run` +``` python +async def run(self): +``` +Run service and wait until it stop. + +## `graceful_shutdown_timeout` +``` python +@property +def graceful_shutdown_timeout(self): + return 10 +``` +How much total time in seconds wait for stop routines. This property can be overriden with subclass: +``` python +class CustomServiceMixin(ServiceMixin): + @property + def graceful_shutdown_timeout(self): + return 60 +``` + +## `dependencies` +``` python +@property +def dependencies(self): + return [] +``` +Should return iterable of current service dependencies instances. + +## `running` +``` python +@property +def running(self) -> bool: +``` +Check if service is running + +## `add_task` +``` python +def add_task(self, coro) -> asyncio.Task: +``` +Add background task. + +## `start` +``` python +async def start(self): + pass +``` +Start routine. + +## `stop` +``` python +async def stop(self): + pass +``` +Stop routine. + + + + +%package help +Summary: Development documents and examples for facet +Provides: python3-facet-doc +%description help +# Facet +[](https://travis-ci.com/pohmelie/facet) +[](https://codecov.io/gh/pohmelie/facet) +[](https://pypi.org/project/facet/) +[](https://pypi.org/project/facet/) + +Service manager for asyncio. + +# Reason +[`mode`](https://github.com/ask/mode) tries to do too much job: +- Messy callbacks (`on_start`, `on_started`, `on_crashed`, etc.). +- Inheritance restrict naming and forces `super()` calls. +- Forced logging module and logging configuration. + +# Features +- Simple (`start`, `stop`, `dependencies` and `add_task`). +- Configurable via inheritance (graceful shutdown timeout). +- Mixin (no `super()` required). +- Requires no runner engine (`Worker`, `Runner`, etc.) just plain `await` or `async with`. + +# License +`facet` is offered under MIT license. + +# Requirements +* python 3.6+ + +# Usage +``` python +import asyncio +import logging + +from facet import ServiceMixin + + +class B(ServiceMixin): + + def __init__(self): + self.value = 0 + + async def start(self): + self.value += 1 + logging.info("b started") + + async def stop(self): + self.value -= 1 + logging.info("b stopped") + + +class A(ServiceMixin): + + def __init__(self): + self.b = B() + + @property + def dependencies(self): + return [self.b] + + async def start(self): + logging.info("a started") + + async def stop(self): + logging.info("a stopped") + + +logging.basicConfig(level=logging.DEBUG) +asyncio.run(A().run()) +``` +This will produce: +``` +INFO:root:b started +INFO:root:a started +``` +Start and stop order determined by strict rule: **dependencies must be started first and stopped last**. That is why `B` starts before `A`. Since `A` may use `B` in `start` routine. + +Hit `ctrl-c` and you will see: +``` +INFO:root:a stopped +INFO:root:b stopped +Traceback (most recent call last): + ... +KeyboardInterrupt +``` +Stop order is reversed, since `A` may use `B` in `stop` routine. Any raised exception propagates to upper context. `facet` do not trying to be too smart. + +Service can be used as a context manager. Instead of +``` python +asyncio.run(A().run()) +``` +Code can look like: +``` python +async def main(): + async with A() as a: + assert a.b.value == 1 + await a.wait() + +asyncio.run(main()) +``` + +Another service feature is `add_task` method: +``` python +class A(ServiceMixin): + + async def task(self): + await asyncio.sleep(1) + logging.info("task done") + + async def start(self): + self.add_task(self.task()) + logging.info("start done") + + +logging.basicConfig(level=logging.DEBUG) +asyncio.run(A().run()) +``` +This will lead to background task creation and handling: +``` +INFO:root:start done +INFO:root:task done +``` +Any non-handled exception on background task will lead the whole service stack crashed. This is also a key feature to fall down fast and loud. + +All background tasks will be cancelled and awaited on service stop. + +You can manage dependencies start/stop to start sequently, parallel or mixed. Like this: +``` python +class A(ServiceMixin): + + def __init__(self): + self.b = B() + self.c = C() + self.d = D() + + @property + def dependencies(self): + return [ + [self.b, self.c], + self.d, + ] +``` +This leads to first `b` and `c` starts parallel, after they successfully started `d` will try to start, and then `a` itself start will be called. And on stop routine `a` stop called first, then `d` stop, then both `b` and `c` stops parallel. + +The rule here is **first nesting level is sequential, second nesting level is parallel** + +# API +Here is public methods you get on inheritance/mixin: +## `wait` +``` python +async def wait(self): +``` +Wait for service stop. Service must be started. This is useful when you use service as a context manager. + +## `run` +``` python +async def run(self): +``` +Run service and wait until it stop. + +## `graceful_shutdown_timeout` +``` python +@property +def graceful_shutdown_timeout(self): + return 10 +``` +How much total time in seconds wait for stop routines. This property can be overriden with subclass: +``` python +class CustomServiceMixin(ServiceMixin): + @property + def graceful_shutdown_timeout(self): + return 60 +``` + +## `dependencies` +``` python +@property +def dependencies(self): + return [] +``` +Should return iterable of current service dependencies instances. + +## `running` +``` python +@property +def running(self) -> bool: +``` +Check if service is running + +## `add_task` +``` python +def add_task(self, coro) -> asyncio.Task: +``` +Add background task. + +## `start` +``` python +async def start(self): + pass +``` +Start routine. + +## `stop` +``` python +async def stop(self): + pass +``` +Stop routine. + + + + +%prep +%autosetup -n facet-0.9.1 + +%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-facet -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Tue Apr 11 2023 Python_Bot <Python_Bot@openeuler.org> - 0.9.1-1 +- Package Spec generated @@ -0,0 +1 @@ +8915c3461343f75e040cf2b7aa4769a0 facet-0.9.1.tar.gz |
