{ "info": { "author": "Oliver Berger", "author_email": "diefans@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Framework :: AsyncIO", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Internet :: WWW/HTTP" ], "description": ".. container:: bagdes\n\n .. image:: https://travis-ci.org/diefans/implant.svg?branch=master\n :target: https://travis-ci.org/diefans/implant\n :align: right\n\n .. image:: https://img.shields.io/pypi/pyversions/implant.svg\n :target: https://pypi.org/project/implant/\n :alt: PyPI - Python Version\n\n .. image:: https://img.shields.io/pypi/v/implant.svg\n :target: https://pypi.org/project/implant/\n :alt: PyPI\n\n .. image:: https://img.shields.io/readthedocs/implant.svg\n :target: http://docs.implant.codes\n :alt: Read the Docs\n\n .. image:: https://codecov.io/gh/diefans/implant/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/diefans/implant\n\n----\n\n.. image:: implant.png\n :alt: implant\n :align: left\n\n\nimplant\n**********\n\nA proof-of-concept for asynchronous adhoc remote procedure calls in Python.\n\nThis is work in progress and serves basically as an exercise.\n\n\n.. inclusion-marker-do-not-remove\n\n\nFeatures\n========\n\n- Python >= 3.5 asyncio\n\n- adhoc transferable remote procedures\n\n- remote part of a `implant.core.Command` may reside in a separate module\n\n- a `implant.core.Command` specific `implant.core.Channel`\n enables arbitrary protocols between local and remote side\n\n- events\n\n- quite small core\n\n- tests\n\n\nLimitations\n===========\n\n- Python >= 3.5\n\n- only pure Python modules are supported for remote import, if no venv is used\n\n- `implant.core.Command` s must reside in a module other then `__main__`\n\n- at the moment sudo must not ask for password\n\n\n\nExample\n=======\n\n\nGeneral application\n-------------------\n\n.. code:: python\n\n import asyncio\n import pathlib\n\n from implant import core, connect, commands\n\n\n async def remote_tasks():\n # create a connector for a python process\n connector = connect.Lxd(\n container='zesty',\n hostname='localhost'\n )\n connector_args = {\n 'python_bin': pathlib.Path('/usr/bin/python3')\n }\n # connect to a remote python process\n remote = await connector.launch(**connector_args)\n\n # start remote communication tasks\n com_remote = asyncio.ensure_future(remote.communicate())\n try:\n # execute command\n cmd = commands.SystemLoad()\n result = await remote.execute(cmd)\n\n print(\"Remote system load:\", result)\n\n finally:\n # stop communication tasks\n com_remote.cancel()\n await com_remote\n\n\n if __name__ == '__main__':\n loop = asyncio.get_event_loop()\n loop.run_until_complete(remote_tasks())\n loop.close()\n\n\nAn example Echo Command\n-----------------------\n\n.. code:: python\n\n import logging\n import os\n\n from implant import core\n\n\n log = logging.getLogger(__name__)\n\n\n class Echo(core.Command):\n\n \"\"\"Demonstrate the basic command API.\"\"\"\n\n async def local(self, context):\n \"\"\"The local side of the RPC.\n\n :param context: :py:obj:`implant.core.DispatchLocalContext`\n \"\"\"\n # custom protocol\n # first: send\n await context.channel.send_iteration(\"send to remote\")\n\n # second: receive\n from_remote = []\n async for x in context.channel:\n from_remote.append(x)\n log.debug(\"************ receiving from remote: %s\", from_remote)\n\n # third: wait for remote to finish and return result\n remote_result = await context.remote_future\n\n result = {\n 'from_remote': ''.join(from_remote),\n }\n result.update(remote_result)\n return result\n\n async def remote(self, context):\n \"\"\"The remote side of the RPC.\n\n :param context: :py:obj:`implant.core.DispatchRemoteContext`\n \"\"\"\n # first: receive\n from_local = []\n async for x in context.channel:\n from_local.append(x)\n log.debug(\"************ receiving from local: %s\", from_local)\n\n # second: send\n await context.channel.send_iteration(\"send to local\")\n\n # third: return result\n return {\n 'from_local': ''.join(from_local),\n 'remote_self': self,\n 'pid': os.getpid()\n }\n\n\nInternals\n=========\n\n::\n\n master <-----------------------------------------> remote\n |\n stdin/stdout\n |\n chunks\n |\n channels\n |\n --> send ---> | | --> queue -->\n | module:class/fqin |\n <-- queue <-- | | <--- send <--\n\n\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/diefans/implant", "keywords": "asyncio ssh RPC Remote execution dependency injection stdin stdout messaging", "license": "Apache License Version 2.0", "maintainer": "", "maintainer_email": "", "name": "implant", "package_url": "https://pypi.org/project/implant/", "platform": "", "project_url": "https://pypi.org/project/implant/", "project_urls": { "Homepage": "https://github.com/diefans/implant" }, "release_url": "https://pypi.org/project/implant/0.1.2/", "requires_dist": [ "click", "ruamel.yaml (==0.15.37)", "async-generator; extra == 'dev'", "pytest; extra == 'dev'", "pytest-cache; extra == 'dev'", "pytest-asyncio; extra == 'dev'", "pytest-random; extra == 'dev'", "pytest-cov; extra == 'dev'", "pytest-benchmark; extra == 'dev'", "pytest-watch; extra == 'dev'", "pytest-testmon; extra == 'dev'", "pylama; extra == 'dev'", "pylama-pylint; extra == 'dev'", "pycodestyle; extra == 'dev'", "pydocstyle; extra == 'dev'", "radon; extra == 'dev'", "isort; extra == 'dev'", "ipython; extra == 'dev'", "pdbpp; extra == 'dev'", "colorlog; extra == 'dev'", "tox; extra == 'dev'", "sphinx; extra == 'docs'", "sphinxcontrib-asyncio; extra == 'docs'", "sphinxcontrib-fulltoc; extra == 'docs'", "humanfriendly; extra == 'docs'", "tokio (==0.99.0); extra == 'tokio'", "uvloop; extra == 'uvloop'" ], "requires_python": ">= 3.5.0.0, < 4.0.1.2", "summary": "Remote execution via stdin/stdout messaging.", "version": "0.1.2" }, "last_serial": 3920297, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "99edae1da01b97beacd7b963050ccb55", "sha256": "53c4035f53922fed07f009f82152491d94d4606b1dd111f0bc17e4e7a3bac710" }, "downloads": -1, "filename": "implant-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "99edae1da01b97beacd7b963050ccb55", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.5,<4.0", "size": 146589, "upload_time": "2018-05-30T20:08:17", "url": "https://files.pythonhosted.org/packages/c2/bc/5ffc4988c757f7ea60bb65aaafd41b811e280b4fce01a201da1d4a01ef16/implant-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "205aea9e6ee1b262727c68c79c50eb23", "sha256": "c8bc4d289e4f72d83b0ae15fafe44f3ecbb6e0d3b0b21e34ffdbdd07b8c36a7d" }, "downloads": -1, "filename": "implant-0.1.0.tar.gz", "has_sig": false, "md5_digest": "205aea9e6ee1b262727c68c79c50eb23", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5,<4.0", "size": 38228, "upload_time": "2018-05-30T20:08:20", "url": "https://files.pythonhosted.org/packages/33/3a/0954de8ded67c932757e841c8279c9e7fd49bc5ea84afa49453bd0e3e3af/implant-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "6d6969e7a5f00105fc6305b6e80f081c", "sha256": "fd1068c72073905437bbc47a8546573bac9689f5897d423fc252848d2485f376" }, "downloads": -1, "filename": "implant-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "6d6969e7a5f00105fc6305b6e80f081c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.5,<4.0", "size": 146584, "upload_time": "2018-05-30T20:13:59", "url": "https://files.pythonhosted.org/packages/ca/67/d37d83bd58b5436bc4a77131be1704d74759e5bf2bd7268b2691e7474007/implant-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b1cef84453ee13a3e152c70b73b40ec3", "sha256": "6994ec2c8d543e1888571104348b6dc2773b10d2246cc2df2b18683c33f7f254" }, "downloads": -1, "filename": "implant-0.1.1.tar.gz", "has_sig": false, "md5_digest": "b1cef84453ee13a3e152c70b73b40ec3", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.5,<4.0", "size": 38214, "upload_time": "2018-05-30T20:14:02", "url": "https://files.pythonhosted.org/packages/6e/2d/39acdb9463d50f4760222e5c66ffdbcbae0ecbba96d931b825565a51ccd3/implant-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "9ab1e625b2ec595ae81bda97ce6003e7", "sha256": "c08d251be9e63e0027bded83607244a6382f34e784ad4276f586e693ef85973c" }, "downloads": -1, "filename": "implant-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "9ab1e625b2ec595ae81bda97ce6003e7", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">= 3.5.0.0, < 4.0.1.2", "size": 40683, "upload_time": "2018-06-01T11:12:04", "url": "https://files.pythonhosted.org/packages/60/e1/72c18f680f6aef28ca4c52c43b20105de25d97375936c32e8f200a5b03d5/implant-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0eafbd15183cbbedf476280ebffbf7d0", "sha256": "ace257625b46a2644d74d97ddfc867561c54f3d041f606ec68ef711af4f69a73" }, "downloads": -1, "filename": "implant-0.1.2.tar.gz", "has_sig": false, "md5_digest": "0eafbd15183cbbedf476280ebffbf7d0", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.5.0.0, < 4.0.1.2", "size": 34348, "upload_time": "2018-06-01T11:12:06", "url": "https://files.pythonhosted.org/packages/9c/37/55a8048e40d4ba6497497f87af847910752a929120ce0c87732305b8a411/implant-0.1.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "9ab1e625b2ec595ae81bda97ce6003e7", "sha256": "c08d251be9e63e0027bded83607244a6382f34e784ad4276f586e693ef85973c" }, "downloads": -1, "filename": "implant-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "9ab1e625b2ec595ae81bda97ce6003e7", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">= 3.5.0.0, < 4.0.1.2", "size": 40683, "upload_time": "2018-06-01T11:12:04", "url": "https://files.pythonhosted.org/packages/60/e1/72c18f680f6aef28ca4c52c43b20105de25d97375936c32e8f200a5b03d5/implant-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0eafbd15183cbbedf476280ebffbf7d0", "sha256": "ace257625b46a2644d74d97ddfc867561c54f3d041f606ec68ef711af4f69a73" }, "downloads": -1, "filename": "implant-0.1.2.tar.gz", "has_sig": false, "md5_digest": "0eafbd15183cbbedf476280ebffbf7d0", "packagetype": "sdist", "python_version": "source", "requires_python": ">= 3.5.0.0, < 4.0.1.2", "size": 34348, "upload_time": "2018-06-01T11:12:06", "url": "https://files.pythonhosted.org/packages/9c/37/55a8048e40d4ba6497497f87af847910752a929120ce0c87732305b8a411/implant-0.1.2.tar.gz" } ] }