{ "info": { "author": "Tom Forbes", "author_email": "tom@tomforb.es", "bugtrack_url": null, "classifiers": [], "description": "# :hibiscus: Petal - Flask, for gRPC services.\n\nPetal reduces the boilerplate required to write and maintain gRPC based services whilst ensuring your service \ncode is always in sync with your definitions. It aims to be a somewhat opinionated gRPC framework. \n**This is very, very early code**.\n\n## Installation and features\n\n`pip install petal`\n\nRight now:\n\n- [x] Define your service methods as simple Python functions\n- [x] Ensure they are up to date with service definitions by utilizing type annotations\n- [x] Build your proto definitions and run your app with a `petal` command\n- [x] Share compiled protobuf definitions as Python packages.\n- [x] Streaming requests and responses\n\nFuture features:\n\n- [ ] Autoreloading during development\n- [ ] Structured logging\n- [ ] Some form of plugin architecture\n- [ ] Distributed tracing\n- [ ] A testing client\n- [ ] AsyncIO support\n\n## Hello world example:\n\n```python\nfrom petal import Service\nfrom example.protobuf.greeter_pb2 import HelloReply, HelloRequest\n\nservice = Service(__name__)\n\n@service.grpc()\ndef say_hello(request: HelloRequest) -> HelloReply:\n return HelloReply(message=f'Hello {request.name}')\n```\n\n## Tutorial: Creating a petal app\n\nLets create a Hello World Petal app. First lets define an entirely useless service. Place the file below \nin `hello_world/protobuf/service.proto`:\n\n```proto\nsyntax = \"proto3\";\npackage hello_world.protobuf.service;\n\nservice HelloWorld {\n rpc SayHello (HelloRequest) returns (HelloReply) {}\n}\n\nmessage HelloRequest {\n}\n\nmessage HelloReply {\n}\n```\n\nThen run `petal build hello_world`.\n\n\n Next, write our service definitions. Create a \n`hello_world/__init__.py` file and add some imports:\n\n```python\nfrom petal import Service\nfrom hello_world.protobuf.service_pb2 import HelloReply, HelloRequest\n\nservice = Service(__name__)\n```\n\nThis imports the request and response types our service will need. Next we need to fill in the \n`SayHello` method:\n\n```python\n@service.grpc()\ndef say_hello(request: HelloRequest) -> HelloReply:\n return HelloReply()\n```\n\nAnd finally, run the service by executing `petal run hello_world`. \n\nNow if we modify the service by adding a new method:\n\n```proto\nmessage HelloAgain {}\n\nservice HelloWorld {\n rpc SayHelloAgain (HelloRequest) returns (HelloAgain) {}\n}\n```\n\nAnd run `petal build hello_world && petal run hello_world`, we get an error:\n\n```shell\n$ petal run hello_world\nError: Cannot find a suitable method for GRPC method SayHelloAgain\nPlease ensure one exists in your service code, or use service.grpc(name=NAME) to define one.\n```\n\nPetal is ensuring we have the correct Python methods defined for all our service functions. We can fix this \nby defining one:\n\n```python\nfrom hello_world.protobuf.service_pb2 import HelloAgain\n\n@service.grpc()\ndef say_hello_again(request: HelloRequest) -> HelloAgain:\n return HelloAgain()\n```\n\nNow running `petal serve hello_world` will work.\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": "https://github.com/orf/petal", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "petal", "package_url": "https://pypi.org/project/petal/", "platform": "", "project_url": "https://pypi.org/project/petal/", "project_urls": { "Homepage": "https://github.com/orf/petal" }, "release_url": "https://pypi.org/project/petal/0.0.2.post2/", "requires_dist": [ "loguru", "requests", "grpcio", "grpcio-tools", "click", "mypy-protobuf" ], "requires_python": ">=3.6", "summary": "", "version": "0.0.2.post2" }, "last_serial": 5170805, "releases": { "0.0.0": [ { "comment_text": "", "digests": { "md5": "d802e2f93ef3626e4b9f66cf139ad346", "sha256": "6e7b6627f82760f3f7e5703a490423d5173e8151d2336cb785334aa7edc71983" }, "downloads": -1, "filename": "petal-0.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "d802e2f93ef3626e4b9f66cf139ad346", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 1142, "upload_time": "2019-04-07T00:47:09", "url": "https://files.pythonhosted.org/packages/0e/e7/0f481dbc583da74bc44d9a08df336ec118010f159ad33e3257d28e828371/petal-0.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "391bcdfcf5ae3897bc25536feb7199cd", "sha256": "0704e1ca0e1164439db5480c324db17426d6584b21aaae5dc1c8ccb4191036ce" }, "downloads": -1, "filename": "petal-0.0.0.tar.gz", "has_sig": false, "md5_digest": "391bcdfcf5ae3897bc25536feb7199cd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 642, "upload_time": "2019-04-07T00:47:11", "url": "https://files.pythonhosted.org/packages/b5/61/16ae6e3a0a3113a27ddcb11213d9c48605ab4cbb4db119b38cedbf3fc2a3/petal-0.0.0.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "1e012dac5dd4fa14df3e913f8ec9fcaa", "sha256": "749bad761e7798395bd393f47ca0d1bd4b3b1d1a6b26729c23909d9ea990246d" }, "downloads": -1, "filename": "petal-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "1e012dac5dd4fa14df3e913f8ec9fcaa", "packagetype": "bdist_wheel", "python_version": "3.7", "requires_python": null, "size": 7469, "upload_time": "2019-04-21T22:15:44", "url": "https://files.pythonhosted.org/packages/3a/83/3f08cf426464d8675713803e438cb18e40d188eebec8f42fe0c2058fb45b/petal-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "96fed5ee14e719f31f74d23606aa0e13", "sha256": "ba0470969c72216cdd2ab19c5888feb6b4e31bb10a5e9b616ca79230fc5f43b2" }, "downloads": -1, "filename": "petal-0.0.2.tar.gz", "has_sig": false, "md5_digest": "96fed5ee14e719f31f74d23606aa0e13", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6573, "upload_time": "2019-04-21T22:15:42", "url": "https://files.pythonhosted.org/packages/5a/ad/796c0107d0b5d045776325fb20513d22d2578a7195506e12df8ff4834900/petal-0.0.2.tar.gz" } ], "0.0.2.post1": [ { "comment_text": "", "digests": { "md5": "24f0abadb4a6fb0bf09cf09804a0c329", "sha256": "ab6654ae5076e2b8e5d4cbef6b5ffabb44e7e639b3283a2069530722b98f5d2d" }, "downloads": -1, "filename": "petal-0.0.2.post1-py3-none-any.whl", "has_sig": false, "md5_digest": "24f0abadb4a6fb0bf09cf09804a0c329", "packagetype": "bdist_wheel", "python_version": "3.7", "requires_python": null, "size": 8766, "upload_time": "2019-04-21T22:24:09", "url": "https://files.pythonhosted.org/packages/cd/b6/31014a067d458e00212bfddbd6d4b32c10e26b4fc924dd2e44021e610e47/petal-0.0.2.post1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8052e992590807e079f86d6252029ca8", "sha256": "7ce24c9c01f66f5fbb441816a4b647704038bd03b62d8a5359e4eab7a155e07f" }, "downloads": -1, "filename": "petal-0.0.2.post1.tar.gz", "has_sig": false, "md5_digest": "8052e992590807e079f86d6252029ca8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7136, "upload_time": "2019-04-21T22:24:07", "url": "https://files.pythonhosted.org/packages/d1/dc/3479dcb6b827d8818eff6fd86a3e96892d6fe07c0c5296db85867e94f332/petal-0.0.2.post1.tar.gz" } ], "0.0.2.post2": [ { "comment_text": "", "digests": { "md5": "a68b16ee63c4c293c9b7607bb43b2c73", "sha256": "5a25b2401d2f0f8ddab943938966f7cf8378fa3962b3ee2e9ea592c8a1f544f4" }, "downloads": -1, "filename": "petal-0.0.2.post2-py3-none-any.whl", "has_sig": false, "md5_digest": "a68b16ee63c4c293c9b7607bb43b2c73", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 8766, "upload_time": "2019-04-21T22:26:00", "url": "https://files.pythonhosted.org/packages/f1/bb/02a0a6ddcb895eb4b51b5e8d1f4d174d41fe8b652e7e3899d348ac4e0dfb/petal-0.0.2.post2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8362c248ca09a6bba0561e5676c29df1", "sha256": "94004689fb3d3e3cbbc3d0d4680459232446c47a028f123e4221a632eeb908f0" }, "downloads": -1, "filename": "petal-0.0.2.post2.tar.gz", "has_sig": false, "md5_digest": "8362c248ca09a6bba0561e5676c29df1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 7134, "upload_time": "2019-04-21T22:26:02", "url": "https://files.pythonhosted.org/packages/5d/64/95480d3dee916991d0344d0c82d061599cf1cf644eefcbb5126770d7f194/petal-0.0.2.post2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a68b16ee63c4c293c9b7607bb43b2c73", "sha256": "5a25b2401d2f0f8ddab943938966f7cf8378fa3962b3ee2e9ea592c8a1f544f4" }, "downloads": -1, "filename": "petal-0.0.2.post2-py3-none-any.whl", "has_sig": false, "md5_digest": "a68b16ee63c4c293c9b7607bb43b2c73", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 8766, "upload_time": "2019-04-21T22:26:00", "url": "https://files.pythonhosted.org/packages/f1/bb/02a0a6ddcb895eb4b51b5e8d1f4d174d41fe8b652e7e3899d348ac4e0dfb/petal-0.0.2.post2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8362c248ca09a6bba0561e5676c29df1", "sha256": "94004689fb3d3e3cbbc3d0d4680459232446c47a028f123e4221a632eeb908f0" }, "downloads": -1, "filename": "petal-0.0.2.post2.tar.gz", "has_sig": false, "md5_digest": "8362c248ca09a6bba0561e5676c29df1", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 7134, "upload_time": "2019-04-21T22:26:02", "url": "https://files.pythonhosted.org/packages/5d/64/95480d3dee916991d0344d0c82d061599cf1cf644eefcbb5126770d7f194/petal-0.0.2.post2.tar.gz" } ] }