{ "info": { "author": "Filipe Waitman", "author_email": "filwaitman@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Framework :: Flask", "Framework :: Pyramid", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent" ], "description": "[![Build Status](https://travis-ci.org/filwaitman/whatever-rest-framework.svg?branch=master)](https://travis-ci.org/filwaitman/whatever-rest-framework)\n[![codecov](https://codecov.io/gh/filwaitman/whatever-rest-framework/branch/master/graph/badge.svg)](https://codecov.io/gh/filwaitman/whatever-rest-framework)\n\n# Whatever REST Framework\n\n## DISCLAIMER:\n\nThis is WIP. Next steps I can think:\n- Review the TODOs I have left in the project \n- Document input/output of every component's method\n- Create unit tests for base components\n\n\n## What?\n\nBasically this is an agnostic and thin layer to create RESTful APIs.\n\n\n## Why?\n\nHonestly because I every time I have to develop an API I tend to use Django just because of Django Rest Framework (and yes, this is my personal opinion). \nI would love to be able to create my RESTful APIs in whatever framework/technology I wanted to.\n\n\n## How?\n\n`pip install whatever-rest-framework`\n\nThere are a bunch of full working projects as examples. Please see the [tests folder](https://github.com/filwaitman/whatever-rest-framework/tree/master/tests). \n\nIn details, you'll need to: \n\n### 1) Create an `APIOrchestrator` by choosing a bunch of components\n\nThe types of base components you can choose for the API orchestrator are:\n\n| Type | Implementations | Must be set? | Default |\n|----------------------------|------------------------------------------------------------------------------------------------------------------------------------|--------------|-----------------------------|\n| framework_component_class | ChaliceFrameworkComponent, DjangoFrameworkComponent, FalconFrameworkComponent, FlaskFrameworkComponent, PyramidFrameworkComponent | Yes | None |\n| orm_component_class | DjangoORMComponent, PeeweeORMComponent, SQLAlchemyORMComponent | Yes | None |\n| schema_component_class | MarshmallowSchemaComponent, MarshmallowSQLAlchemySchemaComponent | Yes | None |\n| error_component_class | DefaultErrorComponent | No | DefaultErrorComponent |\n| pagination_component_class | NoPagePaginationComponent, PagePagePaginationComponent | No | NoPagePaginationComponent |\n| permission_component_class | AllowAllPermissionComponent, AllowAuthenticatedPermissionComponent, ReadOnlyPermissionComponent | No | AllowAllPermissionComponent |\n\n### 2) Define the `get_current_user(self)` method inside this orchestrator\n\nThe logic to discover the current user of a request is heavily dependant of the framework (and the tools you use), and I decided not to include it in the scope of this project.\nIdeally this can be simple as `def get_current_user(self): return g.user` or even `def get_current_user(self): return self.request.user if self.request.user.is_authenticated else None`.\n\n### 3) Create your APIs inheriting from the `APIOrchestrator`\n\nThese APIs need to set the attributes `model_class` and `schema_class`. Also you have to set the `get_queryset(self)`method.\nHere you have full, magic access to the basic API CRUD methods (list resources, retrieve resource, create resource, update resource, delete resource). \n\n**Special note: the `@api_view()` decorator:**\n\nYou can add other specific methods to your needs by adding methods to the API class too! Just decorate your custom methods with the `@api_view()` decorator and you're good to go!\nThis decorator can receive as arguments the components override to be used for that particular method. So you can have, for instance, your APIOrchestrator with permission=`AllowAllPermissionComponent` but this particular method with permission=`AllowAuthenticatedPermissionComponent` just by like below:\n\n```python\nclass APIOrchestrator(BaseAPI):\n permission_component_class = AllowAllPermissionComponent\n # ...\n\n @api_view(permission_component_class=AllowAuthenticatedPermissionComponent)\n def retrieve_more_private_stuff(self):\n return {'super-private': 'data'}\n```\n\n### Working example for a flask application:\n\n```python\nfrom functools import partial\n\nfrom wrf.api.base import BaseAPI, api_view\nfrom wrf.framework.flask import FlaskFrameworkComponent\nfrom wrf.orm.sqlalchemy import SQLAlchemyORMComponent\nfrom wrf.schema.marshmallow_sqlalchemy import MarshmallowSQLAlchemySchemaComponent\n\nfrom import app, db, User, UserSchema\n\nclass APIOrchestrator(BaseAPI):\n orm_component_class = partial(SQLAlchemyORMComponent, session=db.session)\n schema_component_class = MarshmallowSQLAlchemySchemaComponent\n framework_component_class = FlaskFrameworkComponent\n\n def get_current_user(self):\n # from flask_login import current_user; return current_user # if you're using flask-login, for example\n # return self.request.user if self.request.user.is_authenticated else None # if you're using django, for example\n return {'name': 'Filipe'}\n\nclass UserAPI(APIOrchestrator):\n model_class = User\n schema_class = UserSchema\n\n def get_queryset(self):\n return User.query\n \n @api_view()\n def retrieve_something_else(self, pk):\n user = User.query.filter_by(id=pk).one()\n return {'something_else': user.something_else}\n\n@app.route('/', methods=['GET'])\ndef list_():\n return UserAPI(request).list()\n\n@app.route('/', methods=['POST'])\ndef create():\n return UserAPI(request).create()\n\n@app.route('//', methods=['GET'])\ndef retrieve(pk):\n return UserAPI(request).retrieve(pk)\n\n@app.route('//', methods=['PATCH'])\ndef update(pk):\n return UserAPI(request).update(pk)\n\n@app.route('//', methods=['DELETE'])\ndef delete(pk):\n return UserAPI(request).delete(pk)\n\n@app.route('//something_else/', methods=['GET'])\ndef retrieve_something_else(pk):\n return UserAPI(request).retrieve_something_else(pk)\n```\n\n\n## Supported technologies\n\n### Framework:\n- Chalice\n- Django\n- Falcon\n- Flask\n- Pyramid\n\n\n### ORM:\n- Django\n- Peewee\n- SQLAlchemy\n\n\n### Schema:\n- Marshmallow\n- Marshmallow-SQLAlchemy\n\nBear in mind that this project is made to be easily extensible, so if you need to connect something else, it's simple to do it. [Check how simple it is to add support to a new framework](https://github.com/filwaitman/whatever-rest-framework/tree/master/wrf/framework/flask.py), for example. =D\n\n\n## Contributing\n\nPlease [open issues](https://github.com/filwaitman/whatever-rest-framework/issues) if you see one, or [create a pull request](https://github.com/filwaitman/whatever-rest-framework/pulls) when possible. \nIn case of a pull request, please consider the following:\n- Respect the line length (132 characters)\n- Keep the great test coverage of this project\n- Run `tox` locally so you can see if everything is green (including linter and other python versions)", "description_content_type": "text/markdown", "docs_url": null, "download_url": "https://github.com/filwaitman/whatever-rest-framework/tarball/0.5.0", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/filwaitman/whatever-rest-framework", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "whatever-rest-framework", "package_url": "https://pypi.org/project/whatever-rest-framework/", "platform": "", "project_url": "https://pypi.org/project/whatever-rest-framework/", "project_urls": { "Download": "https://github.com/filwaitman/whatever-rest-framework/tarball/0.5.0", "Homepage": "https://github.com/filwaitman/whatever-rest-framework" }, "release_url": "https://pypi.org/project/whatever-rest-framework/0.5.0/", "requires_dist": null, "requires_python": "", "summary": "RESTful API framework for your project, whatever tools you are using.", "version": "0.5.0" }, "last_serial": 5641173, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "6eed639898e4bedf01eb51df08624702", "sha256": "3826e86c646b8e85002fd92415f83dcdf6721848e45498fb56619e226cd0c7f6" }, "downloads": -1, "filename": "whatever-rest-framework-0.1.0.tar.gz", "has_sig": false, "md5_digest": "6eed639898e4bedf01eb51df08624702", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9459, "upload_time": "2019-07-05T19:08:46", "url": "https://files.pythonhosted.org/packages/0b/f1/cb8f44f6a24e666d4554e2a73da78e040ec3723906bac3f5b9229aa438b7/whatever-rest-framework-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "7a1f9ca81b39bec837e34ec6c9dea26f", "sha256": "20d720ead520767ca5985e90482c23f6b93f7856b8c6159923cdf49132bc2357" }, "downloads": -1, "filename": "whatever-rest-framework-0.1.1.tar.gz", "has_sig": false, "md5_digest": "7a1f9ca81b39bec837e34ec6c9dea26f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9580, "upload_time": "2019-07-05T20:44:42", "url": "https://files.pythonhosted.org/packages/ef/1d/1903be63101a60e5036eb21164df098b08b2c96a7922f172b80b34e6c6bd/whatever-rest-framework-0.1.1.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "9aad9dff0aef9227abaa85abfcd64f1c", "sha256": "4eb33eec1c4290d950211064cf21f36c41c08f3416ac063da570b8e5394cf40d" }, "downloads": -1, "filename": "whatever-rest-framework-0.2.0.tar.gz", "has_sig": false, "md5_digest": "9aad9dff0aef9227abaa85abfcd64f1c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10202, "upload_time": "2019-07-11T18:50:09", "url": "https://files.pythonhosted.org/packages/83/1e/752e03328d6a3c2694571d392058c3a31d92e58b9436e1ccf0d1fc91bf2b/whatever-rest-framework-0.2.0.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "270d32d738cd15842e86425bf1158b34", "sha256": "533ae23d1f2967bfa4d01b53eb59ed6cc709aa8d0b7606cf7aa089a23aa3b33e" }, "downloads": -1, "filename": "whatever-rest-framework-0.3.0.tar.gz", "has_sig": false, "md5_digest": "270d32d738cd15842e86425bf1158b34", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10228, "upload_time": "2019-07-23T19:31:22", "url": "https://files.pythonhosted.org/packages/89/5e/ef2266ea80b4068023590fc60285ca5328ddab02ad8763238aa53db7c313/whatever-rest-framework-0.3.0.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "cfa17c80cf4a9f03a0de591f6b6d7df8", "sha256": "d3890a75dcbe76ef1dba2147394e2a4c4647de08310c588287ed19d45317e852" }, "downloads": -1, "filename": "whatever-rest-framework-0.4.0.tar.gz", "has_sig": false, "md5_digest": "cfa17c80cf4a9f03a0de591f6b6d7df8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10375, "upload_time": "2019-07-24T14:32:51", "url": "https://files.pythonhosted.org/packages/34/23/c72e87739cce04674fde69e0687b9bbd47273ea733232904df1f54139911/whatever-rest-framework-0.4.0.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "8a5f001218f78b46568f82e05eea2526", "sha256": "c34aa1a5e3f5f7b2f3119d5e8549d39f95221d1e5fd1117c8094454f2dafa45a" }, "downloads": -1, "filename": "whatever-rest-framework-0.5.0.tar.gz", "has_sig": false, "md5_digest": "8a5f001218f78b46568f82e05eea2526", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12891, "upload_time": "2019-08-06T18:54:34", "url": "https://files.pythonhosted.org/packages/d6/e1/3573298a33b99881dc9293d0f71bd008dcc3ce6dd260c91504916f232f19/whatever-rest-framework-0.5.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "8a5f001218f78b46568f82e05eea2526", "sha256": "c34aa1a5e3f5f7b2f3119d5e8549d39f95221d1e5fd1117c8094454f2dafa45a" }, "downloads": -1, "filename": "whatever-rest-framework-0.5.0.tar.gz", "has_sig": false, "md5_digest": "8a5f001218f78b46568f82e05eea2526", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12891, "upload_time": "2019-08-06T18:54:34", "url": "https://files.pythonhosted.org/packages/d6/e1/3573298a33b99881dc9293d0f71bd008dcc3ce6dd260c91504916f232f19/whatever-rest-framework-0.5.0.tar.gz" } ] }