Package: os-aio-pod
os-aio-podA container of AIO components.This project is a framework for combining multiple AIO components into one. For example, you can easily extend your TCP server with a HTTP server to offer HTTP API. Usage is simple, write regular coroutine and config file, start with the command line tool, the framework will take care of the work loop.Each of the coroutine is a magic bean, this framework is a magic pod.ConceptionCustom coroutine is packed as aasyncio.Task, we call it:bean. Thanks to the Python asyncio, all beans can work together. A runner namedpodmaintains the beans and the whole work loop life cycle.Each bean has a unique id. label can also be used for identifying one or more beans.You can access other beans by using a context object with id or label.Signals can be  dispatched to each beans which registered callback function.Installpip install os-aio-podThere are some extra packages can be installed for more  features.subpackageinstall commandenablesuvlooppip install os-aio-pod[uvloop]enableuvloopuvicornpip install os-aio-pod[uvicorn]enableuvicornhttp server adapteraiohttppip install os-aio-pod[aiohttp]enableaiohttphttp server adapteraiomonitorpip install os-aio-pod[aiomonitor]enableaiomonitoradapterUsageQuick startWrite your coroutine function# example.py
import asyncio

async def helloworld(**kwargs):
    await asyncio.sleep(1)
    print("hello world!", kwargs)run withos-aio-podos-aio-pod run example.helloworld:hi="Ozzy"APIsCustom coroutineActually, there are three types of coroutine code for your choice:Regular coroutine, thehelloobject of the following example.import asyncio

async def hello_world(**kwargs):
    print('hello world!')
    await asyncio.sleep(1)

hello = hello_world()Regular coroutine fucntion, thehello_worldfunction of the above example. Keyword arguments can be set in the config file.A class withasync def __call__(self)method and have context as init arguments:class HelloWorld(object):

    def __init__(self, context):
        self.context = context
        
    async def __call__(self, **kwargs):
        print('hello world!')
        await asyncio.sleep(1)ContextWhen you use class type coroutine, you can use the context to communicate with the framework and other beans.Since v0.1.27,pass_contextdecorator can be used for passing context to function as the first argument if it is invoked by the framework.lablecan also be specified as argument@pass_context(label="app")from os_aio_pod.decorators import pass_context

@pass_context
async def hello_world(context, **kwargs):
    print(context, kwargs)SignalsThanks toasyncio_dispatch, we easily can register and deliver signals.Typically, you should only use context APIs to process signals.The systemSIGINT,SIGTERMare caught by the framework to handler shutdown stuff after dispatch to each registered callback.Other system signals are not supported yet.ConfigureConfig file is a regular Python file, all upper case variables will pass to the frame work which can be accessed later. The reserved key words:BEANS: a list of bean config dict, the reserved key words of each bean config are:core,label, other keyword arguments will pass to your functioncore:  string path of your coroutinelabel: optional, can be used to trace your beanLOG_LEVEL: logger level, defaultINFOLOOP_TYPE: default isasyncio, can beuvloopwhen you install uvloopDEBUG: enable debug mode, defaultFalseSTOP_WAIT_TIME: the wait time when recieve signal(SIGINT,SIGTERM). Once timeout, all unfinished bean will be cancelled. Default isNone, indicate wait until all beans doneExample:config.pyBEANS = [
    {
        'core' : 'hello_world.HelloWorld',
        'label': 'first-bean',
        'key1' : 'value1',
    }
]

LOG_LEVEL      = 'debug'
LOOP_TYPE      = 'asyncio'
DEBUG          = False
STOP_WAIT_TIME = 10Command lineos-aio-podcommand can be used to start the whole framework, the typical usage:$ os-aio-pod run -c config.pyor quick start$ os-aio-pod run [awaitable-func1:k1=v1,k2=v2] [awaitable-func2:k3=v3,k4=v4]The reserved config key words(excludeBEANS) can be set by passing command line options.$ os-aio-pod run --helpBuilt-In ComponentsThere are some built-in adapters can be used for convenient:built-in simple server classos_aio_pod.contrib.simple.ServerIt is a scaffold base class for simple serverfrom os_aio_pod.contrib.simple import Server

class YourServer(Server):

    # can be async/sync 
    async def startup(self, **kwargs):
        pass

    # can be async/sync 
    async def cleanup(self, **kwargs):
        pass

    async def run(self, **kwargs):
        print(self.config)

    # on kill(Ctrl+C)
    def on_stop(self, **kwargs):
        passptpython, python REPLpip install ptpython contextvarsBEANS = [
    {
        'core': 'os_aio_pod.contrib.pypython.TelnetServerAdapter',
    }
]you can connect this server with telnetuvicorn, a lightning-fast ASGI serverpip install uvicornBEANS = [
    {
        'core': 'os_aio_pod.contrib.uvicorn.UvicornAdapter',
        'app' : 'your.app.object.path'
    }
]a context object namedaio_pod_contextwill attached to the app objectaiohttp, a well known aio http serverpip install aiohttpBEANS = [
    {
        'core': 'os_aio_pod.contrib.aiohttp.WebAdapter',
        'app' : 'your.app.object.path'
    }
]a context object namedaio_pod_contextwill attached to the app objectaiomonitor, adds monitor and python REPL capabilities for asyncio applicationpip install aiomonitorBEANS = [
    {
        'core': 'os_aio_pod.contrib.aiomonitor.AioMonitorAdapter',
    }
]built-in tcp serverAn event driven server can be inherited fromos_aio_pod.contrib.tcp_server.Server(default server).If protocol is configured, low-level networking protocol interface will be used instead of the server's on_connect method. The server instance can be accessed withyour_protocol.serverBEANS = [
    {
        'core': 'os_aio_pod.contrib.tcp_server.TCPServerAdapter',
        # 'protocol': 'your.asyncio.Protocol.path'
        # 'server': 'your.event.driven.server'
    }
]built-in producer-consumer modelOne producer and multi-consumers is a common model. You can inherit fromos_aio_pod.contrib.pcflow.Server(which is inherit from built-in simple server) and implementproduceandconsumemethods to run as this model.import asyncio

from os_aio_pod.contrib.pcflow import Server


class YourProducerConsumerServer(Server):
    def startup(self, **kwargs):
        self.stopping = False

    def on_stop(self, **kwargs):
        self.stopping = True

    async def produce(self, **kwargs):
        while not self.stopping:
            await asyncio.sleep(1)
            yield 1

    async def consume(self, obj, **kwargs):
        print(obj)BEANS = [
    {
        'core': 'YourProducerConsumerServer',
        'consumer_num': 10,
    }
]Unit TeststoxLicenseMIT licensed.