{ "info": { "author": "Brian Muller", "author_email": "bamuller@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "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": "# RPCUDP : [RPC](http://en.wikipedia.org/wiki/Remote_procedure_call) over [UDP](http://en.wikipedia.org/wiki/User_Datagram_Protocol) in Python\n[![Build Status](https://secure.travis-ci.org/bmuller/rpcudp.png?branch=master)](https://travis-ci.org/bmuller/rpcudp)\n\nRPC over UDP may seem like a silly idea, but things like the [DHT](http://en.wikipedia.org/wiki/Distributed_hash_table) [Kademlia](http://en.wikipedia.org/wiki/Kademlia) require it. This project is specifically designed for [asynchronous Python 3](https://docs.python.org/3/library/asyncio.html) code to accept and send remote proceedure calls.\n\nBecause of the use of UDP, you will not always know whether or not a procedure call was successfully received. This isn't considered an exception state in the library, though you will know if a response isn't received by the server in a configurable amount of time.\n\n## Installation\n\n```\npip install rpcudp\n```\n\n## Usage\n*This assumes you have a working familiarity with [asyncio](https://docs.python.org/3/library/asyncio.html).*\n\nFirst, let's make a server that accepts a remote procedure call and spin it up.\n\n```python\nimport asyncio\nfrom rpcudp.protocol import RPCProtocol\n\n\nclass RPCServer(RPCProtocol):\n # Any methods starting with \"rpc_\" are available to clients.\n def rpc_sayhi(self, sender, name):\n # This could return a Deferred as well. sender is (ip,port)\n return \"Hello %s you live at %s:%i\" % (name, sender[0], sender[1])\n\n# start a server on UDP port 1234\nloop = asyncio.get_event_loop()\nlisten = loop.create_datagram_endpoint(RPCServer, local_addr=('127.0.0.1', 1234))\ntransport, protocol = loop.run_until_complete(listen)\nloop.run_forever()\n```\n\nNow, let's make a client script. Note that we do need to specify a port for the client as well, since it needs to listen for responses to RPC calls on a UDP port.\n\n```python\nimport asyncio\nfrom rpcudp.protocol import RPCProtocol\n\n\n@asyncio.coroutine\ndef sayhi(protocol, address):\n # result will be a tuple - first arg is a boolean indicating whether a response\n # was received, and the second argument is the response if one was received.\n result = yield from protocol.sayhi(address, \"Snake Plissken\")\n print(result[1] if result[0] else \"No response received.\")\n\n\n# Start local UDP server to be able to handle responses\nloop = asyncio.get_event_loop()\nlisten = loop.create_datagram_endpoint(RPCProtocol, local_addr=('127.0.0.1', 4567))\ntransport, protocol = loop.run_until_complete(listen)\n\n# Call remote UDP server to say hi\nfunc = sayhi(protocol, ('127.0.0.1', 1234))\nloop.run_until_complete(func)\nloop.run_forever()\n```\n\nYou can run this example in the examples folder (client.py and server.py).\n\n## Logging\nThis library uses the standard [Python logging library](https://docs.python.org/3/library/logging.html). To see debut output printed to STDOUT, for instance, use:\n\n```python\nimport logging\n\nlog = logging.getLogger('rpcudp')\nlog.setLevel(logging.DEBUG)\nlog.addHandler(logging.StreamHandler())\n```\n\n## Running Tests\nTo run tests:\n\n```\npip install -r dev-requirements.txt\npython -m unittest\n```\n\n## Implementation Details\nThe protocol is designed to be as small and fast as possible. Python objects are serialized using [MsgPack](http://msgpack.org/). All calls must fit within 8K (generally small enough to fit in one datagram packet).\n\n## Compatibility\nWith version 2.0 compatibility is broken with previous versions. In version 2.0 the method name when making a remote call is always packed as a unicode string. In previous versions, the type of string that method name was depended on the Python version. In order to make instances running on Python 2 (only versions before 3.0 worked with Python 2) and Python 3 compatible with each other the method name is now encoded as a unicode string before being packed, which ensures that [u-msgpack-python](https://github.com/vsergeev/u-msgpack-python) will always pack the it the same way. See [u-msgpack-python#behaviour-notes](https://github.com/vsergeev/u-msgpack-python#behavior-notes) for more information.\n\nIf you intend to have instances running on both Python 2 and Python 3 communicating with each other make sure that all strings in the arguments you send are unicode encoded as well to ensure compatibility.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/bmuller/rpcudp", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "rpcudp", "package_url": "https://pypi.org/project/rpcudp/", "platform": "", "project_url": "https://pypi.org/project/rpcudp/", "project_urls": { "Homepage": "http://github.com/bmuller/rpcudp" }, "release_url": "https://pypi.org/project/rpcudp/4.0.0/", "requires_dist": [ "u-msgpack-python (>=2.5)" ], "requires_python": "", "summary": "Asynchronous RPC via UDP", "version": "4.0.0" }, "last_serial": 5481853, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "c5077464f2b626d3016a7f89a1db85a4", "sha256": "e04ece081297c46c1035ff9e3038eedff9a0e9480867eb13de0469033219f27d" }, "downloads": -1, "filename": "rpcudp-0.1.tar.gz", "has_sig": false, "md5_digest": "c5077464f2b626d3016a7f89a1db85a4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2148, "upload_time": "2013-12-31T18:38:47", "url": "https://files.pythonhosted.org/packages/14/f8/3f68a55380e248b5e07c91f5592482f6189c22b9a84daf90002fa3121af1/rpcudp-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "641e98b48d523ee8326e85d7019693ca", "sha256": "4cdc1bd5c36cd49b9cba1a4e7ebb2a5759662ee6e8e8fbee13a6f10a627f8fd9" }, "downloads": -1, "filename": "rpcudp-0.2.tar.gz", "has_sig": false, "md5_digest": "641e98b48d523ee8326e85d7019693ca", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2179, "upload_time": "2013-12-31T18:52:33", "url": "https://files.pythonhosted.org/packages/dd/60/6afd13bdd00e831b518c8b5521016e2feedf9b5b761e9e3c8792f066a4fd/rpcudp-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "738235f60275e6d24e4e6465bb8fad13", "sha256": "ccba57cdecda494f4cdfefcc8e69b253856ae232f5dc6a6ad8ba99438bba6330" }, "downloads": -1, "filename": "rpcudp-0.3.tar.gz", "has_sig": false, "md5_digest": "738235f60275e6d24e4e6465bb8fad13", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2177, "upload_time": "2014-01-02T17:16:35", "url": "https://files.pythonhosted.org/packages/bd/84/4ec4edf67d88a6b59640ff18e44ce7e8c3dab604c540bca38955681a1a34/rpcudp-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "a8f8befe38f2e73f8fb7faa5da904d57", "sha256": "c18a67c6171575df17b54246b538d4285487eb01eb1fca4bd0ffcd8e7257d261" }, "downloads": -1, "filename": "rpcudp-0.4.tar.gz", "has_sig": false, "md5_digest": "a8f8befe38f2e73f8fb7faa5da904d57", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2277, "upload_time": "2014-01-03T21:54:53", "url": "https://files.pythonhosted.org/packages/37/55/b015a57bace141d1f1811b784d7b79317bd3dd7c835234643085eeb0a5ce/rpcudp-0.4.tar.gz" } ], "1.0": [ { "comment_text": "", "digests": { "md5": "9087b2cfafd34cf02d70b5795baee630", "sha256": "79df2a9a3593fc5bbfdffae735cf0882a96f9cd7d1c0e1068fad426025ed1d2b" }, "downloads": -1, "filename": "rpcudp-1.0.tar.gz", "has_sig": false, "md5_digest": "9087b2cfafd34cf02d70b5795baee630", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2238, "upload_time": "2014-01-04T15:27:05", "url": "https://files.pythonhosted.org/packages/67/19/d44b00edcdd60b0998bcf4a77e5f7471ce9dab2500086546ff39d04fd70d/rpcudp-1.0.tar.gz" } ], "2.0": [ { "comment_text": "", "digests": { "md5": "b62256329d076ec60a1476f212a458d5", "sha256": "9f83889d83639ab664cfac191af11c4ede8e5d7a762ff1d1b5861b06f5a7e4a7" }, "downloads": -1, "filename": "rpcudp-2.0.tar.gz", "has_sig": false, "md5_digest": "b62256329d076ec60a1476f212a458d5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2295, "upload_time": "2015-11-22T15:36:46", "url": "https://files.pythonhosted.org/packages/b2/e2/a4c90704d6b0dc2f69806c245ceeafff8759deaf18403a23794400d8d4a8/rpcudp-2.0.tar.gz" } ], "2.1": [ { "comment_text": "", "digests": { "md5": "f7cf4165c33bb14aed732b65e9b2f48f", "sha256": "0d108540c21c65c3267abdafac939e9837e97cb4300870a39d4b3809c76578dd" }, "downloads": -1, "filename": "rpcudp-2.1.tar.gz", "has_sig": false, "md5_digest": "f7cf4165c33bb14aed732b65e9b2f48f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2299, "upload_time": "2016-01-19T23:52:54", "url": "https://files.pythonhosted.org/packages/81/87/59a3b9b459f31feb4808421f137c5c31e35a483c7e94b4a4e053e18789ae/rpcudp-2.1.tar.gz" } ], "3.0.0": [ { "comment_text": "", "digests": { "md5": "0ca36c9d3091a3140f3b13b65f7fb72f", "sha256": "d4f83e27aa242eab142c4be377b5d4af15f2e68cd47be49e009093932313af81" }, "downloads": -1, "filename": "rpcudp-3.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "0ca36c9d3091a3140f3b13b65f7fb72f", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 4689, "upload_time": "2018-01-01T21:10:25", "url": "https://files.pythonhosted.org/packages/82/4d/59def0b6c083b944df3809005b7f06f2335155cebc116549600c67f422cd/rpcudp-3.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "605a1d2d50a747621c0a36538f45e273", "sha256": "e0100381cd2ee541abdb26001661c863094e25470234e994f080e347d6e68cb6" }, "downloads": -1, "filename": "rpcudp-3.0.0.tar.gz", "has_sig": false, "md5_digest": "605a1d2d50a747621c0a36538f45e273", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4628, "upload_time": "2018-01-01T21:09:58", "url": "https://files.pythonhosted.org/packages/6e/77/58095e02354aebcb88f30b5ce4e63345a8660ca263b5e28524051df03bbd/rpcudp-3.0.0.tar.gz" } ], "4.0.0": [ { "comment_text": "", "digests": { "md5": "16454bfaf8ed20d45b4e1873694bfc10", "sha256": "bffdd5c87b660821134c62169f405b6640275fa0e9d6f053f3ec640b364b7925" }, "downloads": -1, "filename": "rpcudp-4.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "16454bfaf8ed20d45b4e1873694bfc10", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 6822, "upload_time": "2019-07-03T13:53:58", "url": "https://files.pythonhosted.org/packages/41/b9/9e817b28f245a7ca76e46fcf3080bb1890f2e86db17daf32ae0d57946083/rpcudp-4.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "078b098f9a803bd9ebc9c893e500b077", "sha256": "2960cb91f5e4c9dec43b4a6a96857d5474edbfc00abd2b63a6d29fc9761c326c" }, "downloads": -1, "filename": "rpcudp-4.0.0.tar.gz", "has_sig": false, "md5_digest": "078b098f9a803bd9ebc9c893e500b077", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5323, "upload_time": "2019-07-03T13:54:00", "url": "https://files.pythonhosted.org/packages/cf/c9/77e1d5d353a0ee96f1375bf82dc5fbf6c26d64aa43e922196a3a2da7b4a0/rpcudp-4.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "16454bfaf8ed20d45b4e1873694bfc10", "sha256": "bffdd5c87b660821134c62169f405b6640275fa0e9d6f053f3ec640b364b7925" }, "downloads": -1, "filename": "rpcudp-4.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "16454bfaf8ed20d45b4e1873694bfc10", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 6822, "upload_time": "2019-07-03T13:53:58", "url": "https://files.pythonhosted.org/packages/41/b9/9e817b28f245a7ca76e46fcf3080bb1890f2e86db17daf32ae0d57946083/rpcudp-4.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "078b098f9a803bd9ebc9c893e500b077", "sha256": "2960cb91f5e4c9dec43b4a6a96857d5474edbfc00abd2b63a6d29fc9761c326c" }, "downloads": -1, "filename": "rpcudp-4.0.0.tar.gz", "has_sig": false, "md5_digest": "078b098f9a803bd9ebc9c893e500b077", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5323, "upload_time": "2019-07-03T13:54:00", "url": "https://files.pythonhosted.org/packages/cf/c9/77e1d5d353a0ee96f1375bf82dc5fbf6c26d64aa43e922196a3a2da7b4a0/rpcudp-4.0.0.tar.gz" } ] }