diff --git a/.travis.yml b/.travis.yml index 5e6ad04..ff45981 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ install: - pip install pytest --upgrade script: - python setup.py install - - coverage run --source flask_rest_jsonapi -m pytest -v + - coverage run --source flask_combo_jsonapi -m pytest -v after_success: - coveralls diff --git a/README.rst b/README.rst index bf06e21..9d1cd0b 100644 --- a/README.rst +++ b/README.rst @@ -1,18 +1,24 @@ -.. image:: https://travis-ci.org/AdCombo/flask-rest-jsonapi.svg - :target: https://travis-ci.org/AdCombo/flask-rest-jsonapi -.. image:: https://coveralls.io/repos/github/AdCombo/flask-rest-jsonapi/badge.svg - :target: https://coveralls.io/github/AdCombo/flask-rest-jsonapi +.. image:: https://travis-ci.org/AdCombo/flask-combo-jsonapi.svg + :target: https://travis-ci.org/AdCombo/flask-combo-jsonapi +.. image:: https://coveralls.io/repos/github/AdCombo/flask-combo-jsonapi/badge.svg + :target: https://coveralls.io/github/AdCombo/flask-combo-jsonapi -Flask-REST-JSONAPI -################## +Flask-COMBO-JSONAPI +################### + +Flask-COMBO-JSONAPI is a flask extension for building REST APIs. It combines the power of `Flask-Restless `_ and the flexibility of `Flask-RESTful `_ around a strong specification `JSONAPI 1.0 `_. This framework is designed to quickly build REST APIs and fit the complexity of real life projects with legacy data and multiple data storages. + +The main goal is to make it flexible using `plugin system `_ -Flask-REST-JSONAPI is a flask extension for building REST APIs. It combines the power of `Flask-Restless `_ and the flexibility of `Flask-RESTful `_ around a strong specification `JSONAPI 1.0 `_. This framework is designed to quickly build REST APIs and fit the complexity of real life projects with legacy data and multiple data storages. Install ======= - pip install Flask-REST-JSONAPI + pip install Flask-COMBO-JSONAPI + +Installation from pypi is not ready yet. Refer to the `installation manual `_ + A minimal API ============= @@ -20,7 +26,7 @@ A minimal API .. code-block:: python from flask import Flask - from flask_rest_jsonapi import Api, ResourceDetail, ResourceList + from flask_combo_jsonapi import Api, ResourceDetail, ResourceList from flask_sqlalchemy import SQLAlchemy from marshmallow_jsonapi.flask import Schema from marshmallow_jsonapi import fields @@ -82,28 +88,28 @@ URL method endpoint Usage /persons/ DELETE person_detail Delete a person ======================== ====== ============= =========================== -Flask-REST-JSONAPI vs `Flask-RESTful `_ +Flask-COMBO-JSONAPI vs `Flask-RESTful `_ ========================================================================================== -* In contrast to Flask-RESTful, Flask-REST-JSONAPI provides a default implementation of get, post, patch and delete methods around a strong specification JSONAPI 1.0. Thanks to this you can build REST API very quickly. -* Flask-REST-JSONAPI is as flexible as Flask-RESTful. You can rewrite every default method implementation to make custom work like distributing object creation. +* In contrast to Flask-RESTful, Flask-COMBO-JSONAPI provides a default implementation of get, post, patch and delete methods around a strong specification JSONAPI 1.0. Thanks to this you can build REST API very quickly. +* Flask-COMBO-JSONAPI is as flexible as Flask-RESTful. You can rewrite every default method implementation to make custom work like distributing object creation. -Flask-REST-JSONAPI vs `Flask-Restless `_ +Flask-COMBO-JSONAPI vs `Flask-Restless `_ ========================================================================================== -* Flask-REST-JSONAPI is a real implementation of JSONAPI 1.0 specification. So in contrast to Flask-Restless, Flask-REST-JSONAPI forces you to create a real logical abstration over your data models with `Marshmallow `_. So you can create complex resource over your data. -* In contrast to Flask-Restless, Flask-REST-JSONAPI can use any ORM or data storage through the data layer concept, not only `SQLAlchemy `_. A data layer is a CRUD interface between your resource and one or more data storage so you can fetch data from any data storage of your choice or create resource that use multiple data storages. -* Like I said previously, Flask-REST-JSONAPI is a real implementation of JSONAPI 1.0 specification. So in contrast to Flask-Restless you can manage relationships via REST. You can create dedicated URL to create a CRUD API to manage relationships. -* Plus Flask-REST-JSONAPI helps you to design your application with strong separation between resource definition (schemas), resource management (resource class) and route definition to get a great organization of your source code. -* In contrast to Flask-Restless, Flask-REST-JSONAPI is highly customizable. For example you can entirely customize your URLs, define multiple URLs for the same resource manager, control serialization parameters of each method and lots of very useful parameters. -* Finally in contrast to Flask-Restless, Flask-REST-JSONAPI provides a great error handling system according to JSONAPI 1.0. Plus the exception handling system really helps the API developer to quickly find missing resources requirements. +* Flask-COMBO-JSONAPI is a real implementation of JSONAPI 1.0 specification. So in contrast to Flask-Restless, Flask-COMBO-JSONAPI forces you to create a real logical abstration over your data models with `Marshmallow `_. So you can create complex resource over your data. +* In contrast to Flask-Restless, Flask-COMBO-JSONAPI can use any ORM or data storage through the data layer concept, not only `SQLAlchemy `_. A data layer is a CRUD interface between your resource and one or more data storage so you can fetch data from any data storage of your choice or create resource that use multiple data storages. +* Like I said previously, Flask-COMBO-JSONAPI is a real implementation of JSONAPI 1.0 specification. So in contrast to Flask-Restless you can manage relationships via REST. You can create dedicated URL to create a CRUD API to manage relationships. +* Plus Flask-COMBO-JSONAPI helps you to design your application with strong separation between resource definition (schemas), resource management (resource class) and route definition to get a great organization of your source code. +* In contrast to Flask-Restless, Flask-COMBO-JSONAPI is highly customizable. For example you can entirely customize your URLs, define multiple URLs for the same resource manager, control serialization parameters of each method and lots of very useful parameters. +* Finally in contrast to Flask-Restless, Flask-COMBO-JSONAPI provides a great error handling system according to JSONAPI 1.0. Plus the exception handling system really helps the API developer to quickly find missing resources requirements. Documentation ============= -Documentation available here: http://flask-rest-jsonapi.readthedocs.io/en/latest/ +Documentation available here: http://Flask-COMBO-JSONAPI.readthedocs.io/en/latest/ Thanks ====== -Flask, marshmallow, marshmallow_jsonapi, sqlalchemy, Flask-RESTful and Flask-Restless are awesome projects. These libraries gave me inspiration to create Flask-REST-JSONAPI, so huge thanks to authors and contributors. +Flask, marshmallow, marshmallow_jsonapi, sqlalchemy, Flask-RESTful and Flask-Restless are awesome projects. These libraries gave me inspiration to create Flask-COMBO-JSONAPI, so huge thanks to authors and contributors. diff --git a/docs/api.rst b/docs/api.rst index 5df048b..855120e 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -3,7 +3,7 @@ Api === -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi You can provide global decorators as tuple to the Api. @@ -11,7 +11,7 @@ Example: .. code-block:: python - from flask_rest_jsonapi import Api + from flask_combo_jsonapi import Api from your_project.security import login_required api = Api(decorators=(login_required,)) diff --git a/docs/conf.py b/docs/conf.py index 00ea1b4..9cc02a8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# flask-rest-jsonapi documentation build configuration file, created by +# flask-combo-jsonapi documentation build configuration file, created by # sphinx-quickstart on Fri Oct 21 14:33:15 2016. # # This file is execfile()d with the current directory set to its @@ -18,7 +18,8 @@ # import os import sys -sys.path.insert(0, os.path.abspath('..')) + +sys.path.insert(0, os.path.abspath("..")) # -- General configuration ------------------------------------------------ @@ -30,38 +31,39 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. # # source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'flask-rest-jsonapi' -copyright = '2016, miLibris' -author = 'miLibris' +project = "flask-combo-jsonapi" +copyright = "2020, AdCombo" +author = "AdCombo" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '0.1' +version = "0.1" # The full version, including alpha/beta/rc tags. -release = '0.1' +release = "0.1" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -82,7 +84,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The reST default role (used for this markup: `text`) to use for all # documents. @@ -104,7 +106,7 @@ # show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] @@ -121,21 +123,21 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = "alabaster" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = { - 'github_user': 'miLibris', - 'github_repo': 'flask-rest-jsonapi', - 'github_banner': True, - 'travis_button': True, - 'show_related': True, - 'page_width': '1080px', - 'fixed_sidebar': True, - 'code_font_size': '0.8em' + "github_user": "AdCombo", + "github_repo": "flask-combo-jsonapi", + "github_banner": True, + "travis_button": True, + "show_related": True, + "page_width": "1080px", + "fixed_sidebar": True, + "code_font_size": "0.8em", } # Add any paths that contain custom themes here, relative to this directory. @@ -164,7 +166,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied @@ -244,34 +246,30 @@ # html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'flask-rest-jsonapidoc' +htmlhelp_basename = "flask-combo-jsonapidoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'flask-rest-jsonapi.tex', 'flask-rest-jsonapi Documentation', - 'miLibris', 'manual'), + (master_doc, "flask-combo-jsonapi.tex", "flask-combo-jsonapi Documentation", "AdCombo", "manual"), ] # The name of an image file (relative to this directory) to place at the top of @@ -311,10 +309,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'flask-rest-jsonapi', 'flask-rest-jsonapi Documentation', - [author], 1) -] +man_pages = [(master_doc, "flask-combo-jsonapi", "flask-combo-jsonapi Documentation", [author], 1)] # If true, show URL addresses after external links. # @@ -327,9 +322,15 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'flask-rest-jsonapi', 'flask-rest-jsonapi Documentation', - author, 'flask-rest-jsonapi', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "flask-combo-jsonapi", + "flask-combo-jsonapi Documentation", + author, + "flask-combo-jsonapi", + "One line description of project.", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. diff --git a/docs/configuration.rst b/docs/configuration.rst index 6c0d425..781e3c4 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -9,4 +9,4 @@ You have access to 5 configration keys: * MAX_PAGE_SIZE: the maximum page size. If you specify a page size greater than this value you will receive 400 Bad Request response. * MAX_INCLUDE_DEPTH: the maximum length of an include through schema relationships * ALLOW_DISABLE_PAGINATION: if you want to disallow to disable pagination you can set this configuration key to False -* CATCH_EXCEPTIONS: if you want flask_rest_jsonapi to catch all exceptions and return as JsonApiException (default is True) +* CATCH_EXCEPTIONS: if you want flask_combo_jsonapi to catch all exceptions and return as JsonApiException (default is True) diff --git a/docs/data_layer.rst b/docs/data_layer.rst index d01e951..90ca83b 100644 --- a/docs/data_layer.rst +++ b/docs/data_layer.rst @@ -3,11 +3,11 @@ Data layer ========== -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi | The data layer is a CRUD interface between resource manager and data. It is a very flexible system to use any ORM or data storage. You can even create a data layer that use multiple ORMs and data storage to manage your own objects. The data layer implements a CRUD interface for objects and relationships. It also manage pagination, filtering and sorting. | -| Flask-REST-JSONAPI has a full featured data layer that use the popular ORM `SQLAlchemy `_. +| Flask-COMBO-JSONAPI has a full featured data layer that use the popular ORM `SQLAlchemy `_. .. note:: @@ -19,7 +19,7 @@ Example: .. code-block:: python - from flask_rest_jsonapi import ResourceList + from flask_combo_jsonapi import ResourceList from your_project.schemas import PersonSchema from your_project.models import Person @@ -32,15 +32,15 @@ You can also plug additional methods to your data layer in the resource manager. * query: the "query" additional method takes view_kwargs as parameter and return an alternative query to retrieve the collection of objects in the GET method of the ResourceList manager. -* pre / post process methods: all CRUD and relationship(s) operations have a pre / post process methods. Thanks to it you can make additional work before and after each operations of the data layer. Parameters of each pre / post process methods are available in the `flask_rest_jsonapi.data_layers.base.Base `_ base class. +* pre / post process methods: all CRUD and relationship(s) operations have a pre / post process methods. Thanks to it you can make additional work before and after each operations of the data layer. Parameters of each pre / post process methods are available in the `flask_combo_jsonapi.data_layers.base.Base `_ base class. Example: .. code-block:: python from sqlalchemy.orm.exc import NoResultFound - from flask_rest_jsonapi import ResourceList - from flask_rest_jsonapi.exceptions import ObjectNotFound + from flask_combo_jsonapi import ResourceList + from flask_combo_jsonapi.exceptions import ObjectNotFound from your_project.models import Computer, Person class ComputerList(ResourceList): @@ -75,8 +75,8 @@ Example: .. code-block:: python from sqlalchemy.orm.exc import NoResultFound - from flask_rest_jsonapi import ResourceList - from flask_rest_jsonapi.exceptions import ObjectNotFound + from flask_combo_jsonapi import ResourceList + from flask_combo_jsonapi.exceptions import ObjectNotFound from your_project.models import Computer, Person from your_project.additional_methods.computer import before_create_object @@ -105,13 +105,13 @@ By default SQLAlchemy eagerload related data specified in include querystring pa Custom data layer ----------------- -Like I said previously you can create and use your own data layer. A custom data layer must inherit from `flask_rest_jsonapi.data_layers.base.Base `_. You can see the full scope of possibilities of a data layer in this base class. +Like I said previously you can create and use your own data layer. A custom data layer must inherit from `flask_combo_jsonapi.data_layers.base.Base `_. You can see the full scope of possibilities of a data layer in this base class. Usage example: .. code-block:: python - from flask_rest_jsonapi import ResourceList + from flask_combo_jsonapi import ResourceList from your_project.schemas import PersonSchema from your_project.data_layers import MyCustomDataLayer diff --git a/docs/errors.rst b/docs/errors.rst index 73740dc..16a1c86 100644 --- a/docs/errors.rst +++ b/docs/errors.rst @@ -3,7 +3,7 @@ Errors ====== -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi JSONAPI 1.0 specification recommand to return errors like that: @@ -53,20 +53,20 @@ The previous example displays error located in data provided instead of this nex } } -Flask-REST-JSONAPI provides two kind of helpers to achieve error displaying: +Flask-COMBO-JSONAPI provides two kind of helpers to achieve error displaying: -| * **the errors module**: you can import jsonapi_errors from the `errors module `_ to create the structure of a list of errors according to JSONAPI 1.0 specification +| * **the errors module**: you can import jsonapi_errors from the `errors module `_ to create the structure of a list of errors according to JSONAPI 1.0 specification | -| * **the exceptions module**: you can import lot of exceptions from this `module `_ that helps you to raise exceptions that will be well formatted according to JSONAPI 1.0 specification +| * **the exceptions module**: you can import lot of exceptions from this `module `_ that helps you to raise exceptions that will be well formatted according to JSONAPI 1.0 specification -When you create custom code for your api I recommand to use exceptions from exceptions module of Flask-REST-JSONAPI to raise errors because JsonApiException based exceptions are catched and rendered according to JSONAPI 1.0 specification. +When you create custom code for your api I recommand to use exceptions from exceptions module of Flask-COMBO-JSONAPI to raise errors because JsonApiException based exceptions are catched and rendered according to JSONAPI 1.0 specification. Example: .. code-block:: python # all required imports are not displayed in this example - from flask_rest_jsonapi.exceptions import ObjectNotFound + from flask_combo_jsonapi.exceptions import ObjectNotFound class ComputerList(ResourceList): def query(self, view_kwargs): diff --git a/docs/filtering.rst b/docs/filtering.rst index 12d74ea..a701985 100644 --- a/docs/filtering.rst +++ b/docs/filtering.rst @@ -3,9 +3,9 @@ Filtering ========= -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi -Flask-REST-JSONAPI as a very flexible filtering system. The filtering system is completely related to the data layer used by the ResourceList manager. I will explain the filtering interface for SQLAlchemy data layer but you can use the same interface to your filtering implementation of your custom data layer. The only requirement is that you have to use the "filter" querystring parameter to make filtering according to the JSONAPI 1.0 specification. +Flask-COMBO-JSONAPI as a very flexible filtering system. The filtering system is completely related to the data layer used by the ResourceList manager. I will explain the filtering interface for SQLAlchemy data layer but you can use the same interface to your filtering implementation of your custom data layer. The only requirement is that you have to use the "filter" querystring parameter to make filtering according to the JSONAPI 1.0 specification. .. note:: diff --git a/docs/flask-rest-jsonapi.rst b/docs/flask-rest-jsonapi.rst index 1cc3fdb..46f5960 100644 --- a/docs/flask-rest-jsonapi.rst +++ b/docs/flask-rest-jsonapi.rst @@ -1,98 +1,98 @@ -flask_rest_jsonapi package +flask_combo_jsonapi package ========================== -flask_rest_jsonapi.data_layers.filtering.alchemy module +flask_combo_jsonapi.data_layers.filtering.alchemy module ------------------------------------------------------- -.. automodule:: flask_rest_jsonapi.data_layers.filtering.alchemy +.. automodule:: flask_combo_jsonapi.data_layers.filtering.alchemy :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.data_layers.base module +flask_combo_jsonapi.data_layers.base module ------------------------------------------ -.. automodule:: flask_rest_jsonapi.data_layers.filtering.alchemy +.. automodule:: flask_combo_jsonapi.data_layers.filtering.alchemy :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.data_layers.alchemy module +flask_combo_jsonapi.data_layers.alchemy module --------------------------------------------- -.. automodule:: flask_rest_jsonapi.data_layers.alchemy +.. automodule:: flask_combo_jsonapi.data_layers.alchemy :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.api module +flask_combo_jsonapi.api module ----------------------------- -.. automodule:: flask_rest_jsonapi.api +.. automodule:: flask_combo_jsonapi.api :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.constants module +flask_combo_jsonapi.constants module ----------------------------------- -.. automodule:: flask_rest_jsonapi.constants +.. automodule:: flask_combo_jsonapi.constants :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.decorators module +flask_combo_jsonapi.decorators module ------------------------------------ -.. automodule:: flask_rest_jsonapi.decorators +.. automodule:: flask_combo_jsonapi.decorators :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.errors module +flask_combo_jsonapi.errors module -------------------------------- -.. automodule:: flask_rest_jsonapi.errors +.. automodule:: flask_combo_jsonapi.errors :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.exceptions module +flask_combo_jsonapi.exceptions module ------------------------------------ -.. automodule:: flask_rest_jsonapi.exceptions +.. automodule:: flask_combo_jsonapi.exceptions :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.pagination module +flask_combo_jsonapi.pagination module ------------------------------------ -.. automodule:: flask_rest_jsonapi.pagination +.. automodule:: flask_combo_jsonapi.pagination :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.querystring module +flask_combo_jsonapi.querystring module ------------------------------------- -.. automodule:: flask_rest_jsonapi.querystring +.. automodule:: flask_combo_jsonapi.querystring :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.resource module +flask_combo_jsonapi.resource module ---------------------------------- -.. automodule:: flask_rest_jsonapi.resource +.. automodule:: flask_combo_jsonapi.resource :members: :undoc-members: :show-inheritance: -flask_rest_jsonapi.schema module +flask_combo_jsonapi.schema module -------------------------------- -.. automodule:: flask_rest_jsonapi.schema +.. automodule:: flask_combo_jsonapi.schema :members: :undoc-members: :show-inheritance: diff --git a/docs/include_related_objects.rst b/docs/include_related_objects.rst index fe75d64..a025bc5 100644 --- a/docs/include_related_objects.rst +++ b/docs/include_related_objects.rst @@ -3,7 +3,7 @@ Include related objects ======================= -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi You can include related object(s) details to responses with the querystring parameter named "include". You can use "include" parameter on any kind of route (classical CRUD route or relationships route) and any kind of http methods as long as method return data. diff --git a/docs/index.rst b/docs/index.rst index 9dfee51..3507298 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,9 +1,9 @@ -Flask-REST-JSONAPI +Flask-COMBO-JSONAPI ================== -.. module:: flask_rest_jsonapi +.. module:: flask_combo_jsonapi -**Flask-REST-JSONAPI** is an extension for Flask that adds support for quickly building REST APIs with huge flexibility around the JSONAPI 1.0 specification. It is designed to fit the complexity of real life environments so Flask-REST-JSONAPI helps you to create a logical abstraction of your data called "resource" and can interface any kind of ORMs or data storage through data layer concept. +**Flask-COMBO-JSONAPI** is an extension for Flask that adds support for quickly building REST APIs with huge flexibility around the JSONAPI 1.0 specification. It is designed to fit the complexity of real life environments so Flask-COMBO-JSONAPI helps you to create a logical abstraction of your data called "resource" and can interface any kind of ORMs or data storage through data layer concept. Main concepts ------------- @@ -14,14 +14,14 @@ Main concepts | * `JSON API 1.0 specification `_: it is a very popular specification about client server interactions for REST JSON API. It helps you work in a team because it is very precise and sharable. Thanks to this specification your API offers lots of features like a strong structure of request and response, filtering, pagination, sparse fieldsets, including related objects, great error formatting etc. | -| * **Logical data abstraction**: you usually need to expose resources to clients that don't fit your data table architecture. For example sometimes you don't want to expose all attributes of a table, compute additional attributes or create a resource that uses data from multiple data storages. Flask-REST-JSONAPI helps you create a logical abstraction of your data with `Marshmallow `_ / `marshmallow-jsonapi `_ so you can expose your data through a very flexible way. +| * **Logical data abstraction**: you usually need to expose resources to clients that don't fit your data table architecture. For example sometimes you don't want to expose all attributes of a table, compute additional attributes or create a resource that uses data from multiple data storages. Flask-COMBO-JSONAPI helps you create a logical abstraction of your data with `Marshmallow `_ / `marshmallow-jsonapi `_ so you can expose your data through a very flexible way. | | * **Data layer**: the data layer is a CRUD interface between your resource manager and your data. Thanks to it you can use any data storage or ORMs. There is an already full featured data layer that uses the SQLAlchemy ORM but you can create and use your own custom data layer to use data from your data storage(s). You can even create a data layer that uses multiple data storages and ORMs, send notifications or make any custom work during CRUD operations. Features -------- -Flask-REST-JSONAPI has lots of features: +Flask-COMBO-JSONAPI has lots of features: * Relationship management * Powerful filtering @@ -37,7 +37,7 @@ User's Guide ------------ This part of the documentation will show you how to get started in using -Flask-REST-JSONAPI with Flask. +Flask-COMBO-JSONAPI with Flask. .. toctree:: :maxdepth: 3 diff --git a/docs/installation.rst b/docs/installation.rst index 9e590c0..de63abe 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -3,20 +3,23 @@ Installation ============ -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi -Install Flask-REST-JSONAPI with ``pip`` :: +Install Flask-COMBO-JSONAPI with ``pip`` :: - pip install flask-rest-jsonapi + pip install flask-combo-jsonapi The development version can be downloaded from `its page at GitHub -`_. :: +`_. :: - git clone https://github.com/miLibris/flask-rest-jsonapi.git - cd flask-rest-jsonapi - mkvirtualenv venv + git clone https://github.com/AdCombo/flask-combo-jsonapi.git + cd flask-combo-jsonapi + python3 -m venv venv + . ./venv/bin/activate + pip install -U pip python setup.py install + pip install -r requirements-dev.txt .. note:: diff --git a/docs/logical_data_abstraction.rst b/docs/logical_data_abstraction.rst index 100207b..0661fde 100644 --- a/docs/logical_data_abstraction.rst +++ b/docs/logical_data_abstraction.rst @@ -3,9 +3,9 @@ Logical data abstraction ======================== -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi -The first thing to do in Flask-REST-JSONAPI is to create a logical data abstraction. This part of the api discribes schemas of resources exposed by the api that is not the exact mapping of the data architecture. The declaration of schemas is made by `Marshmallow `_ / `marshmallow-jsonapi `_. Marshmallow is a very popular serialization / deserialization library that offers a lot of features to abstract your data architecture. Moreover there is an other library called marshmallow-jsonapi that fit the JSONAPI 1.0 specification and provides Flask integration. +The first thing to do in Flask-COMBO-JSONAPI is to create a logical data abstraction. This part of the api discribes schemas of resources exposed by the api that is not the exact mapping of the data architecture. The declaration of schemas is made by `Marshmallow `_ / `marshmallow-jsonapi `_. Marshmallow is a very popular serialization / deserialization library that offers a lot of features to abstract your data architecture. Moreover there is an other library called marshmallow-jsonapi that fit the JSONAPI 1.0 specification and provides Flask integration. Example: diff --git a/docs/modules.rst b/docs/modules.rst index 12cf1e0..b82d61e 100644 --- a/docs/modules.rst +++ b/docs/modules.rst @@ -1,7 +1,7 @@ -flask-rest-jsonapi +flask-combo-jsonapi ================== .. toctree:: :maxdepth: 4 - flask-rest-jsonapi + flask-combo-jsonapi diff --git a/docs/oauth.rst b/docs/oauth.rst index d996d6c..3bc6c1e 100644 --- a/docs/oauth.rst +++ b/docs/oauth.rst @@ -3,16 +3,16 @@ OAuth ===== -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi -Flask-REST-JSONAPI support OAuth via `Flask-OAuthlib `_ +Flask-COMBO-JSONAPI support OAuth via `Flask-OAuthlib `_ Example: .. code-block:: python from flask import Flask - from flask_rest_jsonapi import Api + from flask_combo_jsonapi import Api from flask_oauthlib.provider import OAuth2Provider app = Flask(__name__) @@ -23,7 +23,7 @@ Example: api.oauth_manager(oauth2) -In this example Flask-REST-JSONAPI will protect all your resource methods with this decorator :: +In this example Flask-COMBO-JSONAPI will protect all your resource methods with this decorator :: oauth2.require_oauth() @@ -61,7 +61,7 @@ Usage example: .. code-block:: python from flask import Flask - from flask_rest_jsonapi import Api + from flask_combo_jsonapi import Api from flask_oauthlib.provider import OAuth2Provider app = Flask(__name__) @@ -82,7 +82,7 @@ Example: .. code-block:: python - from flask_rest_jsonapi import ResourceList + from flask_combo_jsonapi import ResourceList from your_project.extensions import oauth2 class PersonList(ResourceList): diff --git a/docs/pagination.rst b/docs/pagination.rst index 552f6d4..792a589 100644 --- a/docs/pagination.rst +++ b/docs/pagination.rst @@ -3,7 +3,7 @@ Pagination ========== -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi When you use the default implementation of get method on a ResourceList your results will be paginated by default. Default pagination size is 30 but you can manage it from querystring parameter named "page". diff --git a/docs/permission.rst b/docs/permission.rst index 74655a6..4151a6b 100644 --- a/docs/permission.rst +++ b/docs/permission.rst @@ -3,16 +3,16 @@ Permission ========== -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi -Flask-REST-JSONAPI provides a very agnostic permission system. +Flask-COMBO-JSONAPI provides a very agnostic permission system. Example: .. code-block:: python from flask import Flask - from flask_rest_jsonapi import Api + from flask_combo_jsonapi import Api from your_project.permission import permission_manager app = Flask(__name__) @@ -39,7 +39,7 @@ The permission manager must be a function that looks like this: .. note:: - Flask-REST-JSONAPI use a decorator to check permission for each method named has_permission. You can provide args and kwargs to this decorators so you can retrieve this args and kwargs in the permission_manager. The default usage of the permission system does not provides any args or kwargs to the decorator. + Flask-COMBO-JSONAPI use a decorator to check permission for each method named has_permission. You can provide args and kwargs to this decorators so you can retrieve this args and kwargs in the permission_manager. The default usage of the permission system does not provides any args or kwargs to the decorator. If permission is denied I recommand to raise exception like that: @@ -54,7 +54,7 @@ You can disable the permission system or make custom permission checking managem .. code-block:: python - from flask_rest_jsonapi import ResourceList + from flask_combo_jsonapi import ResourceList from your_project.extensions import api class PersonList(ResourceList): @@ -73,7 +73,7 @@ Example: .. code-block:: python from flask import Flask - from flask_rest_jsonapi import Api + from flask_combo_jsonapi import Api from flask_oauthlib.provider import OAuth2Provider from your_project.permission import permission_manager diff --git a/docs/quickstart.rst b/docs/quickstart.rst index f313413..4436a82 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -3,24 +3,24 @@ Quickstart ========== -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi -It's time to write your first REST API. This guide assumes you have a working understanding of `Flask `_, and that you have already installed both Flask and Flask-REST-JSONAPI. If not, then follow the steps in the :ref:`installation` section. +It's time to write your first REST API. This guide assumes you have a working understanding of `Flask `_, and that you have already installed both Flask and Flask-COMBO-JSONAPI. If not, then follow the steps in the :ref:`installation` section. -In this section you will learn basic usage of Flask-REST-JSONAPI around a small tutorial that use the SQLAlchemy data layer. This tutorial show you an example of a person and his computers. +In this section you will learn basic usage of Flask-COMBO-JSONAPI around a small tutorial that use the SQLAlchemy data layer. This tutorial show you an example of a person and his computers. First example ------------- -An example of Flask-REST-JSONAPI API looks like this: +An example of Flask-COMBO-JSONAPI API looks like this: .. code-block:: python # -*- coding: utf-8 -*- from flask import Flask - from flask_rest_jsonapi import Api, ResourceDetail, ResourceList, ResourceRelationship - from flask_rest_jsonapi.exceptions import ObjectNotFound + from flask_combo_jsonapi import Api, ResourceDetail, ResourceList, ResourceRelationship + from flask_combo_jsonapi.exceptions import ObjectNotFound from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm.exc import NoResultFound from marshmallow_jsonapi.flask import Schema, Relationship diff --git a/docs/resource_manager.rst b/docs/resource_manager.rst index 3afe864..124634a 100644 --- a/docs/resource_manager.rst +++ b/docs/resource_manager.rst @@ -3,11 +3,11 @@ Resource Manager ================ -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi Resource manager is the link between your logical data abstraction, your data layer and optionally other software. It is the place where logic management of your resource is located. -Flask-REST-JSONAPI provides 3 kinds of resource manager with default methods implementation according to the JSONAPI 1.0 specification: +Flask-COMBO-JSONAPI provides 3 kinds of resource manager with default methods implementation according to the JSONAPI 1.0 specification: * **ResourceList**: provides get and post methods to retrieve a collection of objects or create one. * **ResourceDetail**: provides get, patch and delete methods to retrieve details of an object, update an object and delete an object @@ -27,7 +27,7 @@ Example: .. code-block:: python - from flask_rest_jsonapi import ResourceList + from flask_combo_jsonapi import ResourceList from your_project.schemas import PersonSchema from your_project.models import Person from your_project.extensions import db @@ -67,7 +67,7 @@ Example: .. code-block:: python - from flask_rest_jsonapi import ResourceDetail + from flask_combo_jsonapi import ResourceDetail from your_project.schemas import PersonSchema from your_project.models import Person from your_project.security import login_required @@ -100,7 +100,7 @@ Example: .. code-block:: python - from flask_rest_jsonapi import ResourceList + from flask_combo_jsonapi import ResourceList from your_project.schemas import PersonSchema from your_project.models import Person from your_project.extensions import db @@ -121,7 +121,7 @@ Example: .. code-block:: python - from flask_rest_jsonapi import ResourceDetail + from flask_combo_jsonapi import ResourceDetail from your_project.schemas import PersonSchema from your_project.models import Person from your_project.extensions import db @@ -142,7 +142,7 @@ Example: .. code-block:: python - from flask_rest_jsonapi import ResourceRelationship + from flask_combo_jsonapi import ResourceRelationship from your_project.schemas import PersonSchema from your_project.models import Person from your_project.extensions import db diff --git a/docs/routing.rst b/docs/routing.rst index 4fa1de5..c5566a4 100644 --- a/docs/routing.rst +++ b/docs/routing.rst @@ -3,7 +3,7 @@ Routing ======= -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi The routing system is very simple and fits this pattern :: @@ -14,7 +14,7 @@ Example: .. code-block:: python # all required imports are not displayed in this example - from flask_rest_jsonapi import Api + from flask_combo_jsonapi import Api api = Api() api.route(PersonList, 'person_list', '/persons') diff --git a/docs/sorting.rst b/docs/sorting.rst index 51e556d..6dba237 100644 --- a/docs/sorting.rst +++ b/docs/sorting.rst @@ -3,7 +3,7 @@ Sorting ======= -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi You can sort results with querystring parameter named "sort" diff --git a/docs/sparse_fieldsets.rst b/docs/sparse_fieldsets.rst index 5f8b849..5833814 100644 --- a/docs/sparse_fieldsets.rst +++ b/docs/sparse_fieldsets.rst @@ -3,7 +3,7 @@ Sparse fieldsets ================ -.. currentmodule:: flask_rest_jsonapi +.. currentmodule:: flask_combo_jsonapi You can restrict the fields returned by api with the querystring parameter called "fields". It is very useful for performance purpose because fields not returned are not resolved by api. You can use "fields" parameter on any kind of route (classical CRUD route or relationships route) and any kind of http methods as long as method return data. diff --git a/examples/api.py b/examples/api.py index a7ec11c..39761e8 100644 --- a/examples/api.py +++ b/examples/api.py @@ -1,6 +1,6 @@ from flask import Flask -from flask_rest_jsonapi import Api, ResourceDetail, ResourceList, ResourceRelationship -from flask_rest_jsonapi.exceptions import ObjectNotFound +from flask_combo_jsonapi import Api, ResourceDetail, ResourceList, ResourceRelationship +from flask_combo_jsonapi.exceptions import ObjectNotFound from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm.exc import NoResultFound from marshmallow_jsonapi.flask import Schema, Relationship diff --git a/examples/api_nested.py b/examples/api_nested.py index 30cbec0..cd806c9 100644 --- a/examples/api_nested.py +++ b/examples/api_nested.py @@ -1,6 +1,6 @@ from flask import Flask -from flask_rest_jsonapi import Api, ResourceDetail, ResourceList, ResourceRelationship -from flask_rest_jsonapi.exceptions import ObjectNotFound +from flask_combo_jsonapi import Api, ResourceDetail, ResourceList, ResourceRelationship +from flask_combo_jsonapi.exceptions import ObjectNotFound from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm.exc import NoResultFound from marshmallow_jsonapi.flask import Schema, Relationship diff --git a/flask_combo_jsonapi/__init__.py b/flask_combo_jsonapi/__init__.py new file mode 100644 index 0000000..85b11ee --- /dev/null +++ b/flask_combo_jsonapi/__init__.py @@ -0,0 +1,11 @@ +from flask_combo_jsonapi.api import Api +from flask_combo_jsonapi.resource import ResourceList, ResourceDetail, ResourceRelationship +from flask_combo_jsonapi.exceptions import JsonApiException + +__all__ = [ + 'Api', + 'ResourceList', + 'ResourceDetail', + 'ResourceRelationship', + 'JsonApiException' +] diff --git a/flask_rest_jsonapi/api.py b/flask_combo_jsonapi/api.py similarity index 96% rename from flask_rest_jsonapi/api.py rename to flask_combo_jsonapi/api.py index d0a78c9..54b0463 100644 --- a/flask_rest_jsonapi/api.py +++ b/flask_combo_jsonapi/api.py @@ -7,9 +7,9 @@ from flask import request, abort -from flask_rest_jsonapi.decorators import jsonapi_exception_formatter -from flask_rest_jsonapi.exceptions import PluginMethodNotImplementedError -from flask_rest_jsonapi.resource import ResourceList, ResourceRelationship +from flask_combo_jsonapi.decorators import jsonapi_exception_formatter +from flask_combo_jsonapi.exceptions import PluginMethodNotImplementedError +from flask_combo_jsonapi.resource import ResourceList, ResourceRelationship class Api(object): @@ -70,7 +70,7 @@ def init_app(self, app=None, blueprint=None, additional_blueprints=None): def route(self, resource, view, *urls, **kwargs): """Create an api view. - :param Resource resource: a resource class inherited from flask_rest_jsonapi.resource.Resource + :param Resource resource: a resource class inherited from flask_combo_jsonapi.resource.Resource :param str view: the view name :param str urls: the urls of the view :param kwargs: additional options of the route diff --git a/flask_rest_jsonapi/data_layers/__init__.py b/flask_combo_jsonapi/data_layers/__init__.py similarity index 100% rename from flask_rest_jsonapi/data_layers/__init__.py rename to flask_combo_jsonapi/data_layers/__init__.py diff --git a/flask_rest_jsonapi/data_layers/alchemy.py b/flask_combo_jsonapi/data_layers/alchemy.py similarity index 99% rename from flask_rest_jsonapi/data_layers/alchemy.py rename to flask_combo_jsonapi/data_layers/alchemy.py index ba9c4b3..880ef7e 100644 --- a/flask_rest_jsonapi/data_layers/alchemy.py +++ b/flask_combo_jsonapi/data_layers/alchemy.py @@ -9,9 +9,9 @@ from marshmallow.base import SchemaABC from flask import current_app -from flask_rest_jsonapi.data_layers.base import BaseDataLayer -from flask_rest_jsonapi.data_layers.sorting.alchemy import create_sorts -from flask_rest_jsonapi.exceptions import ( +from flask_combo_jsonapi.data_layers.base import BaseDataLayer +from flask_combo_jsonapi.data_layers.sorting.alchemy import create_sorts +from flask_combo_jsonapi.exceptions import ( RelationNotFound, RelatedObjectNotFound, JsonApiException, @@ -20,15 +20,15 @@ InvalidType, PluginMethodNotImplementedError, ) -from flask_rest_jsonapi.data_layers.filtering.alchemy import create_filters -from flask_rest_jsonapi.schema import ( +from flask_combo_jsonapi.data_layers.filtering.alchemy import create_filters +from flask_combo_jsonapi.schema import ( get_model_field, get_related_schema, get_relationships, get_nested_fields, get_schema_field, ) -from flask_rest_jsonapi.utils import SPLIT_REL +from flask_combo_jsonapi.utils import SPLIT_REL class SqlalchemyDataLayer(BaseDataLayer): diff --git a/flask_rest_jsonapi/data_layers/base.py b/flask_combo_jsonapi/data_layers/base.py similarity index 99% rename from flask_rest_jsonapi/data_layers/base.py rename to flask_combo_jsonapi/data_layers/base.py index 552fd11..ae9a543 100644 --- a/flask_rest_jsonapi/data_layers/base.py +++ b/flask_combo_jsonapi/data_layers/base.py @@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Optional if TYPE_CHECKING: - from flask_rest_jsonapi.resource import Resource + from flask_combo_jsonapi.resource import Resource class BaseDataLayer: diff --git a/flask_rest_jsonapi/data_layers/filtering/__init__.py b/flask_combo_jsonapi/data_layers/filtering/__init__.py similarity index 100% rename from flask_rest_jsonapi/data_layers/filtering/__init__.py rename to flask_combo_jsonapi/data_layers/filtering/__init__.py diff --git a/flask_rest_jsonapi/data_layers/filtering/alchemy.py b/flask_combo_jsonapi/data_layers/filtering/alchemy.py similarity index 96% rename from flask_rest_jsonapi/data_layers/filtering/alchemy.py rename to flask_combo_jsonapi/data_layers/filtering/alchemy.py index e51835d..875c8dd 100644 --- a/flask_rest_jsonapi/data_layers/filtering/alchemy.py +++ b/flask_combo_jsonapi/data_layers/filtering/alchemy.py @@ -4,10 +4,10 @@ from sqlalchemy import and_, or_, not_, sql from sqlalchemy.orm import aliased -from flask_rest_jsonapi.data_layers.shared import deserialize_field, create_filters_or_sorts -from flask_rest_jsonapi.exceptions import InvalidFilters, PluginMethodNotImplementedError -from flask_rest_jsonapi.schema import get_relationships, get_model_field -from flask_rest_jsonapi.utils import SPLIT_REL +from flask_combo_jsonapi.data_layers.shared import deserialize_field, create_filters_or_sorts +from flask_combo_jsonapi.exceptions import InvalidFilters, PluginMethodNotImplementedError +from flask_combo_jsonapi.schema import get_relationships, get_model_field +from flask_combo_jsonapi.utils import SPLIT_REL Filter = sql.elements.BinaryExpression diff --git a/flask_rest_jsonapi/data_layers/shared.py b/flask_combo_jsonapi/data_layers/shared.py similarity index 96% rename from flask_rest_jsonapi/data_layers/shared.py rename to flask_combo_jsonapi/data_layers/shared.py index 0a859ec..d9fe3d2 100644 --- a/flask_rest_jsonapi/data_layers/shared.py +++ b/flask_combo_jsonapi/data_layers/shared.py @@ -2,7 +2,7 @@ from marshmallow import fields, ValidationError -from flask_rest_jsonapi.exceptions import InvalidFilters +from flask_combo_jsonapi.exceptions import InvalidFilters # Fields that are not of array type diff --git a/flask_rest_jsonapi/data_layers/sorting/__init__.py b/flask_combo_jsonapi/data_layers/sorting/__init__.py similarity index 100% rename from flask_rest_jsonapi/data_layers/sorting/__init__.py rename to flask_combo_jsonapi/data_layers/sorting/__init__.py diff --git a/flask_rest_jsonapi/data_layers/sorting/alchemy.py b/flask_combo_jsonapi/data_layers/sorting/alchemy.py similarity index 94% rename from flask_rest_jsonapi/data_layers/sorting/alchemy.py rename to flask_combo_jsonapi/data_layers/sorting/alchemy.py index 5cbaf72..3c25056 100644 --- a/flask_rest_jsonapi/data_layers/sorting/alchemy.py +++ b/flask_combo_jsonapi/data_layers/sorting/alchemy.py @@ -4,10 +4,10 @@ from sqlalchemy import sql from sqlalchemy.orm import aliased -from flask_rest_jsonapi.data_layers.shared import create_filters_or_sorts -from flask_rest_jsonapi.exceptions import InvalidFilters, PluginMethodNotImplementedError, InvalidSort -from flask_rest_jsonapi.schema import get_relationships, get_model_field -from flask_rest_jsonapi.utils import SPLIT_REL +from flask_combo_jsonapi.data_layers.shared import create_filters_or_sorts +from flask_combo_jsonapi.exceptions import InvalidFilters, PluginMethodNotImplementedError, InvalidSort +from flask_combo_jsonapi.schema import get_relationships, get_model_field +from flask_combo_jsonapi.utils import SPLIT_REL Sort = sql.elements.BinaryExpression diff --git a/flask_rest_jsonapi/decorators.py b/flask_combo_jsonapi/decorators.py similarity index 96% rename from flask_rest_jsonapi/decorators.py rename to flask_combo_jsonapi/decorators.py index 22f910b..6e9b5fa 100644 --- a/flask_rest_jsonapi/decorators.py +++ b/flask_combo_jsonapi/decorators.py @@ -5,9 +5,9 @@ from flask import request, make_response, jsonify, current_app -from flask_rest_jsonapi.errors import jsonapi_errors, format_http_exception -from flask_rest_jsonapi.exceptions import JsonApiException -from flask_rest_jsonapi.utils import JSONEncoder +from flask_combo_jsonapi.errors import jsonapi_errors, format_http_exception +from flask_combo_jsonapi.exceptions import JsonApiException +from flask_combo_jsonapi.utils import JSONEncoder def check_headers(func): diff --git a/flask_rest_jsonapi/errors.py b/flask_combo_jsonapi/errors.py similarity index 89% rename from flask_rest_jsonapi/errors.py rename to flask_combo_jsonapi/errors.py index 40d1ffa..53f554b 100644 --- a/flask_rest_jsonapi/errors.py +++ b/flask_combo_jsonapi/errors.py @@ -1,5 +1,5 @@ """Helper to format Api errors according to jsonapi specification""" -from flask_rest_jsonapi.exceptions import BadRequest, ObjectNotFound, InvalidType, AccessDenied, Unauthorized +from flask_combo_jsonapi.exceptions import BadRequest, ObjectNotFound, InvalidType, AccessDenied, Unauthorized STATUS_MAP = { 400: BadRequest, diff --git a/flask_rest_jsonapi/exceptions.py b/flask_combo_jsonapi/exceptions.py similarity index 100% rename from flask_rest_jsonapi/exceptions.py rename to flask_combo_jsonapi/exceptions.py diff --git a/flask_rest_jsonapi/pagination.py b/flask_combo_jsonapi/pagination.py similarity index 100% rename from flask_rest_jsonapi/pagination.py rename to flask_combo_jsonapi/pagination.py diff --git a/flask_rest_jsonapi/plugin.py b/flask_combo_jsonapi/plugin.py similarity index 99% rename from flask_rest_jsonapi/plugin.py rename to flask_combo_jsonapi/plugin.py index c0b9e7e..afbbdf7 100644 --- a/flask_rest_jsonapi/plugin.py +++ b/flask_combo_jsonapi/plugin.py @@ -3,7 +3,7 @@ from sqlalchemy.orm import Query -from flask_rest_jsonapi.exceptions import PluginMethodNotImplementedError +from flask_combo_jsonapi.exceptions import PluginMethodNotImplementedError class BasePlugin(object): diff --git a/flask_rest_jsonapi/querystring.py b/flask_combo_jsonapi/querystring.py similarity index 96% rename from flask_rest_jsonapi/querystring.py rename to flask_combo_jsonapi/querystring.py index 47965a9..945cb2b 100644 --- a/flask_rest_jsonapi/querystring.py +++ b/flask_combo_jsonapi/querystring.py @@ -4,9 +4,9 @@ from flask import current_app -from flask_rest_jsonapi.exceptions import BadRequest, InvalidFilters, InvalidSort, InvalidField, InvalidInclude -from flask_rest_jsonapi.schema import get_model_field, get_relationships, get_schema_from_type -from flask_rest_jsonapi.utils import SPLIT_REL +from flask_combo_jsonapi.exceptions import BadRequest, InvalidFilters, InvalidSort, InvalidField, InvalidInclude +from flask_combo_jsonapi.schema import get_model_field, get_relationships, get_schema_from_type +from flask_combo_jsonapi.utils import SPLIT_REL class QueryStringManager(object): diff --git a/flask_rest_jsonapi/resource.py b/flask_combo_jsonapi/resource.py similarity index 96% rename from flask_rest_jsonapi/resource.py rename to flask_combo_jsonapi/resource.py index 4457e0a..c67e6e1 100644 --- a/flask_rest_jsonapi/resource.py +++ b/flask_combo_jsonapi/resource.py @@ -10,14 +10,14 @@ from marshmallow_jsonapi.exceptions import IncorrectTypeError from marshmallow import ValidationError -from flask_rest_jsonapi.querystring import QueryStringManager as QSManager -from flask_rest_jsonapi.pagination import add_pagination_links -from flask_rest_jsonapi.exceptions import InvalidType, BadRequest, RelationNotFound, PluginMethodNotImplementedError -from flask_rest_jsonapi.decorators import check_headers, check_method_requirements, jsonapi_exception_formatter -from flask_rest_jsonapi.schema import compute_schema, get_relationships, get_model_field -from flask_rest_jsonapi.data_layers.base import BaseDataLayer -from flask_rest_jsonapi.data_layers.alchemy import SqlalchemyDataLayer -from flask_rest_jsonapi.utils import JSONEncoder +from flask_combo_jsonapi.querystring import QueryStringManager as QSManager +from flask_combo_jsonapi.pagination import add_pagination_links +from flask_combo_jsonapi.exceptions import InvalidType, BadRequest, RelationNotFound, PluginMethodNotImplementedError +from flask_combo_jsonapi.decorators import check_headers, check_method_requirements, jsonapi_exception_formatter +from flask_combo_jsonapi.schema import compute_schema, get_relationships, get_model_field +from flask_combo_jsonapi.data_layers.base import BaseDataLayer +from flask_combo_jsonapi.data_layers.alchemy import SqlalchemyDataLayer +from flask_combo_jsonapi.utils import JSONEncoder class ResourceMeta(MethodViewType): diff --git a/flask_rest_jsonapi/schema.py b/flask_combo_jsonapi/schema.py similarity index 98% rename from flask_rest_jsonapi/schema.py rename to flask_combo_jsonapi/schema.py index 283d7b0..2f10d37 100644 --- a/flask_rest_jsonapi/schema.py +++ b/flask_combo_jsonapi/schema.py @@ -5,8 +5,8 @@ from marshmallow.base import SchemaABC from marshmallow_jsonapi.fields import Relationship, List, Nested -from flask_rest_jsonapi.exceptions import InvalidInclude -from flask_rest_jsonapi.utils import SPLIT_REL +from flask_combo_jsonapi.exceptions import InvalidInclude +from flask_combo_jsonapi.utils import SPLIT_REL def compute_schema(schema_cls, default_kwargs, qs, include): diff --git a/flask_rest_jsonapi/utils.py b/flask_combo_jsonapi/utils.py similarity index 100% rename from flask_rest_jsonapi/utils.py rename to flask_combo_jsonapi/utils.py diff --git a/flask_rest_jsonapi/__init__.py b/flask_rest_jsonapi/__init__.py deleted file mode 100644 index 981474c..0000000 --- a/flask_rest_jsonapi/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -from flask_rest_jsonapi.api import Api -from flask_rest_jsonapi.resource import ResourceList, ResourceDetail, ResourceRelationship -from flask_rest_jsonapi.exceptions import JsonApiException - -__all__ = [ - 'Api', - 'ResourceList', - 'ResourceDetail', - 'ResourceRelationship', - 'JsonApiException' -] diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..657011a --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,2 @@ +pytest +sphinx \ No newline at end of file diff --git a/setup.py b/setup.py index 3f8570e..558cbdf 100644 --- a/setup.py +++ b/setup.py @@ -1,37 +1,37 @@ +import os from setuptools import setup, find_packages +__version__ = "1.0.0" -__version__ = "0.30.1" +requirements_filepath = os.path.join(os.path.dirname(__name__), "requirements.txt") +with open(requirements_filepath) as fp: + install_requires = fp.read() setup( - name="Flask-REST-JSONAPI", + name="Flask-COMBO-JSONAPI", version=__version__, - description="Flask extension to create REST web api according to JSONAPI 1.0 specification with Flask, Marshmallow \ - and data provider of your choice (SQLAlchemy, MongoDB, ...)", - url="https://github.com/miLibris/flask-rest-jsonapi", - author="miLibris API Team", - author_email="pf@milibris.net", + description="Flask extension to create REST web api according to JSONAPI 1.0 specification" + " with Flask, Marshmallow and data provider of your choice (SQLAlchemy, MongoDB, ...)", + url="https://github.com/AdCombo/flask-combo-jsonapi/issues/10", + author="AdCombo Team", + author_email="roman@adcombo.com", license="MIT", classifiers=[ + "Development Status :: 5 - Production/Stable", "Framework :: Flask", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", - "License :: OSI Approved :: MIT License", + "Topic :: Internet", ], keywords="web api rest jsonapi flask sqlalchemy marshmallow", packages=find_packages(exclude=["tests"]), zip_safe=False, platforms="any", - install_requires=[ - "Flask>=1.0.1", - "marshmallow==3.2.1", - "marshmallow_jsonapi>=0.22.0", - "apispec>=2.0.2", - "sqlalchemy", - ], - # setup_requires=['pytest-runner'], + install_requires=install_requires, tests_require=["pytest"], extras_require={"tests": "pytest", "docs": "sphinx"}, ) diff --git a/tests/test_sqlalchemy_data_layer.py b/tests/test_sqlalchemy_data_layer.py index 6d10452..52d4a50 100644 --- a/tests/test_sqlalchemy_data_layer.py +++ b/tests/test_sqlalchemy_data_layer.py @@ -10,18 +10,18 @@ from marshmallow_jsonapi import fields from marshmallow import ValidationError -from flask_rest_jsonapi import Api, ResourceList, ResourceDetail, ResourceRelationship, JsonApiException -from flask_rest_jsonapi.pagination import add_pagination_links -from flask_rest_jsonapi.exceptions import RelationNotFound, InvalidSort, InvalidFilters, InvalidInclude, BadRequest -from flask_rest_jsonapi.querystring import QueryStringManager as QSManager -from flask_rest_jsonapi.data_layers.alchemy import SqlalchemyDataLayer -from flask_rest_jsonapi.data_layers.base import BaseDataLayer -from flask_rest_jsonapi.data_layers.filtering.alchemy import Node -from flask_rest_jsonapi.utils import SPLIT_REL +from flask_combo_jsonapi import Api, ResourceList, ResourceDetail, ResourceRelationship, JsonApiException +from flask_combo_jsonapi.pagination import add_pagination_links +from flask_combo_jsonapi.exceptions import RelationNotFound, InvalidSort, InvalidFilters, InvalidInclude, BadRequest +from flask_combo_jsonapi.querystring import QueryStringManager as QSManager +from flask_combo_jsonapi.data_layers.alchemy import SqlalchemyDataLayer +from flask_combo_jsonapi.data_layers.base import BaseDataLayer +from flask_combo_jsonapi.data_layers.filtering.alchemy import Node +from flask_combo_jsonapi.utils import SPLIT_REL -import flask_rest_jsonapi.decorators -import flask_rest_jsonapi.resource -import flask_rest_jsonapi.schema +import flask_combo_jsonapi.decorators +import flask_combo_jsonapi.resource +import flask_combo_jsonapi.schema @pytest.fixture(scope="module") @@ -599,9 +599,9 @@ def test_Node(person_model, person_schema, monkeypatch): def test_check_method_requirements(monkeypatch): self = type("self", (object,), dict()) request = type("request", (object,), dict(method="GET")) - monkeypatch.setattr(flask_rest_jsonapi.decorators, "request", request) + monkeypatch.setattr(flask_combo_jsonapi.decorators, "request", request) with pytest.raises(Exception): - flask_rest_jsonapi.decorators.check_method_requirements(lambda: 1)(self()) + flask_combo_jsonapi.decorators.check_method_requirements(lambda: 1)(self()) def test_json_api_exception(): @@ -636,11 +636,11 @@ def schema_load_mock(*args): rl.schema = person_schema rd._data_layer = dl rd.schema = person_schema - monkeypatch.setattr(flask_rest_jsonapi.resource, "request", request) - monkeypatch.setattr(flask_rest_jsonapi.decorators, "current_app", app) - monkeypatch.setattr(flask_rest_jsonapi.decorators, "request", request) + monkeypatch.setattr(flask_combo_jsonapi.resource, "request", request) + monkeypatch.setattr(flask_combo_jsonapi.decorators, "current_app", app) + monkeypatch.setattr(flask_combo_jsonapi.decorators, "request", request) monkeypatch.setattr(rl.schema, "load", schema_load_mock) - r = super(flask_rest_jsonapi.resource.Resource, ResourceList).__new__(ResourceList) + r = super(flask_combo_jsonapi.resource.Resource, ResourceList).__new__(ResourceList) with pytest.raises(Exception): r.dispatch_request() rl.post() @@ -651,16 +651,16 @@ def test_compute_schema(person_schema): query_string = {"page[number]": "3", "fields[person]": list()} qsm = QSManager(query_string, person_schema) with pytest.raises(InvalidInclude): - flask_rest_jsonapi.schema.compute_schema(person_schema, dict(), qsm, ["id"]) - flask_rest_jsonapi.schema.compute_schema(person_schema, dict(only=list()), qsm, list()) + flask_combo_jsonapi.schema.compute_schema(person_schema, dict(), qsm, ["id"]) + flask_combo_jsonapi.schema.compute_schema(person_schema, dict(only=list()), qsm, list()) def test_compute_schema_propagate_context(person_schema, computer_schema): query_string = {} qsm = QSManager(query_string, person_schema) - schema = flask_rest_jsonapi.schema.compute_schema(person_schema, dict(), qsm, ["computers"]) + schema = flask_combo_jsonapi.schema.compute_schema(person_schema, dict(), qsm, ["computers"]) assert schema.declared_fields["computers"].__dict__["_Relationship__schema"].__dict__["context"] == dict() - schema = flask_rest_jsonapi.schema.compute_schema(person_schema, dict(context=dict(foo="bar")), qsm, ["computers"]) + schema = flask_combo_jsonapi.schema.compute_schema(person_schema, dict(context=dict(foo="bar")), qsm, ["computers"]) assert schema.declared_fields["computers"].__dict__["_Relationship__schema"].__dict__["context"] == dict(foo="bar")