{ "info": { "author": "Sander Ferdinand", "author_email": "sa.ferdinand@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities" ], "description": "# Flask-YoloAPI\n\n![whoop](https://i.imgur.com/xVS3UGq.png)\n\nA simple library for simple JSON endpoints. YOLO!\n\nExample\n-------\n\n#### GET\n\n```python\nfrom flask_yoloapi import endpoint, parameter\n\n@app.route('/api/hello')\n@endpoint.api(\n parameter('name', type=str, required=True)\n)\ndef api_hello(name):\n return \"Hello %s!\" % name\n```\n\n`http://localhost:5000/api/hello?name=Sander`\n\n```javascript\n{\n data: \"Hello Sander!\"\n}\n```\n\n#### POST\n\n```python\nfrom flask_yoloapi import endpoint, parameter\n\n@app.route('/api/hello', methods=['POST'])\n@endpoint.api(\n parameter('name', type=str, required=True),\n parameter('age', type=int, default=18)\n)\ndef api_hello(name, age):\n return \"Hello %s, your age is %d\" % (name, age)\n```\n\n`curl -H \"Content-Type: application/json\" -vvXPOST -d '{\"name\":\"Sander\"}' http://localhost:5000/api/hello`\n\n```javascript\n{\n data: \"Hello Sander, your age is 18\"\n}\n```\n\n\nUse cases\n-------------\n\n- No boilerplate code that involves classes to make API routes.\n- You don't want to fish incoming parameters out of `request.args` / `request.form` / `request.json` :sleeping:\n- You don't need to hook your endpoints directly to SQLa models.\n- You don't care about providing REST compliancy - you just want somewhat consistent JSON endpoints, damnit!\n\n\nInstallation\n------------\n```sh\npip install flask-yoloapi\n```\n\n\n## Return values\nIn the example above, a string was returned. The following types are also supported:\n\n- `str`, `unicode`, `int`, `float`, `dict`, `list`, `datetime`, `bool`, `flask.Response`.\n\n```python\n@app.route('/wishlist')\n@endpoint.api(\n parameter('category', type=str, required=False)\n)\ndef wishlist(category):\n if category == \"cars\":\n return ['volvo xc60', 'mclaren mp4-12c']\n```\n\n```javascript\n{\n \"data\": [\n \"volvo xc60\", \n \"mclaren mp4-12c\"\n ]\n}\n``` \n\n## HTTP status codes\n\nTo return different status codes, return a 2-length `tuple` with the second index being the status code itself.\n\n```python\n@app.route('/create_foo')\n@endpoint.api()\ndef create_foo():\n return 'created', 201\n```\n\n## Route parameters\n\nYou can still use Flask's route parameters in conjunction with endpoint parameters.\n\n```python\n@app.route('/hello/')\n@endpoint.api(\n parameter('age', type=int, required=True)\n)\ndef hello(name, age):\n return {'name': name, 'age': age}\n```\n\n`/hello/sander?age=27`\n\n```javascript\n{\n \"data\": {\n \"age\": 27, \n \"name\": \"sander\"\n }\n}\n```\n\n## Default values\n\nYou can define default values for endpoint parameters via `default`.\n\n```python\n@app.route('/hello/')\n@endpoint.api(\n parameter('age', type=int, required=False, default=10)\n)\ndef hello(name, age):\n return {'name': name, 'age': age}\n```\n`/hello/sander`\n```javascript\n{\n \"data\": {\n \"age\": 10, \n \"name\": \"sander\"\n }\n}\n```\n\n## Type annotations\n\nParameter types are required, except when type annotations are in use.\n\nA Python 3.5 example:\n\n```python\n@app.route('/hello/', methods=['POST'])\n@endpoint.api(\n parameter('age', required=True),\n parameter('name', required=True)\n)\ndef hello(name: str, age: int):\n return {'name': name, 'age': age}\n```\n\nPython 2 equivalent:\n\n```python\n@app.route('/hello/', methods=['POST'])\n@endpoint.api(\n parameter('age', type=int, required=True),\n parameter('name', type=str, required=True)\n)\ndef hello(name, age):\n return {'name': name, 'age': age}\n```\n\nNote that type annotations are only supported from Python 3.5 and upwards (PEP 484).\n\n## Custom validators\n\nAdditional parameter validation can be done by providing a validator function. This function takes 1 parameter; the input. \n\n\n```python\ndef custom_validator(value):\n if value > 120:\n raise Exception(\"you can't possibly be that old!\")\n\n@app.route('/hello/')\n@endpoint.api(\n parameter('age', type=int, required=True, validator=custom_validator)\n)\ndef hello(name, age):\n return {'name': name, 'age': age}\n```\n\n`/hello/sander?age=130`\n\n```javascript\n{\n \"data\": \"parameter 'age' error: you can't possibly be that old!\"\n}\n```\n\nWhen the validation proves to be unsuccessful, you may do 2 things:\n\n- Raise an `Exception`, it will automatically construct a JSON response. This is shown above.\n- Return a `Flask.Response` object, where you may construct your own HTTP response\n\nIf you need more flexibility regarding incoming types use the `flask_yoloapi.types.ANY` type.\n\n## Parameter handling\n\nThis library is rather opportunistic about gathering incoming parameters, as it will check in the following 3 places:\n\n- `request.args`\n- `request.json`\n- `request.form`\n\nAn optional `location` argument can be provided to specify the source of the parameter.\n\n```python\n@app.route('/login')\n@endpoint.api(\n parameter('username', type=str, location='form', required=True),\n parameter('password', type=str, location='form', required=True),\n)\ndef login(username, password):\n return \"Wrong password!\", 403\n```\n\nThe following 3 locations are supported:\n\n- `args` - GET parameters\n- `form` - parameters submitted via HTTP form submission\n- `json` - parameters submitted via a JSON encoded HTTP request\n\n## Datetime format\n\nTo output datetime objects in `ISO 8601` format (which are trivial to parse in Javascript via `Date.parse()`), use a custom JSON encoder.\n\n```python\nfrom datetime import date\nfrom flask.json import JSONEncoder\n\nclass ApiJsonEncoder(JSONEncoder):\n def default(self, obj):\n if isinstance(obj, (date, datetime)):\n return obj.isoformat()\n return super(ApiJsonEncoder, self).default(obj)\n\napp = Flask(__name__)\napp.json_encoder = ApiJsonEncoder\n```\n\n\n## Error handling\n\nWhen the view function itself raises an exception, a JSON response is generated that includes:\n\n- The error message\n- Docstring of the view function\n- HTTP 500\n\nThis error response is also generated when endpoint requirements are not met.\n\n```javascript\n{\n data: \"argument 'password' is required\",\n docstring: {\n help: \"Logs the user in.\",\n return: \"The logged in message!\",\n params: {\n username: {\n help: \"The username of the user\",\n required: true,\n type: \"str\"\n }\n },\n ...\n```\n\nContributors\n-----\n\n- dromer\n- iksteen\n\nTests\n-----\n\n```\n$ pytest --cov=flask_yoloapi tests\n=========================================== test session starts ============================================\nplatform linux -- Python 3.5.3, pytest-3.1.3, py-1.5.2, pluggy-0.4.0\nrootdir: /home/dsc/flask-yoloapi, inifile:\nplugins: flask-0.10.0, cov-2.5.1\ncollected 19 items \n\ntests/test_app.py ...................\n\n----------- coverage: platform linux, python 3.5.3-final-0 -----------\nName Stmts Miss Cover\n-------------------------------------------------\nflask_yoloapi/__init__.py 2 0 100%\nflask_yoloapi/endpoint.py 111 4 96%\nflask_yoloapi/exceptions.py 3 1 67%\nflask_yoloapi/types.py 5 2 60%\nflask_yoloapi/utils.py 52 5 90%\n-------------------------------------------------\nTOTAL 173 12 93%\n\n```\n\nLicense\n-------------\nMIT.", "description_content_type": "text/markdown", "docs_url": null, "download_url": "https://github.com/skftn/flask-yoloapi/archive/master.zip", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/skftn/flask-yoloapi", "keywords": "flask api flapi yoloapi", "license": "", "maintainer": "", "maintainer_email": "", "name": "flask-yoloapi", "package_url": "https://pypi.org/project/flask-yoloapi/", "platform": "", "project_url": "https://pypi.org/project/flask-yoloapi/", "project_urls": { "Download": "https://github.com/skftn/flask-yoloapi/archive/master.zip", "Homepage": "https://github.com/skftn/flask-yoloapi" }, "release_url": "https://pypi.org/project/flask-yoloapi/0.1.6/", "requires_dist": null, "requires_python": "", "summary": "Simply the best Flask API library", "version": "0.1.6" }, "last_serial": 4394068, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "f894ce62e0747e48cc47babbf99cdadf", "sha256": "d49a298a55017628bb601f66eef2c73e8cf7a8c698661559f82102176cc273f4" }, "downloads": -1, "filename": "flask_yoloapi-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "f894ce62e0747e48cc47babbf99cdadf", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10097, "upload_time": "2017-09-23T19:41:43", "url": "https://files.pythonhosted.org/packages/28/d0/2986dcf0723422decd20d79e88380a82c2a2036383c27dc0de7f43ae4adf/flask_yoloapi-0.0.1-py3-none-any.whl" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "afdaeedb55210d511af814e4ef1d32c0", "sha256": "a90527c93ddb7b41a4159c498d682b3178b5a0edc47fbf75d3621c7023f3f73f" }, "downloads": -1, "filename": "flask_yoloapi-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "afdaeedb55210d511af814e4ef1d32c0", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13459, "upload_time": "2017-09-23T23:25:04", "url": "https://files.pythonhosted.org/packages/b5/35/654d5b2737e0f2d8393cf369e31a7fd2490659680de08f2dc178439fb592/flask_yoloapi-0.0.2-py3-none-any.whl" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "68865642e3cade33b41c043ebb1b7386", "sha256": "6b49515defaf25adae53136215374f7b326dfcdddd1bec92eacd4cf22716ff15" }, "downloads": -1, "filename": "Flask_YoloAPI-0.0.3-py2-none-any.whl", "has_sig": false, "md5_digest": "68865642e3cade33b41c043ebb1b7386", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 10097, "upload_time": "2017-09-24T19:42:30", "url": "https://files.pythonhosted.org/packages/d9/28/aef770f81992656129340e0571926cc727c2735ba520c629c8d23e24c882/Flask_YoloAPI-0.0.3-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "3ace3443d1d238ff486a695229ee50e5", "sha256": "2c680fe8baceb0f39e4b5c0cfecde05d7fc347dbe5db041695449a5e48383432" }, "downloads": -1, "filename": "Flask_YoloAPI-0.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "3ace3443d1d238ff486a695229ee50e5", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10098, "upload_time": "2017-09-24T19:43:49", "url": "https://files.pythonhosted.org/packages/99/55/43af6f92946496ff2d233989294ae9ac2750b9a8b4f82ea048d7d3bdd02e/Flask_YoloAPI-0.0.3-py3-none-any.whl" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "e44a0f38c2b227d8582610f2ee07a316", "sha256": "aecbffca5a4f2b57d4405ca5fd751f587cbe336f68cc9abb7cd2e57158cf774f" }, "downloads": -1, "filename": "Flask_YoloAPI-0.0.4-py2-none-any.whl", "has_sig": false, "md5_digest": "e44a0f38c2b227d8582610f2ee07a316", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 10120, "upload_time": "2017-09-25T13:31:24", "url": "https://files.pythonhosted.org/packages/65/60/7db77793296a93bf4f1ede16d467da9d5dd0794e5036ab4183016d985869/Flask_YoloAPI-0.0.4-py2-none-any.whl" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "7af7d71941fb7bfe49b4722e2172dc3a", "sha256": "68f474d6c573f8b9e1555c6574f6983e9b7ab4ab1c136ebeecb281a26eca388b" }, "downloads": -1, "filename": "Flask_YoloAPI-0.0.5-py3-none-any.whl", "has_sig": false, "md5_digest": "7af7d71941fb7bfe49b4722e2172dc3a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10118, "upload_time": "2017-09-27T07:04:01", "url": "https://files.pythonhosted.org/packages/2a/79/3cee2f8e9884c63072e61bc96b2a7887a4342facc5143d3abf8301de1b72/Flask_YoloAPI-0.0.5-py3-none-any.whl" } ], "0.0.6": [ { "comment_text": "", "digests": { "md5": "85d31501aedcd01c810ca414ba803905", "sha256": "4b62ec89c86356cb9a50410acd4a0a54ffd1cc412c865e9d6db5a44dfa4febda" }, "downloads": -1, "filename": "Flask_YoloAPI-0.0.6-py2-none-any.whl", "has_sig": false, "md5_digest": "85d31501aedcd01c810ca414ba803905", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 10693, "upload_time": "2017-09-28T11:35:22", "url": "https://files.pythonhosted.org/packages/3f/ce/993100583cf394fc8199ea35748e6629119ba5414bb8e3450df9626c8906/Flask_YoloAPI-0.0.6-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f362deb9ac2239696914f35e3c21802a", "sha256": "1ad87877a2e9a6d581edd996493ad68776a86370b3d923248c2a5a2564037c1f" }, "downloads": -1, "filename": "Flask_YoloAPI-0.0.6-py3-none-any.whl", "has_sig": false, "md5_digest": "f362deb9ac2239696914f35e3c21802a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10742, "upload_time": "2017-10-05T13:04:17", "url": "https://files.pythonhosted.org/packages/1c/bc/10cfb685c1a0f6319d6929aeb710eade1d23dac0fde3f0a0fee18aa48f77/Flask_YoloAPI-0.0.6-py3-none-any.whl" } ], "0.0.7": [ { "comment_text": "", "digests": { "md5": "aaf136866256f8077fdd2bfd7ecea1d6", "sha256": "bb70f222927308f930c3854ba5fbed62597a440d78634f407dd52c7bc121750d" }, "downloads": -1, "filename": "Flask_YoloAPI-0.0.7-py3-none-any.whl", "has_sig": false, "md5_digest": "aaf136866256f8077fdd2bfd7ecea1d6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 10852, "upload_time": "2017-12-11T12:27:22", "url": "https://files.pythonhosted.org/packages/54/a4/97b03b1a0fc17ddaff0db8247e9d7b11d54766df669ea5a6cda8e88d37e6/Flask_YoloAPI-0.0.7-py3-none-any.whl" } ], "0.0.8": [ { "comment_text": "", "digests": { "md5": "096c9ce7f82a5b2d0541f74f17558495", "sha256": "c6166f7c39cf12dc1d8f844a1b49cd9514fe8016161a1b15ad436d21613275d4" }, "downloads": -1, "filename": "Flask_YoloAPI-0.0.8-py3-none-any.whl", "has_sig": false, "md5_digest": "096c9ce7f82a5b2d0541f74f17558495", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11058, "upload_time": "2018-01-19T22:27:32", "url": "https://files.pythonhosted.org/packages/36/80/acf5ff706aeabb9d41b3c07c8b5e3f8bb6ec0fe44b8db66d2b944bf99593/Flask_YoloAPI-0.0.8-py3-none-any.whl" } ], "0.0.9": [ { "comment_text": "", "digests": { "md5": "0b42c3ccfeecc0202ebfbfc8ceab2c4f", "sha256": "2ac1dd7cc7b7b72192b32f0d34616ce5c2e6dafe66cdaea3c5f2e673abeb9122" }, "downloads": -1, "filename": "Flask_YoloAPI-0.0.9-py2-none-any.whl", "has_sig": false, "md5_digest": "0b42c3ccfeecc0202ebfbfc8ceab2c4f", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 11076, "upload_time": "2018-03-20T20:14:36", "url": "https://files.pythonhosted.org/packages/f2/48/51b86ea1aa5c632b8e3eac1f58bc00ecf3b1f258307acea02bd46d80b5d4/Flask_YoloAPI-0.0.9-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b9640969fa4e54e270ad3fc7d99a7cbd", "sha256": "eed9eb4e677729c7e6ceae7ff2e88d7c9cfb6f902fdad8b333a209e4624bf5fc" }, "downloads": -1, "filename": "Flask_YoloAPI-0.0.9-py3-none-any.whl", "has_sig": false, "md5_digest": "b9640969fa4e54e270ad3fc7d99a7cbd", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11074, "upload_time": "2018-03-20T20:14:38", "url": "https://files.pythonhosted.org/packages/13/7c/2f66e93f9fa959ffb015bc77774445bd86eb7bcb28a856d8d203688b54d8/Flask_YoloAPI-0.0.9-py3-none-any.whl" } ], "0.1.0": [ { "comment_text": "", "digests": { "md5": "c82063c0b7971fc08ecc59af82bff1ae", "sha256": "4c3672196588a520e79823e151da1958137707ce530d30e5b80adc9f8f55857d" }, "downloads": -1, "filename": "Flask_YoloAPI-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "c82063c0b7971fc08ecc59af82bff1ae", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15145, "upload_time": "2018-04-20T00:02:52", "url": "https://files.pythonhosted.org/packages/81/a2/292b1db20c1608249e8b9fa6db0020f8d0d445dd50753cb2058e23233806/Flask_YoloAPI-0.1.0-py3-none-any.whl" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "9f32610ea63c288a2c2e5a778fff42b4", "sha256": "26871f8f99771af25500082b47d581e5c9e4831302f4ff51b7091d0c2cd02d44" }, "downloads": -1, "filename": "Flask_YoloAPI-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "9f32610ea63c288a2c2e5a778fff42b4", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15149, "upload_time": "2018-04-20T00:06:31", "url": "https://files.pythonhosted.org/packages/d1/d6/d1a654344970392c56c2d7a396002929735dcde302db8796805b847457b9/Flask_YoloAPI-0.1.1-py3-none-any.whl" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "156f7375e4caea0bea3665a43b65d249", "sha256": "4916d66a6cc81e99d39f7ec1a339f22a53c500ce0169d41abf49d96c3579aec8" }, "downloads": -1, "filename": "Flask_YoloAPI-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "156f7375e4caea0bea3665a43b65d249", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15123, "upload_time": "2018-04-20T00:09:44", "url": "https://files.pythonhosted.org/packages/fa/b8/49cc02ee846878bad67abe9c9db38beef14b7e90934d7bb9daa5c0bddeac/Flask_YoloAPI-0.1.2-py3-none-any.whl" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "de815857de8c573fd31f584c46931529", "sha256": "0c4de0ec079baa1f123bd63bb307b2ed69ff60424bc92cf0aed514f3e84c6da6" }, "downloads": -1, "filename": "Flask-YoloAPI-0.1.3.tar.gz", "has_sig": false, "md5_digest": "de815857de8c573fd31f584c46931529", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11740, "upload_time": "2018-04-20T00:19:21", "url": "https://files.pythonhosted.org/packages/8b/4e/027674d19bcd1c7e04df4b96bc329cd70a37b3aca0833b6f3f164af5f0ef/Flask-YoloAPI-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "0238383441617396bf80c643183a5171", "sha256": "86a1b7210026c63a983d1b5e1dc21bd6410fae6bd1cfde6a80bfa525b4a364da" }, "downloads": -1, "filename": "Flask-YoloAPI-0.1.4.tar.gz", "has_sig": false, "md5_digest": "0238383441617396bf80c643183a5171", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11759, "upload_time": "2018-06-17T22:46:22", "url": "https://files.pythonhosted.org/packages/43/56/cc515b8edd3210ed90de9329ec92a10305264354ee7cf440691c0bf3be58/Flask-YoloAPI-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "58464c2787c41315a5387ffb9eed47ff", "sha256": "c2ea166cfef8c88473cfb85341f16faa280b1ae8c4f656ebbf491e777006e565" }, "downloads": -1, "filename": "Flask_YoloAPI-0.1.5-py3-none-any.whl", "has_sig": false, "md5_digest": "58464c2787c41315a5387ffb9eed47ff", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11626, "upload_time": "2018-06-17T22:53:45", "url": "https://files.pythonhosted.org/packages/51/f6/eab2c894cde03bcba9e402d9be0d45ae304f39dc98dc381f4728813f1b0b/Flask_YoloAPI-0.1.5-py3-none-any.whl" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "62555c99dc9a10f9b1f7f394897b9491", "sha256": "401572695aad204d8f997c30861145321b2879b027f02d7fe5beb133a1dff1dd" }, "downloads": -1, "filename": "Flask-YoloAPI-0.1.6.tar.gz", "has_sig": false, "md5_digest": "62555c99dc9a10f9b1f7f394897b9491", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10082, "upload_time": "2018-10-19T12:46:34", "url": "https://files.pythonhosted.org/packages/2a/67/ac605d5a45b03d5020e1535f44b238e3078500bd2544193d7ede1c6dc8af/Flask-YoloAPI-0.1.6.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "62555c99dc9a10f9b1f7f394897b9491", "sha256": "401572695aad204d8f997c30861145321b2879b027f02d7fe5beb133a1dff1dd" }, "downloads": -1, "filename": "Flask-YoloAPI-0.1.6.tar.gz", "has_sig": false, "md5_digest": "62555c99dc9a10f9b1f7f394897b9491", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10082, "upload_time": "2018-10-19T12:46:34", "url": "https://files.pythonhosted.org/packages/2a/67/ac605d5a45b03d5020e1535f44b238e3078500bd2544193d7ede1c6dc8af/Flask-YoloAPI-0.1.6.tar.gz" } ] }