Example #1
0
def routes(app, models, schemas):
    class ParentView(GenericModelView):
        model = models["parent"]
        schema = schemas["parent"]

        related = Related(children=RelatedId(lambda: ChildView(), "child_ids"))

        def get(self, id):
            return self.retrieve(id)

        def put(self, id):
            return self.update(id)

    class NestedParentView(ParentView):
        related = Related(children=lambda: ChildView())

        def put(self, id):
            return self.update(id)

    class ParentWithCreateView(ParentView):
        related = Related(children=Related(models["child"]))

        def put(self, id):
            return self.update(id)

    class ChildView(GenericModelView):
        model = models["child"]
        schema = schemas["child"]

        base_query_options = (raiseload("*"), )

        related = Related(parent=RelatedId(ParentView, "parent_id"))

        def get(self, id):
            return self.retrieve(id)

        def put(self, id):
            return self.update(id)

    class NestedChildView(GenericModelView):
        model = models["child"]
        schema = schemas["child"]

        related = Related(parent=ParentView)

        def put(self, id):
            return self.update(id)

    class ChildWithOtherParentView(ChildView):
        related = ChildView.related | Related(
            other_parent=Related(models["parent"]))

    api = Api(app)
    api.add_resource("/parents/<int:id>", ParentView)
    api.add_resource("/nested_parents/<int:id>", NestedParentView)
    api.add_resource("/parents_with_create/<int:id>", ParentWithCreateView)
    api.add_resource("/children/<int:id>", ChildView)
    api.add_resource("/nested_children/<int:id>", NestedChildView)
    api.add_resource("/children_with_other_parent/<int:id>",
                     ChildWithOtherParentView)
Example #2
0
def routes(app, models, schemas, filter_fields):
    class WidgetListView(GenericModelView):
        model = models['widget']
        schema = schemas['widget']

        filtering = Filtering(
            color=operator.eq,
            size=(operator.eq, {
                'separator': '|',
                'empty': sql.false(),
            }),
            size_alt=(operator.eq, {
                'empty': lambda view: view.model.size == 1,
            }),
            size_min=('size', operator.ge),
            size_divides=('size', lambda size, value: size % value == 0),
            size_is_odd=filter_fields['size_is_odd'],
            color_no_separator=filter_fields['color_no_separator'],
        )

        def get(self):
            return self.list()

    api = Api(app)
    api.add_resource('/widgets', WidgetListView)
Example #3
0
def routes(app, models, schemas):
    class WidgetViewBase(GenericModelView):
        model = models["widget"]
        schema = schemas["widget"]

    class WidgetListView(WidgetViewBase):
        def get(self):
            return self.list()

        def post(self):
            return self.create()

    class WidgetView(WidgetViewBase):
        def get(self, id):
            return self.retrieve(id)

        def patch(self, id):
            return self.update(id, partial=True)

        def delete(self, id):
            return self.destroy(id)

    api = Api(app)
    api.add_resource("/widgets",
                     WidgetListView,
                     WidgetView,
                     id_rule="<int:id>")
Example #4
0
def test_view_func_wrapper(app, views):
    api = Api(app)
    api.add_resource("/widgets", views["widget_list"], views["widget"])

    # This is really a placeholder for asserting that e.g. custom New Relic
    # view information gets passed through.
    assert app.view_functions["WidgetView"].__name__ == "WidgetView"
Example #5
0
def routes(app, models, schemas):
    Widget = models["widget"]

    class WidgetListView(GenericModelView):
        model = models["widget"]
        schema = schemas["widget"]

        sorting = Sorting(
            "name",
            "size",
            content_length=sql.func.length(Widget.content),
            content_length2=lambda model, field_name: sql.func.length(model.
                                                                      content),
        )

        def get(self):
            return self.list()

    class FixedWidgetListView(WidgetListView):
        sorting = FixedSorting("name,size")

        def get(self):
            return self.list()

    api = Api(app)
    api.add_resource("/widgets", WidgetListView)
    api.add_resource("/fixed_widgets", FixedWidgetListView)
Example #6
0
def test_create_client_id(app, views, client):
    api = Api(app)
    api.add_resource("/widgets", views["widget_list"], views["widget"])

    response = client.post("/widgets", data={"id": "100"})
    assert response.headers["Location"] == "http://localhost/widgets/100"
    assert_response(response, 201, {"id": "100"})
Example #7
0
def routes(app, models, schemas, filter_fields):
    class WidgetViewBase(GenericModelView):
        model = models["widget"]
        schema = schemas["widget"]

        filtering = Filtering(
            color=operator.eq,
            color_allow_empty=ColumnFilter("color",
                                           operator.eq,
                                           allow_empty=True),
            size=ColumnFilter(operator.eq, separator="|"),
            size_min=ColumnFilter("size", operator.ge),
            size_divides=ColumnFilter("size",
                                      lambda size, value: size % value == 0),
            size_is_odd=ModelFilter(
                fields.Boolean(),
                lambda model, value: model.size % 2 == int(value),
            ),
            size_min_unvalidated=ColumnFilter("size",
                                              operator.ge,
                                              validate=False),
            size_skip_invalid=ColumnFilter("size",
                                           operator.eq,
                                           skip_invalid=True),
        )

    class WidgetListView(WidgetViewBase):
        def get(self):
            return self.list()

    class WidgetSizeRequiredListView(WidgetViewBase):
        filtering = WidgetViewBase.filtering | Filtering(
            size=ColumnFilter(operator.eq, required=True))

        def get(self):
            return self.list()

    class WidgetColorCustomListView(WidgetViewBase):
        filtering = Filtering(color=filter_fields["color_custom"])

        def get(self):
            return self.list()

    class WidgetDefaultFiltersView(WidgetViewBase):
        filtering = Filtering(
            color=ModelFilter(
                fields.String(missing="red"),
                lambda model, value: model.color == value,
            ),
            size=ColumnFilter(operator.eq, missing=1),
        )

        def get(self):
            return self.list()

    api = Api(app)
    api.add_resource("/widgets", WidgetListView)
    api.add_resource("/widgets_size_required", WidgetSizeRequiredListView)
    api.add_resource("/widgets_color_custom", WidgetColorCustomListView)
    api.add_resource("/widgets_default_filters", WidgetDefaultFiltersView)
def routes(app, models, schemas):
    class WidgetViewBase(GenericModelView):
        model = models["widget"]
        schema = schemas["widget"]
        id_fields = ("id_1", "id_2")

    class WidgetListView(WidgetViewBase):
        def get(self):
            return self.list()

        def post(self):
            return self.create(allow_client_id=True)

    class WidgetView(WidgetViewBase):
        def get(self, id_1, id_2):
            return self.retrieve((id_1, id_2))

        def patch(self, id_1, id_2):
            return self.update((id_1, id_2), partial=True)

        def delete(self, id_1, id_2):
            return self.destroy((id_1, id_2))

    api = Api(app)
    api.add_resource("/widgets",
                     WidgetListView,
                     WidgetView,
                     id_rule="<int:id_1>/<int:id_2>")
Example #9
0
def routes(app, views):
    api = Api(app)
    api.add_resource(
        '/widgets',
        views['widget_list'],
        views['widget'],
        id_rule='<int:id>',
    )
    api.add_resource(
        '/widgets_flush',
        views['widget_flush_list'],
    )
    api.add_resource(
        '/default_error',
        views['default_error'],
    )
    api.add_resource(
        '/abort',
        views['abort'],
    )
    api.add_resource(
        '/uncaught',
        views['uncaught'],
    )
    api.add_resource(
        '/slash/',
        views['slash'],
    )
Example #10
0
def routes(app, models, schemas, auth):
    class WidgetViewBase(GenericModelView):
        model = models['widget']
        schema = schemas['widget']

        authentication = auth['authentication']
        authorization = auth['authorization']

    class WidgetListView(WidgetViewBase):
        def get(self):
            return self.list()

        def post(self):
            return self.create()

    class WidgetView(WidgetViewBase):
        def get(self, id):
            return self.retrieve(id)

        def patch(self, id):
            return self.update(id, partial=True)

        def delete(self, id):
            return self.destroy(id)

    class WidgetAnyCredentialsView(WidgetViewBase):
        authorization = HasAnyCredentialsAuthorization()

        def get(self, id):
            return self.retrieve(id)

    class WidgetCreateMissingView(WidgetViewBase):
        def create_missing_item(self, id):
            return self.create_item({
                'id': id,
                'owner_id': flask.request.args['owner_id'],
            })

        def get(self, id):
            return self.retrieve(id, create_missing=True)

        def put(self, id):
            return self.update(id, create_missing=True)

    api = Api(app)
    api.add_resource(
        '/widgets',
        WidgetListView,
        WidgetView,
        id_rule='<int:id>',
    )
    api.add_resource(
        '/widgets_any_credentials/<int:id>',
        WidgetAnyCredentialsView,
    )
    api.add_resource(
        '/widgets_create_missing/<int:id>',
        WidgetCreateMissingView,
    )
Example #11
0
def test_delete_return_item(app, views, client):
    api = Api(app)
    api.add_resource('/widgets/<int:id>', views['custom_widget'])

    response = client.delete('/widgets/1')
    assert_response(response, 200, {
        'id': '9',
    })
Example #12
0
def test_create_no_location(app, views, client):
    views["widget_list"].get_location = lambda self, item: None

    api = Api(app)
    api.add_resource("/widgets", views["widget_list"], views["widget"])

    response = client.post("/widgets", data={})
    assert "Location" not in response.headers
    assert_response(response, 201, {"id": "2"})
Example #13
0
def test_rule_without_slash(app, views, client):
    api = Api(app, "/api")
    api.add_resource("/widgets", views["widget_list"])

    response = client.get("/widgets")
    assert_response(response, 200)

    response = client.get("/widgets/")
    assert_response(response, 404)
Example #14
0
def test_api_prefix(app, views, client, base_client):
    api = Api(app, "/api")
    api.add_resource("/widgets", views["widget_list"])

    response = client.get("/widgets")
    assert_response(response, 200, [{"id": "1"}])

    response = base_client.get("/api/widgets")
    assert_response(response, 200, [{"id": "1"}])
Example #15
0
def routes(app, models, schemas):
    class WidgetViewBase(GenericModelView):
        model = models['widget']
        schema = schemas['widget']

    class MaxLimitWidgetListView(WidgetViewBase):
        pagination = MaxLimitPagination(2)

        def get(self):
            return self.list()

    class OptionalLimitWidgetListView(WidgetViewBase):
        filtering = Filtering(size=operator.eq, )
        pagination = LimitPagination()

        def get(self):
            return self.list()

        def post(self):
            return self.create()

    class LimitOffsetWidgetListView(WidgetViewBase):
        filtering = Filtering(size=operator.eq, )
        pagination = LimitOffsetPagination(2, 4)

        def get(self):
            return self.list()

        def post(self):
            return self.create()

    class PageWidgetListView(WidgetViewBase):
        pagination = PagePagination(2)

        def get(self):
            return self.list()

        def post(self):
            return self.create()

    class RelayCursorListView(WidgetViewBase):
        sorting = Sorting('id', 'size')
        pagination = RelayCursorPagination(2)

        def get(self):
            return self.list()

        def post(self):
            return self.create()

    api = Api(app)
    api.add_resource('/max_limit_widgets', MaxLimitWidgetListView)
    api.add_resource('/optional_limit_widgets', OptionalLimitWidgetListView)
    api.add_resource('/limit_offset_widgets', LimitOffsetWidgetListView)
    api.add_resource('/page_widgets', PageWidgetListView)
    api.add_resource('/relay_cursor_widgets', RelayCursorListView)
Example #16
0
def test_factory_pattern(app, views, client):
    api = Api()
    api.init_app(app)

    with pytest.raises(AssertionError, match="no application specified"):
        api.add_resource("/widgets", views["widget_list"])

    api.add_resource("/widgets", views["widget_list"], app=app)

    response = client.get("/widgets")
    assert_response(response, 200, [{"id": "1"}])
def routes(app, views):
    api = Api(app)
    api.add_resource("/widgets",
                     views["widget_list"],
                     views["widget"],
                     id_rule="<int:id>")
    api.add_resource("/widgets_flush", views["widget_flush_list"])
    api.add_resource("/default_error", views["default_error"])
    api.add_resource("/abort", views["abort"])
    api.add_resource("/uncaught", views["uncaught"])
    api.add_resource("/slash/", views["slash"])
Example #18
0
def test_create_no_location(app, views, client):
    views['widget_list'].get_location = lambda self, item: None

    api = Api(app)
    api.add_resource('/widgets', views['widget_list'], views['widget'])

    response = client.post('/widgets', data={})
    assert 'Location' not in response.headers
    assert_response(response, 201, {
        'id': '2',
    })
Example #19
0
def test_create_client_id(app, views, client):
    api = Api(app)
    api.add_resource('/widgets', views['widget_list'], views['widget'])

    response = client.post('/widgets', data={
        'id': '100',
    })
    assert response.headers['Location'] == 'http://localhost/widgets/100'
    assert_response(response, 201, {
        'id': '100',
    })
Example #20
0
def test_no_append_slash(monkeypatch, app, views, client):
    monkeypatch.setattr(app, "url_rule_class", StrictRule)

    api = Api(app, "/api")
    api.add_resource("/widgets/", views["widget_list"])

    response = client.get("/widgets")
    assert_response(response, 404)

    response = client.get("/widgets/")
    assert_response(response, 200)
def create_app() -> Flask:
    app = Flask(__name__)

    # Load application settings from environment variable.
    # If environment variable is not set will load development settings by default.
    app_settings = os.getenv("APP_SETTINGS", "settings.DevelopmentConfig")
    env_path = Path(".env.development").absolute()

    if not app_settings:
        raise ValueError('"APP_SETTINGS" environment variable not set')

    if app_settings == "settings.TestingConfig":
        env_path = Path(".env.testing")
    elif app_settings == "settings.ProductionConfig":
        env_path = Path(".env.production")

    # Load environment variables depending on application settings (Dev/Test/Prod)
    load_dotenv(path=env_path)
    app.config.from_object(app_settings)

    # Initialize Flask-SQLAlchemy ORM
    db.init_app(app)
    db.app = app

    # Initialize Flask-Migrate
    Migrate(app, db)

    # Initialize flask_resty api
    api = Api(app, prefix="/api")
    initialize_routes(api)

    # Initialize Flask-Bcrypt
    bcrypt_.init_app(app)

    # Initialize swagger
    template = {
        "components": {
            "securitySchemes": {
                "basicAuth": {
                    "type": "http",
                    "scheme": "basic"
                },
                "bearerAuth": {
                    "type": "http",
                    "scheme": "bearer",
                    "bearerFormat": "JWT",
                },
            }
        }
    }
    Swagger(app, template=template)

    return app
def routes(app, views):
    api = Api(app)
    api.add_resource(
        '/widgets',
        views['widget_list'],
        views['widget'],
        id_rule='<int:id>',
    )
    api.add_resource(
        '/widgets_flush',
        views['widget_flush_list'],
    )
Example #23
0
def test_factory_pattern(app, views, client):
    api = Api()
    api.init_app(app)

    with pytest.raises(AssertionError, message="no application specified"):
        api.add_resource('/widgets', views['widget_list'])

    api.add_resource('/widgets', views['widget_list'], app=app)

    response = client.get('/widgets')
    assert_response(response, 200, [{
        'id': '1',
    }])
Example #24
0
    def routes(self, app, models, schemas, auth):
        class WidgetListView(GenericModelView):
            model = models['widget']
            schema = schemas['widget']

            authentication = auth['authentication']
            authorization = auth['authorization']

            def get(self):
                return self.list()

        api = Api(app)
        api.add_resource('/widgets', WidgetListView)
Example #25
0
def test_api_prefix(app, views, client, base_client):
    api = Api(app, '/api')
    api.add_resource('/widgets', views['widget_list'])

    response = client.get('/widgets')
    assert_response(response, 200, [{
        'id': '1',
    }])

    response = base_client.get('/api/widgets')
    assert_response(response, 200, [{
        'id': '1',
    }])
Example #26
0
def test_training_slash(app, views, client):
    api = Api(app)
    api.add_resource(
        "/widgets/", views["widget_list"], views["widget"], id_rule="<id>/"
    )

    response = client.post("/widgets/", data={"id": "100"})
    assert response.headers["Location"] == "http://localhost/widgets/100/"

    assert_response(response, 201, {"id": "100"})

    response = client.get("/widgets/100/")
    assert response.status_code == 200
Example #27
0
def routes(app, models, schemas, filter_fields):
    class WidgetViewBase(GenericModelView):
        model = models['widget']
        schema = schemas['widget']

    class WidgetListView(WidgetViewBase):
        filtering = Filtering(
            color=operator.eq,
            color_allow_empty=ColumnFilter(
                'color',
                operator.eq,
                allow_empty=True,
            ),
            size=ColumnFilter(operator.eq, separator='|'),
            size_min=ColumnFilter('size', operator.ge),
            size_divides=ColumnFilter(
                'size',
                lambda size, value: size % value == 0,
            ),
            size_is_odd=filter_fields['size_is_odd'],
            size_min_unvalidated=ColumnFilter(
                'size',
                operator.ge,
                validate=False,
            ),
        )

        def get(self):
            return self.list()

    class WidgetSizeRequiredListView(WidgetViewBase):
        filtering = Filtering(
            size=ColumnFilter(operator.eq, required=True),
        )

        def get(self):
            return self.list()

    class WidgetColorCustomListView(WidgetViewBase):
        filtering = Filtering(
            color=filter_fields['color_custom'],
        )

        def get(self):
            return self.list()

    api = Api(app)
    api.add_resource('/widgets', WidgetListView)
    api.add_resource('/widgets_size_required', WidgetSizeRequiredListView)
    api.add_resource('/widgets_color_custom', WidgetColorCustomListView)
Example #28
0
def routes(app, models):
    class WidgetView(ModelView):
        model = models['widget']

        @get_item_or_404
        def get(self, item):
            return str(item.id)

        @get_item_or_404(create_missing=True)
        def put(self, item):
            return str(item.id)

    api = Api(app)
    api.add_resource('/widgets/<int:id>', WidgetView)
Example #29
0
def test_resource_rules(app, views, client):
    api = Api(app)
    api.add_resource(
        base_rule="/widget/<id>",
        base_view=views["widget"],
        alternate_rule="/widgets",
        alternate_view=views["widget_list"],
    )

    get_response = client.get("/widget/1")

    assert_response(get_response, 200, {"id": "1"})

    post_response = client.post("/widgets", data={})
    assert post_response.headers["Location"] == "http://localhost/widget/2"

    assert_response(post_response, 201, {"id": "2"})
Example #30
0
def routes(app, models):
    class WidgetView(ModelView):
        model = models["widget"]

        @get_item_or_404
        def get(self, item):
            return str(item.id)

        @get_item_or_404(create_transient_stub=True)
        def put(self, item):
            return str(item.id)

        @get_item_or_404(with_for_update=True)
        def patch(self, item):
            return str(item.id)

    api = Api(app)
    api.add_resource("/widgets/<int:id>", WidgetView)