{ "info": { "author": "Michael Nazario", "author_email": "mnazario@palantir.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application" ], "description": "..\n Copyright 2015 Palantir Technologies, Inc.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n============\ntypedjsonrpc\n============\n.. image:: https://img.shields.io/pypi/status/typedjsonrpc.svg\n :target: https://img.shields.io/pypi/status/typedjsonrpc\n\n.. image:: https://img.shields.io/pypi/l/typedjsonrpc.svg\n :target: https://img.shields.io/pypi/l/typedjsonrpc\n\n.. image:: https://img.shields.io/pypi/pyversions/typedjsonrpc.svg\n :target: https://img.shields.io/pypi/pyversions/typedjsonrpc\n\n.. image:: https://img.shields.io/pypi/wheel/typedjsonrpc.svg\n :target: https://img.shields.io/pypi/wheel/typedjsonrpc\n\n.. image:: https://badge.fury.io/py/typedjsonrpc.svg\n :target: http://badge.fury.io/py/typedjsonrpc\n\n.. image:: https://circleci.com/gh/palantir/typedjsonrpc.svg?style=shield\n :target: https://circleci.com/gh/palantir/typedjsonrpc\n\ntypedjsonrpc is a decorator-based `JSON-RPC `_ library for\nPython that exposes parameter and return types. It is influenced by\n`Flask JSON-RPC `_ but has some key differences:\n\ntypedjsonrpc...\n\n* allows return type checking\n* focuses on easy debugging\n\nThese docs are also available on `Read the Docs `_.\n\nUsing typedjsonrpc\n==================\nInstallation\n------------\nUse pip to install typedjsonrpc:\n\n.. code-block:: bash\n\n $ pip install typedjsonrpc\n\nProject setup\n-------------\nTo include typedjsonrpc in your project, use:\n\n.. code-block:: python\n\n from typedjsonrpc.registry import Registry\n from typedjsonrpc.server import Server\n\n registry = Registry()\n server = Server(registry)\n\nThe registry will keep track of methods that are available for JSON-RPC. Whenever you annotate\na method, it will be added to the registry. You can always use the method ``rpc.describe()`` to get\na description of all available methods. ``Server`` is a\n`WSGI `_ compatible app that handles requests. ``Server``\nalso has a development mode that can be run using ``server.run(host, port)``.\n\nExample usage\n-------------\nAnnotate your methods to make them accessible and provide type information:\n\n.. code-block:: python\n\n @registry.method(returns=int, a=int, b=int)\n def add(a, b):\n return a + b\n\n @registry.method(returns=str, a=str, b=str)\n def concat(a, b):\n return a + b\n\nThe return type *has* to be declared using the ``returns`` keyword. For methods that don't return\nanything, you can use either ``type(None)`` or just ``None``:\n\n.. code-block:: python\n\n @registry.method(returns=type(None), a=str)\n def foo(a):\n print(a)\n\n @registry.method(returns=None, a=int)\n def bar(a):\n print(5 * a)\n\nYou can use any of the basic JSON types:\n\n========== =====================================\nJSON type Python type\n========== =====================================\nstring basestring (Python 2), str (Python 3)\nnumber int, float\nnull None\nboolean bool\narray list\nobject dict\n========== =====================================\n\nYour functions may also accept ``*args`` and ``**kwargs``, but you cannot declare their types. So\nthe correct way to use these would be:\n\n.. code-block:: python\n\n @registry.method(a=str)\n def foo(a, *args, **kwargs):\n return a + str(args) + str(kwargs)\n\nTo check that everything is running properly, try (assuming ``add`` is declared in your main\nmodule):\n\n.. code-block:: bash\n\n $ curl -XPOST http://:/api -d @- <:/api -d @- <`_. In that case, if there is an\nerror during execution - e.g. you tried to use a string as one of the parameters for ``add`` - the\nresponse will contain an error object with a ``debug_url``:\n\n.. code-block:: bash\n\n $ curl -XPOST http://:/api -d @- <.\",\n \"debug_url\": \"/debug/1234567890\"\n }\n }\n }\n\nThis tells you to find the traceback interpreter at ``:/debug/1234567890``.\n\nLogging\n-------\n\nThe registry has a default logger in the module ``typedjsonrpc.registry`` and it logs all errors\nthat are not defined by ``typedjsonrpc``. You can configure the logger as follows:\n\n.. code-block:: python\n\n import logging\n logger = logging.getLogger(\"typedjsonrpc.registry\")\n # Do configuration to this logger\n\nHTTP status codes\n-----------------\nSince typedjsonrpc 0.4.0, HTTP status codes were added to the responses from the\n``typedjsonrpc.server.Server`` class. This is to improve the usage of typedjsonrpc over HTTP. The\nfollowing chart are the satus codes which are returned:\n\n+-----------------------------------+---------+-------------+\n|Condition | Batched | Status code |\n+===================================+=========+=============+\n| Success | Y | 200 |\n+ +---------+-------------+\n| | N | 200 |\n+-----------------------------------+---------+-------------+\n| All notifications | Y | 204 |\n+ +---------+-------------+\n| | N | 204 |\n+-----------------------------------+---------+-------------+\n| ParseError or InvalidRequestError | Y | 200 |\n+ +---------+-------------+\n| | N | 400 |\n+-----------------------------------+---------+-------------+\n| MethodNotFoundError | Y | 200 |\n+ +---------+-------------+\n| | N | 404 |\n+-----------------------------------+---------+-------------+\n| All other errors | Y | 200 |\n+ +---------+-------------+\n| | N | 500 |\n+-----------------------------------+---------+-------------+\n\nAdditional features\n===================\n\nCustomizing type serialization\n------------------------------\nIf you would like to serialize custom types, you can set the ``json_encoder`` and ``json_decoder``\nattributes on ``Server`` to your own custom ``json.JSONEncoder`` and ``json.JSONDecoder``\ninstance. By default, we use the default encoder and decoder.\n\nAdding hooks before the first request\n-------------------------------------\nYou can add functions to run before the first request is called. This can be useful for some\nspecial setup you need for your WSGI app. For example, you can register a function to print\ndebugging information before your first request:\n\n.. code-block:: python\n\n import datetime\n\n from typedjsonrpc.registry import Registry\n from typedjsonrpc.server import Server\n\n registry = Registry()\n server = Server(registry)\n\n def print_time():\n now = datetime.datetime.now()\n print(\"Handling first request at: {}\".format(now))\n\n server.register_before_first_request(print_time)\n\nAccessing the HTTP request from JSON-RPC methods\n------------------------------------------------\nIn some situations, you may want to access the HTTP request from your JSON-RPC method. For example,\nyou could need to perform logic based on headers in the request. In the `typedjsonrpc.server`\nmodule, there is a special `typedjsonrpc.server.current_request` attribute which allows you to\naccess the HTTP request which was used to call the current method.\n\n.. warning::\n\n ``current_request`` is implemented as a thread-local. If you attempt to call\n ``Server.wsgi_app`` from ``Registry.method``, then ``current_request`` *will be overriden in*\n *that thread*.\n\nExample:\n\n.. code-block:: python\n\n from typedjsonrpc.server import current_request\n\n @registry.method(returns=list)\n def get_headers():\n return list(current_request.headers)\n\nDisabling strictness of floats\n------------------------------\n``typedjsonrpc`` by default will only accept floats into a `float` typed parameter. For example, if\nyour function were this:\n\n.. code-block:: python\n\n import math\n\n @registry.method(returns=int, x=float)\n def floor(x):\n return int(math.floor(x))\n\nand your input were this::\n\n {\n \"jsonrpc\": \"2.0\",\n \"method\": \"floor\",\n \"params\": {\n \"x\": 1\n },\n \"id\": \"foo\"\n }\n\nYou would get an invalid param error like this::\n\n {\n \"error\": {\n \"code\": -32602,\n \"data\": {\n \"debug_url\": \"/debug/4456954960\",\n \"message\": \"Value '1' for parameter 'x' is not of expected type .\"\n },\n \"message\": \"Invalid params\"\n },\n \"id\": \"foo\",\n \"jsonrpc\": \"2.0\"\n }\n\nThis can actually frequently come up when you use a JSON encoder. A JSON encoder may choose to write\nthe float ``1.0`` as an integer ``1``. In order to get around this, you can manually edit the JSON\nor set ``strict_floats`` to ``False`` in your `typedjsonrpc.registry.Registry`.", "description_content_type": null, "docs_url": null, "download_url": null, "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/palantir/typedjsonrpc", "keywords": "jsonrpc json-rpc rpc", "license": "Apache License 2.0", "maintainer": null, "maintainer_email": null, "name": "typedjsonrpc", "package_url": "https://pypi.org/project/typedjsonrpc/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/typedjsonrpc/", "project_urls": { "Homepage": "https://github.com/palantir/typedjsonrpc" }, "release_url": "https://pypi.org/project/typedjsonrpc/0.4.0/", "requires_dist": null, "requires_python": null, "summary": "A typed decorator-based JSON-RPC library for Python", "version": "0.4.0" }, "last_serial": 1904615, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "5dfbfea01363986f99126ab897c7d55a", "sha256": "fdb2daffdc9c495aa7eef9e9e2113fb43d490b84d57493eee76e5791ce3d441d" }, "downloads": -1, "filename": "typedjsonrpc-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "5dfbfea01363986f99126ab897c7d55a", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 18663, "upload_time": "2015-08-14T02:43:29", "url": "https://files.pythonhosted.org/packages/68/af/c69831185fcdd2aa3c4a167bc3530614f864a59a304c178344c316b6219e/typedjsonrpc-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "83edc12aea44bdd4209dd147ec8fb9cc", "sha256": "c1311adca27c91a2b3355e6e186f14a8b1f2c002df0050cac475a6c2dd17a128" }, "downloads": -1, "filename": "typedjsonrpc-0.1.0.tar.gz", "has_sig": false, "md5_digest": "83edc12aea44bdd4209dd147ec8fb9cc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28384, "upload_time": "2015-08-14T02:43:32", "url": "https://files.pythonhosted.org/packages/e7/b7/96313adb72127ce8fa78cc2065d9f3b09bd79ffbaa8ff5046620d49342dd/typedjsonrpc-0.1.0.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "dd2f84ef2fd295824e75ca0ec107a0a9", "sha256": "75a714182b7b14b54cba63a6c5e5abfb9c7c15d3428304b160b1b85f20d658c8" }, "downloads": -1, "filename": "typedjsonrpc-0.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "dd2f84ef2fd295824e75ca0ec107a0a9", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 20122, "upload_time": "2015-08-21T04:08:15", "url": "https://files.pythonhosted.org/packages/8a/45/e0e73be99ecfdab5626606ce3e68e1220deef29c5187db880162738e0980/typedjsonrpc-0.2.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4779962b406ab70b89b13b36d57ecb69", "sha256": "418e9d6fd93cb6feef41da7e1e2a06ee458f690e9d3554e36adf31fbf7e53fd4" }, "downloads": -1, "filename": "typedjsonrpc-0.2.0.tar.gz", "has_sig": false, "md5_digest": "4779962b406ab70b89b13b36d57ecb69", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29934, "upload_time": "2015-08-21T04:08:19", "url": "https://files.pythonhosted.org/packages/89/a7/fd8da06f0687f7c8b216c9d82f38ccb7a8017843126da1e4286c4e172b05/typedjsonrpc-0.2.0.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "713624df662219062b87d7c8a6ee5c7d", "sha256": "3d9c274d4145ee4fea7c268a18a876967d77e9477917c4d0ff3e39fcb557bb99" }, "downloads": -1, "filename": "typedjsonrpc-0.3.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "713624df662219062b87d7c8a6ee5c7d", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 20314, "upload_time": "2015-09-09T02:33:00", "url": "https://files.pythonhosted.org/packages/bf/c4/858a7ebfdb5b2c21b41e32a318dfd742aa1490b1eaa0ededc40a2624b645/typedjsonrpc-0.3.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "af04e02b4d749ffc9b9999ea3d3979bf", "sha256": "66f5aba53a6f90348d4ed6b516bea1746b148845c4d031c8b5daabfb4f2811a6" }, "downloads": -1, "filename": "typedjsonrpc-0.3.0.tar.gz", "has_sig": false, "md5_digest": "af04e02b4d749ffc9b9999ea3d3979bf", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 51765, "upload_time": "2015-09-09T02:33:09", "url": "https://files.pythonhosted.org/packages/9c/48/358e9bddff7e953e91e5cc0037b93b33dc877a1b747b11fc88ebf71c9e26/typedjsonrpc-0.3.0.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "445723366dfe0f11d7a4112698f418ff", "sha256": "0bccb01c1f2d90c19caceebe5cc45e0d31d5ff1eeb308c03d5fa77ddf0765df3" }, "downloads": -1, "filename": "typedjsonrpc-0.4.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "445723366dfe0f11d7a4112698f418ff", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 22478, "upload_time": "2016-01-14T16:59:15", "url": "https://files.pythonhosted.org/packages/fe/52/1f32bf002e570261e83064605428cd2e67ec6e046f6f5b49a8dbfb0779e6/typedjsonrpc-0.4.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f7cee5b1c583b52175a8a0a48ac8d3e4", "sha256": "e2bc43e25bc6935681668f89f0223ab0f254a6dc4c532dd73ec9fce49dda85bf" }, "downloads": -1, "filename": "typedjsonrpc-0.4.0.tar.gz", "has_sig": false, "md5_digest": "f7cee5b1c583b52175a8a0a48ac8d3e4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32162, "upload_time": "2016-01-14T16:59:20", "url": "https://files.pythonhosted.org/packages/54/d6/c027e0326bd0728c9667940e8ce17b35c03cb0e27d1234e906e4ba45195c/typedjsonrpc-0.4.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "445723366dfe0f11d7a4112698f418ff", "sha256": "0bccb01c1f2d90c19caceebe5cc45e0d31d5ff1eeb308c03d5fa77ddf0765df3" }, "downloads": -1, "filename": "typedjsonrpc-0.4.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "445723366dfe0f11d7a4112698f418ff", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 22478, "upload_time": "2016-01-14T16:59:15", "url": "https://files.pythonhosted.org/packages/fe/52/1f32bf002e570261e83064605428cd2e67ec6e046f6f5b49a8dbfb0779e6/typedjsonrpc-0.4.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f7cee5b1c583b52175a8a0a48ac8d3e4", "sha256": "e2bc43e25bc6935681668f89f0223ab0f254a6dc4c532dd73ec9fce49dda85bf" }, "downloads": -1, "filename": "typedjsonrpc-0.4.0.tar.gz", "has_sig": false, "md5_digest": "f7cee5b1c583b52175a8a0a48ac8d3e4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32162, "upload_time": "2016-01-14T16:59:20", "url": "https://files.pythonhosted.org/packages/54/d6/c027e0326bd0728c9667940e8ce17b35c03cb0e27d1234e906e4ba45195c/typedjsonrpc-0.4.0.tar.gz" } ] }