{ "info": { "author": "Dmitriy Vlasov", "author_email": "scailer@yandex.ru", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Framework :: AsyncIO", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "MicroAgent\n==========\n\nMicroAgent is a tool for building multiagent ecosystems for distributed programs. MicroAgent allow you faster write apps on event-oriented and data-driven architectures. It provide universal API for work with event bus and queue brokers, and periodical tasks - by interval and \"as cron\".\n\nInstalling\n----------\n\nWith aioredis_ backend provide signal bus and list-based queues::\n\n pip install 'microagent[aioredis]'\n\nWith aioamqp_ backend provide queues over AMQP (RabbitMQ)::\n\n pip install 'microagent[amqp]'\n\nWith kafka_ backend provide queues over Kafka (experemental)::\n\n pip install 'microagent[kafka]'\n\nWith pulsar_ backend provide signal bus (Redis) and list-based queues (Redis)::\n\n pip install 'microagent[pulsar]'\n\nWith mocks for writing tests::\n\n pip install 'microagent[mock]'\n\nStart\n-----\n\nMinimal working example\n\n.. code-block:: python\n\n import asyncio\n from microagent import MicroAgent, periodic\n\n class MyAgent(MicroAgent):\n @periodic(period=1, timeout=1)\n async def hello(self):\n print('Hellow world!')\n\n async def main():\n await MyAgent().start()\n\n if __name__ == '__main__':\n loop = asyncio.get_event_loop()\n loop.call_soon(lambda: asyncio.ensure_future(main()))\n loop.run_forever()\n\n\nEvent-driven\n------------\n\n.. code-block:: python\n\n import os\n import asyncio\n\n from microagent import MicroAgent, periodic, receiver, load_stuff\n from microagent.tools.aioredis import AIORedisSignalBus\n\n cur_dir = os.path.dirname(os.path.realpath(__file__))\n signals, queues = load_stuff('file://' + os.path.join(cur_dir, 'events.json'))\n\n\n class SenderAgent(MicroAgent):\n @periodic(period=1, timeout=1)\n async def sender(self):\n await self.bus.my_event.send('sender_name', val1=1, val2='a')\n\n\n class CatcherAgent(MicroAgent):\n @receiver(signals.my_event)\n async def catcher(self, signal, sender, val1, val2):\n print(f'Catch {signal} {sender} {val1} {val2}')\n\n\n async def main():\n bus = AIORedisSignalBus('redis://localhost/7')\n await SenderAgent(bus=bus).start()\n await CatcherAgent(bus=bus).start()\n\nevents.json\n\n.. code-block:: javascript\n\n {\n \"version\": 1,\n \"signals\": [\n {\"name\": \"my_event\", \"providing_args\": [\"val1\", \"val2\"]}\n ]\n }\n\nRun\n\n.. code-block::\n\n $ python3 examples/event_driven.py\n Catch sender_name 1 a\n Catch sender_name 1 a\n Catch sender_name 1 a\n\n\nData-driven\n-----------\n\n.. code-block:: python\n\n import os\n import asyncio\n\n from microagent import MicroAgent, periodic, consumer, load_stuff\n from microagent.tools.aioredis import AIORedisBroker\n\n cur_dir = os.path.dirname(os.path.realpath(__file__))\n signals, queues = load_stuff('file://' + os.path.join(cur_dir, 'queues.json'))\n\n\n class SenderAgent(MicroAgent):\n @periodic(period=1, timeout=1)\n async def sender(self):\n await self.broker.my_queue.send({'val1': 1, 'val2': 'a'})\n\n\n class CatcherAgent(MicroAgent):\n @consumer(queues.my_queue)\n async def catcher(self, val1, **data):\n print(f'Catch {val1} {data}')\n\n\n async def main():\n broker = AIORedisBroker('redis://localhost/7')\n await SenderAgent(broker=broker).start()\n await CatcherAgent(broker=broker).start()\n\nqueues.json\n\n.. code-block:: javascript\n\n {\n \"version\": 1,\n \"queues\": [\n {\"name\": \"my_queue\"}\n ]\n }\n\nRun\n\n.. code-block::\n\n $ python3 examples/data_driven.py\n Catch 1 {'val2': 'a'}\n Catch 1 {'val2': 'a'}\n Catch 1 {'val2': 'a'}\n\n\nSync handling with RPC\n----------------------\n\n.. code-block:: python\n\n import os\n import sys\n import time\n import asyncio\n import logging\n\n from microagent import MicroAgent, periodic, receiver, load_stuff\n from microagent.tools.aioredis import AIORedisSignalBus\n\n logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)\n cur_dir = os.path.dirname(os.path.realpath(__file__))\n signals, queues = load_stuff('file://' + os.path.join(cur_dir, 'events.json'))\n\n\n class SenderAgent(MicroAgent):\n @periodic(period=5, timeout=5)\n async def sender(self):\n self.log.info('Begin at %s', time.asctime())\n response = await self.bus.my_event.call('sender_name', val1=1, val2='a')\n self.log.info('Finish at %s with %s', time.asctime(), response)\n\n\n class CatcherAgent(MicroAgent):\n @receiver(signals.my_event)\n async def catcher(self, signal, sender, val1, val2):\n self.log.info(f'Catch {signal} {sender} {val1} {val2}')\n await asyncio.sleep(3)\n return 1\n\n\n async def main():\n bus = AIORedisSignalBus('redis://localhost/7')\n await SenderAgent(bus=bus).start()\n await CatcherAgent(bus=bus).start()\n\nRun\n\n.. code-block::\n\n $ python3 examples/remote_call.py\n INFO:microagent:Begin at Mon Sep 8 09:32:44 2019\n INFO:microagent:Catch sender_name 1 a\n INFO:microagent:Finish at Mon Sep 8 09:32:47 2019 with {'CatcherAgent.catcher': 1}\n\n\nPeriodic tasks\n--------------\n\n.. code-block:: python\n\n import asyncio\n from microagent import MicroAgent, periodic, cron\n\n class MyAgent(MicroAgent):\n @periodic(period=1, timeout=1, start_after=5)\n async def hello(self):\n print('Hellow world!')\n\n @cron('*/2 * * * *', timeout=10)\n async def two_min(self):\n print('Run every 2 min')\n\n async def main():\n await MyAgent().start()\n\n.. code-block::\n\n $ python3 examples/periodic.py\n Hellow world!\n Hellow world!\n Run every 2 min\n Hellow world!\n\nHooks\n-----\n\n.. code-block:: python\n\n from microagent import MicroAgent, on\n\n class MyAgent(MicroAgent):\n @on('pre_start')\n async def call_first(self):\n print('Call before recivers and consumers will be enabled')\n\n @on('post_start')\n async def call_second(self):\n print('Call after recivers and consumers will be enabled')\n\n @on('pre_stop')\n async def call_last(self):\n print('Call when agent.stop() called')\n\n async def run():\n agent = MyAgent()\n await agent.start()\n print('Working...')\n await agent.stop()\n\n\n if __name__ == '__main__':\n loop = asyncio.get_event_loop()\n loop.run_until_complete(run())\n loop.close()\n\n\n.. code-block::\n\n $ python3 examples/hooks.py\n Call before recivers and consumers will be enabled\n Call after recivers and consumers will be enabled\n Workng...\n Call when agent.stop() called\n\n\n.. _aioredis: https://pypi.org/project/aioredis/\n.. _aioamqp: https://pypi.org/project/aioamqp/\n.. _kafka: https://pypi.org/project/aiokafka/\n.. _pulsar: https://pypi.org/project/pulsar/\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/scailer/microagent", "keywords": "async,pubsub,queue,agent,periodic,cron", "license": "MIT license", "maintainer": "", "maintainer_email": "", "name": "microagent", "package_url": "https://pypi.org/project/microagent/", "platform": "", "project_url": "https://pypi.org/project/microagent/", "project_urls": { "Homepage": "https://github.com/scailer/microagent" }, "release_url": "https://pypi.org/project/microagent/0.8/", "requires_dist": [ "ujson", "requests", "croniter", "aioredis ; extra == 'aioredis'", "aioamqp (==0.12.0) ; extra == 'amqp'", "aiokafka (==0.5) ; extra == 'kafka'", "asynctest ; extra == 'mock'", "pulsar ; extra == 'pulsar'" ], "requires_python": "", "summary": "Tool for agent ecosystem", "version": "0.8" }, "last_serial": 5802048, "releases": { "0.8": [ { "comment_text": "", "digests": { "md5": "b8ace98805d33baaada35c7fcf9f080b", "sha256": "bd9fb6fb955b35aeba3cbfb140c7706cbe6702396bfa949ce3de542304a9e2c0" }, "downloads": -1, "filename": "microagent-0.8-py3-none-any.whl", "has_sig": false, "md5_digest": "b8ace98805d33baaada35c7fcf9f080b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 20294, "upload_time": "2019-09-09T06:48:04", "url": "https://files.pythonhosted.org/packages/32/d5/d73b8a0df562c068ecc97a3e0ada949205922b922e39780eb5b81eb56929/microagent-0.8-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f447a76f323f2482414f8b07a8350823", "sha256": "3f4dd9a46c66784dc6170ffacc10d772569cfc1e0b4523e6f3b4c262fbd2ef7e" }, "downloads": -1, "filename": "microagent-0.8.tar.gz", "has_sig": false, "md5_digest": "f447a76f323f2482414f8b07a8350823", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16836, "upload_time": "2019-09-09T06:48:06", "url": "https://files.pythonhosted.org/packages/29/a0/c31d5337558c5d848a63ab7b5ecfb87ac3649292a6e439acfc9d363ba751/microagent-0.8.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b8ace98805d33baaada35c7fcf9f080b", "sha256": "bd9fb6fb955b35aeba3cbfb140c7706cbe6702396bfa949ce3de542304a9e2c0" }, "downloads": -1, "filename": "microagent-0.8-py3-none-any.whl", "has_sig": false, "md5_digest": "b8ace98805d33baaada35c7fcf9f080b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 20294, "upload_time": "2019-09-09T06:48:04", "url": "https://files.pythonhosted.org/packages/32/d5/d73b8a0df562c068ecc97a3e0ada949205922b922e39780eb5b81eb56929/microagent-0.8-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f447a76f323f2482414f8b07a8350823", "sha256": "3f4dd9a46c66784dc6170ffacc10d772569cfc1e0b4523e6f3b4c262fbd2ef7e" }, "downloads": -1, "filename": "microagent-0.8.tar.gz", "has_sig": false, "md5_digest": "f447a76f323f2482414f8b07a8350823", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16836, "upload_time": "2019-09-09T06:48:06", "url": "https://files.pythonhosted.org/packages/29/a0/c31d5337558c5d848a63ab7b5ecfb87ac3649292a6e439acfc9d363ba751/microagent-0.8.tar.gz" } ] }