Coder Social home page Coder Social logo

flask_accepts's People

Contributors

andreykis avatar apryor6 avatar azzamsa avatar calvinwyoung avatar cirruseo avatar daniel-svard avatar dependabot[bot] avatar elnygren avatar john-bodley avatar mjreiss avatar pipozzz avatar rafaelcascalho avatar stael avatar vladarefiev avatar volfpeter avatar wormfriend avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flask_accepts's Issues

Adding descriptions to fields

Flask-RESTPlus has the ability to set field descriptions that appear in swagger like so:
https://flask-restplus.readthedocs.io/en/stable/swagger.html#documenting-the-fields
Is something like this possible in flask_accepts with marshmallow? I can't find anything in the documentation and a quick glance over the flask_accepts source indicates that any "metadata" set on a marshmallow field is ignored during the mapping process. I imagine that something like this would be ideal:

from marshmallow import Schema, fields

class SomeSchema(Schema):
    some_field = fields.String(metadata={"description":"Some Field"})

Reference for marshmallow field metadata: https://marshmallow.readthedocs.io/en/stable/api_reference.html#module-marshmallow.fields

Any ideas?

Update dev-requirements.txt

Hi, great library.
There's a typo in dev-requirement.txt , flask-restx version is flask-restx==0.12.1, which doesn't exist.

TypeError: Unknown type for marshmallow model field was used.

Hi,

I wanted to use custom marshmallow field related to mongo data serialisation

class ObjectIdField(fields.Field):

    def _deserialize(self, value, attr, data, **kwargs):
        try:
            return bson.ObjectId(value)
        except Exception:
            raise ValidationError('invalid ObjectId `%s`' % value)

    def _serialize(self, value, attr, obj, **kwargs):
        if value is None:
            return missing
        return str(value)```

and I'm getting this error: TypeError: Unknown type for marshmallow model field was used.

Could you give me some directions how to deal with this? 

Thanks

Support for different swagger output per HTTP method

Say I have the following snippet:

class WidgetSchema(Schema):
    id = fields.UUID()
    created_at = fields.DateTime()
    foo = fields.String()
    baz = fields.Integer()


def create_app():
    app = Flask(__name__)
    api = Api(app)

    @api.route("/widget")
    class WidgetResource(Resource):
        @accepts(schema=WidgetSchema, api=api)
        @responds(schema=WidgetSchema, api=api)
        def post(self):
            # save data to a new record, and return ID
            return request.parsed_obj

        @accepts(dict(name="id", type=UUID), schema=WidgetSchema, api=api)
        @responds(schema=WidgetSchema, api=api)
        def patch(self):
            return request.parsed_obj

    return app

In this scenario, here are the available fields for each method:
post

  • foo
  • baz

patch

  • foo

id and created_at are set by the database, and baz may only be set during a record creation. Therefore, the model (which describes Widget records), and the acceptable fields for each method are all different.

The default behavior should remain the same. However, the introduction of a new parameter (fields or something) could provide a list of strings. The strings would be the field names that are allowed for a particular method. If provided, the decorator should ensure that only the fields from that list are included in the request. Additionally, the Swagger UI would only list fields from fields as available inputs.

The only alternative solution I can see is to create a separate schema for each unique method accept and response (which could become quite verbose).

Here is an example of the same snippet with the new parameters:

class WidgetSchema(Schema):
    id = fields.UUID()
    created_at = fields.DateTime()
    foo = fields.String()
    baz = fields.Integer()


def create_app():
    app = Flask(__name__)
    api = Api(app)

    @api.route("/widget")
    class WidgetResource(Resource):
        @accepts(schema=WidgetSchema, api=api, fields=["foo", "baz"])
        @responds(schema=WidgetSchema, api=api)
        def post(self):
            # save data to a new record, and return ID
            return request.parsed_obj

        @accepts(dict(name="id", type=UUID), schema=WidgetSchema, api=api, fields=["foo"])
        @responds(schema=WidgetSchema, api=api)
        def patch(self):
            return request.parsed_obj

    return app

Support for higher flask-restx versions ?

I'm getting error in my new project using latest flask-restx

flask-accepts 0.16.2 has requirement flask-restx==0.1.0, but you'll have flask-restx 0.2.0 which is incompatible.

Are you going to support multiple versions instead of flask-restx==0.1.0?

Thanks

Partial param for Schema loading

Hey there.
I would like to add partial: bool param to @accepts decorator for passing it to schema.load()
I created local branch with those changes, how can I create a PR?

[Q] Customize schema_errors?

Currently, when I send a post request with invalid data, I'm getting this response

{
    "schema_errors": {
        "email": [
            "Not a valid email address."
        ],
        "password": [
            "Missing data for required field."
        ]
    }
}

Is it possible to customize it such that it appears something like this?

{
    "message": "Problem occurred",
    "errors": {
        "email": [
            "Not a valid email address."
        ],
        "password": [
            "Missing data for required field."
        ]
    }
}

Support for marshmallow_sqlalchemy

Hi,
i tried to use the flask_accepts extension with marshmallow_sqlalchemy.

Unfortunately it crashes at the utils.py map_type function, because its a ModelSchema or a ModelMetaSchema.

a quick fix would be adding:

try:
    from marshmallow_sqlalchemy import ModelSchema, ModelSchemameta
except ImportError:
    pass

and modifing

def map_type(val, api, model_name, operation):
    value_type = type(val)

    if value_type in type_map:
        return type_map[value_type](val, api, model_name, operation)

    if isinstance(value_type, SchemaMeta) or isinstance(value_type, Schema) or isinstance(value_type,ModelSchemaMeta) or  isinstance(value_type,ModelSchema):
        return type_map[Schema](val, api, model_name, operation)

    raise TypeError('Unknown type for marshmallow model field was used.')

Usage with flask_marschmallow (with optional flask_sqlalchemy and marshmellow-sqlalchemy)

A short question:

Is it possible to use the two decorators @accepts and @responds with schemas defined with flask_marshmellow including the optional integration with flask_sqlalchemy and marshmellow-sqlalchemy?

That way, I could connect marshmallow schemas with models from sqlalchemy and still use your decorators to save some line of codes including swagger documentation.

I pose this question, as I don't see exactly, how you use marshmallow under the hood.

Thanks

Decorators do not work with schema instances

The decorators "accepts" and "responds" do not work with Marshmallow schema instances. It will be important to allow that, since you can pass keyword parameters to a schema instance constructor such as "only" and "exclude".

Using a scheme instance with accepts results in:

  File "/group13/mattf/git-projects/adfs/venv/lib/python3.6/site-packages/flask_accepts/utils.py", line 32, in for_swagger
    for k, v in vars(schema()).get("declared_fields", {}).items()
TypeError: 'MySchema' object is not callable

Using a schema instance with responds results in:

  File "/group13/mattf/git-projects/adfs/venv/lib/python3.6/site-packages/flask_accepts/utils.py", line 54, in get_default_model_name
    return "".join(schema.__name__.rsplit("Schema", 1))
AttributeError: 'PersonSchema' object has no attribute '__name__'

These should be very easy to fix in the utils module.

Support multiple status codes and schemas with responds

Currently, only a single responds decorator may be provided, optionally with a status_code. Support for multiple schemas corresponding to different status codes would be straightforward to implement by inspecting the return type and mapping the status_code to the schema, if it is available.

The current functionality for ignoring pre-made Flask Responses would need to be modified to only ignore those for which it does not have a corresponding Schema.

The status code of the response can come from any of the normal Flask means (i.e. as a data, code, headers tuple, via make_response, etc)

Add support of marshmallow schema instance as nested parameter.

As seen from this answer, marshmallow supports usage of schema instance as nested field of outer schema.

Question in that StackOverflow thread contains one of the examples, when this could be useful and exact use-case we have in our project.

Unfortunately, flask_accepts doesn't support such behaviour at the moment. Usage of schema instance results in Error, thrown in flask_accepts/utils.py at this line of code:
Screen Shot 2019-10-10 at 13 34 35

I could submit a fix for that by the end of today. The only change added will be this one:
Screen Shot 2019-10-10 at 13 50 56

Note: In the future this could be improved to iteration over type_map keys and ensuring isinstance for all of them.
This would make available usage of marshmallow feature to extend existing marshmallow fields

Nested Marshmallow Schemas throwing error on Swagger

Using the code from Issue #25 I'm seeing an error thrown in swagger.

Schemas registered with fields.Nested() are not showing up in the swagger ui, and the ui throws the error.

image

code:

import datetime
from dataclasses import dataclass
import werkzeug
werkzeug.cached_property = werkzeug.utils.cached_property
from marshmallow import fields, Schema, post_load
from flask import Flask, jsonify, request
from flask_accepts import accepts, responds


class CogSchema(Schema):
    cog_foo = fields.String(default="cog")
    cog_baz = fields.Integer(default=999)


class WidgetSchema(Schema):
    foo = fields.String(default="test string")
    baz = fields.Integer(default=42)
    flag = fields.Bool(default=False)
    date = fields.Date(default="01-01-1900")
    dec = fields.Decimal(default=42.42)
    dct = fields.Dict(default={"key": "value"})

    cog = fields.Nested(CogSchema)


def create_app(env=None):
    from flask_restplus import Api, Namespace, Resource

    app = Flask(__name__)
    api = Api(app)

    @app.route("/simple/make_a_widget", methods=["POST"])
    @accepts(dict(name="some_arg", type=str), schema=WidgetSchema)
    @responds(schema=WidgetSchema)
    def post():
        from flask import jsonify

        return request.parsed_obj

    @api.route("/restplus/make_a_widget")
    class WidgetResource(Resource):
        @accepts(dict(name="some_arg", type=str), schema=WidgetSchema, api=api)
        @responds(schema=WidgetSchema, api=api)
        def post(self):
            from flask import jsonify

            return request.parsed_obj

    return app


app = create_app()
if __name__ == "__main__":
    app.run(debug=True)

Issue with metaclass and Schemas in Nested fields

Hi,

This refers to #39 and #40

I'm in a situation where I use flask_accepts in association with flask_marshmallow and marshmallow_sqlalchemy.

Basically, all schemas that I define are not constructed from marshmallow base Schema class directly but from another class SQLAlchemySchema (which itself inherits from marshmallow base Schema). In that configuration, when trying to use these Schemas in a Nested field, flask_accepts throws a TypeError as seen in #39: "Unknown type for marshmallow model field was used."

Long story short after looking into it, I can see that SQLAlchemySchema class uses its own metaclass (inherited from marshmallow SchemaMeta) which prevents #40 from working as it uses isinstance to check the type of the provided Schema.

In example (simplified), we have:

from marshmallow.schema import Schema, SchemaMeta


class SQLAlchemyMeta(SchemaMeta):
   ...

class SQLAlchemySchema(Schema, metaclass=SQLAlchemyMeta):
   ...

which leads to the following:

>>> isinstance(type(SQLAlchemySchema), SchemaMeta)
False

and causes the error because type(SQLAlchemySchema) returns SQLAlchemyMeta and not SchemaMeta.

I think we can solve this by using issubclass instead of isinstance in #40, which would give:

def map_type(val, api, model_name, operation):
    value_type = type(val)
    if value_type in type_map:
        return type_map[value_type](val, api, model_name, operation)

    if issubclass(value_type, SchemaMeta) or issubclass(value_type, Schema):
        return type_map[Schema](val, api, model_name, operation)

    raise TypeError('Unknown type for marshmallow model field was used.')

I've implemented this change in my project and all seems to work fine.

I'm more than willing to make a PR for this but I'd like to have feedback on my analysis and make sure I did not miss anything.

Avoid explicit passing of api parameter

It would be nice to avoid having to pass api=... in the decorators for cases where you are attaching swagger documentation to a RESTplus Resource.

The reason for the existing mechanism is that the decorators must introspect to determine if they are being applied to a class method vs a regular function in order to properly register documentation. Perhaps through inspecting local/closure variables within the decorator it may be possible to identify the associated Api, but I'm not completely sure.

It will likely always be necessary to keep the api parameter around in cases where the default behavior does not function as the user wants, but ideally the default behavior "just works" for most cases and can simplify the flask_accepts api.

The X-Fields header is ignored

Hi,

The handling of the X-Fields header (or the app.config["RESTX_MASK_HEADER"] header to be more precise) is ignored when response marshaling is done using a mashmallow schema.

I have already implemented the bug fix, PR is coming soon.

All the best!

Support is missing for some field types, particularly Boolean, Date, and DateTime

As in the title, it would be very useful to support the Date, DateTime, and Boolean field types. These don't come through in the registered model, and I can see that they are not in the type_map dict in utils.py. There are a great many field types in Marshmallow, some of which may not be relevant to this conversion exercise, but the three I've listed are arguably essential. Where a type is not supported in flask-accepts, I'd say it should default to Raw.

Support documentation of validator functions in Swagger

See some preliminary discussion in #15

Marshmallow provides rich validation that, although it can be used in flask_accepts now, does not come with documentation. We can create a mapping to provide Swagger docs on validators that have a corresponding validator in both libraries. The remainder will either get ignored or can be addressed with a lower level solution.

Wierd model names after version 0.12.0

Model names are showing load and dump extensions after version 0.12.x

class CogSchema(Schema):
    cog_foo = fields.String(default="cog")
    cog_baz = fields.Integer(default=999)


class WidgetSchema(Schema):
    foo = fields.String(default="test string")
    baz = fields.Integer(default=42)
    flag = fields.Bool(default=False)
    date = fields.Date(default="01-01-1900")
    dec = fields.Decimal(default=42.42)
    dct = fields.Dict(default={"key": "value"})

    cog = fields.Nested(CogSchema)


@api.route("/restplus/make_a_widget")
class WidgetResource(Resource):
    @accepts(dict(name="some_arg", type=str), schema=CogSchema, api=api)
    @responds(schema=CogSchema, api=api)
    def get(self):
        return request.parsed_obj

    @accepts(dict(name="some_arg", type=str), schema=WidgetSchema, api=api)
    @responds(schema=WidgetSchema, api=api)
    def post(self):
        return request.parsed_obj

image

Partial schema loading

I took a short look to the decorators and I cannot see a way, to load an added schema partially (therefore ignore required fields) as described in Partial Loading in the marshmallow docs.
An additional arg to the accepts decorator which wil be passed further to the schema.loads methods would make that feature also available in flask_accepts.

Missing 'required', 'description', 'default' parameters in Restplus field initialisation.

Restplus provides opportunity to specify if a field in a model is required or not. It also has per-field description, default parameters and other interesting documentation features.

Unfortunately, most of this functionality is not yet supported by flask_accepts, while it might be super-useful for end users to see such information in docs (alongside with fields description, which already has an opened issue #33 ). So I would be happy to participate in developing those features.

As far as I understood, missing 'description, 'required' and other parameters can be fully fixed by modifying

flask_accepts/utils

type_map variable.

I can submit PR with this function:

def _ma_field_to_fr_field(value, model_name) -> dict:
    fr_field_parameters = {}

    if hasattr(value, 'default'):
        fr_field_parameters['example'] = value.default

    if hasattr(value, 'required'):
        if isinstance(value.required, bool) is False:
            raise TypeError(
                "Wrong type for 'required' parameter in marshmallow schema field. Model: {}, field: {}".format(
                    model_name, value.name
                )
            )

        fr_field_parameters['required'] = value.required

    if hasattr(value, 'metadata') and 'description' in value.metadata:
        fr_field_parameters['description'] = value.metadata['description']

    if hasattr(value, 'missing') and type(value.missing) != ma.utils._Missing:
        fr_field_parameters['default'] = value.missing

    return fr_field_parameters

It can be applied in every mapper function, used to map marshmallow field type to restplus field type in this way:

ma.Bool: lambda val, api, model_name, operation: fr.Boolean(
        **_ma_field_to_fr_field(val, model_name)
),

It should also be applied to Nested and List types in the same way:

fr.List(
        map_type(val.inner, api, model_name, operation), **_ma_field_to_fr_field(val, model_name)
)
fr.Nested(
        map_type(val.nested, api, model_name, operation), **_ma_field_to_fr_field(val, model_name)
)

It can later be used to parse marshmallow model fields for Range validator with min / max being present. This might be useful as restplus allows to specify min / max values for List, String, Float and other types.

The result documentation for models would look like this:
Screen Shot 2019-09-24 at 13 40 07

For comparison, without this fix, documentation for same model would look like this:
Screen Shot 2019-09-24 at 13 41 14

If this whole thing makes sense to lead developers on this project, I am happy to add some tests to new functionality and submit PR by the end of today.

Small Note: I have been working with restplus a lot in scope of my current project at work. Unfortunately, me and my team realised restplus limits us too much in terms of model parsing. That is why we decided to move to Marshmallow. However, we want to keep documentation and are planning to use flask_accepts to do so. That is why I will be happy to submit other changes in future.

Flask + flask-resplus crash when returning dict from API

Example code:

@api.route('/user')
class UserAPIResource(Resource):
    '''REST API with get, put, post...'''

    @responds(schema=UserSchema(), api=api, status_code=200)
    def get(self):
        """
        return current user info that gets used by various services
        """
        data = get_user_data(user_id=current_user.id)
        # data is a dict here, like {"email": "...", etc...}
        return data

Crashes:

TypeError: 'dict' object is not callable
The view function did not return a valid response. The return type must be a string, tuple, Response instance, or WSGI callable, but it was a dict.

It's because of the following part in decorators.py

if not _is_method(func): # <- this fails
    return jsonify(serialized), status_code
# and we hit this line which DOES NOT use jsonify 
# although flask expects somethign wrapped in jsonify here...
return serialized, status_code

Looking for a way to use a schema to define acceptable query params

I have a case where I defined a marshmallow schema that is being used in both @accepts and @responds for different methods. I would like to use the schema object in an @accepts for a get_all route but instead of the fields being defined in the body of the request they should be query params. For example a UserSchema might have 3 fields.

class UserSchema(Schema):
    userId = ma_fields.Integer(dump_only=True, attribute='user_id')
    firstName = ma_fields.String(attribute='first_name')
    emailAddress = ma_fields.Email(attribute='email')

and we might have a get_all route like this

    @accepts(dict(name='limit', type=int), dict(name='page', type=int), api=api)
    @responds(schema=UserSchema(many=True), api=api)
    def get(self):
        return UserService.get_all(**request.parsed_args)

I would like to have a route with documented parameters based on the schema
Perhaps something like

    @accepts(dict(name='limit', type=int), dict(name='page', type=int), UserSchema(location='values'), api=api)
    @responds(schema=UserSchema(many=True), api=api)
    def get(self):
        return UserService.get_all(**request.parsed_args)

It seems like if we are returning a UserSchema object/s with this request we should be able to easily make all of that schemas dump-able fields queryable.

End result would document the existence of ?userId ?firstName and ?emailAddress.
and request.parsed_args would be a dict with 'user_id', 'first_name', 'email' as well as the other query arg dicts 'limit' and 'page'

[Question] flask-RESTful or flask-restplus

Hi!
I am using flask_accepts together with flask_restplus.
To do so, I need to change some code of this library.
My question is that, with which is this library intended to be used, flask_RESTful or flask_restplus ?

Marshmallow Two-way Nesting Schemas Validation

In order to avoid circular import in a flask/marshmallow project, it's possible to reference the Nested field by using its name (as described here https://marshmallow.readthedocs.io/en/latest/nesting.html#two-way-nesting)

Unfortunately, flask_accepts doesn't support it :

 File env/lib/python3.8/site-packages/flask_accepts/decorators/decorators.py", line 110, in decorator
body = for_swagger(
File "env/lib/python3.8/site-packages/flask_accepts/utils.py", line 63, in for_swagger
fields = {
File "env/lib/python3.8/site-packages/flask_accepts/utils.py", line 64, in
k: map_type(v, api, model_name, operation)
File "env/lib/python3.8/site-packages/flask_accepts/utils.py", line 182, in map_type
return type_map[value_type](val, api, model_name, operation)
File "env/lib/python3.8/site-packages/flask_accepts/utils.py", line 19, in unpack_nested
model_name = get_default_model_name(val.nested)
File "env/lib/python3.8/site-packages/flask_accepts/utils.py", line 152, in get_default_model_name
return "".join(schema.name.rsplit("Schema", 1))

AttributeError: 'str' object has no attribute 'name'

A change will also be necessary for the method map_type() since you have to give the object iteself while it's not yet charged.
Can you please add the possibility to support this configuration ?
Thank you

Only swagger generation for end-point

Hello @apryor6 .
I am happy using this library, but sometimes I want to do something before validation, for example pass context to Marshmallow Schema, but I still want to generate swagger for this API.

I'd like to contribute to the library implementing such functionality. What is the best way to do it to your opinion?

  • extend existing both accepts and responds decorators with validate: bool param.
  • create new decorator @swagger just for generation swagger spec.

What do you think?

@accepts overwirte "location"

when add accepts like this:
@accepts(dict(name='file',type=FileStorage, help='select file', location='files'),api=api)
the swagger doc is not correct.

In decorators.py line 56:
for qp in query_params: _parser.add_argument(**qp, location="values")

I changed to:
for qp in query_params: if(qp.get('location')): _parser.add_argument(**qp) else: _parser.add_argument(**qp,location="values")

then swagger works.

Specifying a default, non-JSON-serializable value causes Swagger page to crash

I am using flask-restx==0.2.0 with flask_accepts==0.16.4

Specifying default as a non serializable value like datetime in Marshmallow causes the Swagger page to fail to load. Here is my code:

Marshmallow class

class RespondSchema(Schema):
    data = fields.String(required=True)
    timestamp = fields.DateTime(default=datetime.utcnow)

Route

@api.route("/route")
class SomeRoute(Resource):
    @api.doc("some_route")
    @accepts(schema=AcceptSchema, api=api)
    @responds(schema=RespondSchema, api=api)
    def post(self):
        return SomeService.do_stuff(request.parsed_obj)

Traceback

Traceback (most recent call last):
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask/app.py", line 2464, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/werkzeug/middleware/proxy_fix.py", line 169, in __call__
    return self.app(environ, start_response)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask/app.py", line 2450, in wsgi_app
    response = self.handle_exception(e)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask_restx/api.py", line 638, in error_router
    return original_handler(f)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask/app.py", line 1867, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask_restx/api.py", line 636, in error_router
    return self.handle_error(e)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask_restx/api.py", line 638, in error_router
    return original_handler(f)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask_restx/api.py", line 636, in error_router
    return self.handle_error(e)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask_restx/api.py", line 379, in wrapper
    return self.make_response(data, code, headers=headers)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask_restx/api.py", line 402, in make_response
    resp = self.representations[mediatype](data, *args, **kwargs)
  File "/Users/andrew.mickael/PycharmProjects/Financial-Ingestion-Service/venv/lib/python3.7/site-packages/flask_restx/representations.py", line 25, in output_json
    dumped = dumps(data, **settings) + "\n"
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 201, in encode
    chunks = list(chunks)
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 431, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 438, in _iterencode
    o = _default(o)
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type builtin_function_or_method is not JSON serializable

marshmallow's (>=3.0.0b7) load method has only one output

Hi,
I tried to use the decorator @accepts with a marshmallow schema, but there is an error:

File "/XXX/YYY//site-packages/flask_accepts/decorators/decorators.py", line 80, in inner
obj, err = schema(many=many).load(request.get_json())
ValueError: too many values to unpack (expected 2)

I think, this is because marshmallow's schema.load returns from version 3.0.0b7 only one parameter, not two (https://marshmallow.readthedocs.io/en/stable/upgrading.html).

Is there any way to cover this?

Support stacked model definitions with both decorators

Currently, the model name can be specified in either accepts or responds; however, in the case where both decorators are applied there is a "last in" effect where the top-most decorator (in code) are the only models that are displayed in the documentation. This affects only the documentation and not the functionality of the api itself.

It would be preferable to allow for declaration of models at both places or, at least, to be able to introspect in the case where both decorators are provided but the name is given in the lower decorator.

Multipart Request

Currently, only content-type:json is supported in @accepts as per code here.

In my use-case, request schema has a file and other form parameters. Since flask keeps that data in request.values and request.form attributes it is currently not configurable.

My suggestion for this is to check the headers and parse the parameters accordingly. Please let me know If there is another way to get around it or this can be the right direction going forward. And If it is, I can pitch in to create a PR for it.

Marshmallow schema with many=True seems to be ignored

Using a marshmallow schema with many=True seems to be ignored in both validation and the swagger output.

my_ns = my_api.namespace("roles")

@my_ns.route("/")
class MyResource(flask_restplus.Resource):
    @flask_accepts.accepts(schema=MyRequestSchema(many=True), api=my_ns)
    @flask_accepts.responds(schema=MyResponseSchema(many=True), api=my_ns)
    def put():
        return []

For this example, the endpoint will not accept a list at the top-level of the request body as I intend. It just accepts an object as if many=True wasn't there.

I believe in versions prior to 0.14.2 the validation worked, but the swagger output was still incorrect.

Add supported versions to readme and/or pypi

Hi.
After cloning the project and installing requirements, I tried to run the tests only for them to fail. I then realized that this library uses dataclasses which is a python >= 3.8 feature. Would be nice to add this information to the README file. It would really help with those interested in contributing ๐Ÿ˜….

Feature: accept dictionaries as schemas

Hi,

Just for the sake of completeness, the accepts and responds decorators should accept dictionaries (with a model_name argument) as a schema. To achieve this, model_name could be passed on to _get_or_create_schema() from the decorators and the method should be extended with this bit of code:

if isinstance(schema, dict):
    if model_name is None:
        raise ValueError(
            "You should set model_name when the schema is generated from a dict."
        )
    schema = Schema.from_dict(schema, name=model_name)

I can send a PR if the feature request is accepted.

Br,

Nested marshmellow schemas

This lib is really nice and works great with simple marshmallow schemas. Unfortunately Swagger doesn't display correctly when using nested schemas like this

Headers are not validated in @accepts decorator

According to restPlus documentaion:

Use the location argument to add_argument() to specify alternate locations to pull the values from(https://flask-restplus.readthedocs.io/en/stable/parsing.html)

From the request headers

parser.add_argument('User-Agent', location='headers')

So restPlus parser can validate headers if it is necessary, but if I use @accepts deco it does not validate headers. See example below:

class Todo(Resource):
   @accepts(
        {'name': 'id', 'type': str, 'required': True, 'action': 'append'},
        {'name': 'fake_header', 'type': str, 'required': True, 'location': 'headers'},   # verify header
        schema=SomeSchema,
        api=api
    )
    def post(self):
        return {"method": 'Fake header is not validated!'}

And when I trigger the POST method without fake_header it returns me response (200 OK), but I expect 400 Bad request.

It looks like you somehow override default behavior of reqparse module.

Add Swagger for supported marshmallow validators

I am trying to add a string field to my Schema which uses the validate.OneOf() from marshmallow. I see the correct error response if I pass a bad option to this field but the Swagger UI does not have the helpful options in model description. Are there plans to add maps from the native marshmallow validators to the supported Flask-Restplus validators.

Screen Shot 2019-12-17 at 2 14 43 PM

I was able to achieve this behavior using the api.model from Restplus

TypeError: int() argument must be a string, a bytes-like object or a number, not 'InstrumentedAttribute'

Using the Swagger interface i'm trying to make a PUT request. This triggers the update but i get an error in the response and in the console where i'm running the server.

Response error:

{
  "message": "Internal Server Error"
}

I'm using Flask_api_example, the tests all pass fine but making a PUT request in the swagger interface (127.0.0.1:5000) triggers this error. The entry gets updated just fine, couldn't find the issue in my implementation so i think it can be related to flask_accepts.

127.0.0.1 - - [12/Nov/2019 20:22:47] "GET /api/barbota/ranks/ HTTP/1.1" 200 -
[2019-11-12 20:22:57,833] ERROR in app: Exception on /api/barbota/ranks/1 [PUT]
Traceback (most recent call last):
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/flask_restplus/api.py", line 325, in wrapper
    resp = resource(*args, **kwargs)
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/flask/views.py", line 89, in view
    return self.dispatch_request(*args, **kwargs)
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/flask_restplus/resource.py", line 44, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/flask_accepts/decorators/decorators.py", line 100, in inner
    return func(*args, **kwargs)
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/flask_accepts/decorators/decorators.py", line 186, in inner
    serialized = schema.dump(rv)
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/marshmallow/schema.py", line 553, in dump
    result = self._serialize(processed_obj, many=many)
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/marshmallow/schema.py", line 517, in _serialize
    value = field_obj.serialize(attr_name, obj, accessor=self.get_attribute)
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/marshmallow/fields.py", line 325, in serialize
    return self._serialize(value, attr, obj, **kwargs)
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/marshmallow/fields.py", line 899, in _serialize
    ret = self._format_num(value)  # type: _T
  File "/home/bledy/projects/barbota-api/.venv/lib/python3.7/site-packages/marshmallow/fields.py", line 874, in _format_num
    return self.num_type(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'InstrumentedAttribute'

Simple Example in README.md looks incorrect

README.md contains the following example, but it looks to me like there are some issues with this code. I'd fix it, but I'm not 100% sure what the best fix is. Happy to raise a PR if you're able to point me in the right direction.

The code looks like this...

from flask import Flask, request
from flask_accepts import accepts, responds

from .widget import Widget, WidgetSchema, make_widget

def create_app():
    app = Flask(__name__)

    @app.route("/widget")
    @accepts(dict(name="foo", type=str), api=api)
    @responds(schema=WidgetSchema, api=api)
    def widget()
        name: str = request.parsed_args["foo"]
	widget: Widget = make_widget(name)
	return widget

    return app

Issues:

  • the def widget() is missing the :. Easy fix.
  • the @accepts decorator uses api but this isn't defined within this code. Is the fix to remove this from the decorator?
  • the @responds decorator has same issue. Same fix?

TypeError: make() got an unexpected keyword argument 'many'

I'm attempting to run your marshmallow_example.py example, but keep running into this error:

...
File "/Users/SomeProject/venv/lib/python3.7/site-packages/marshmallow/schema.py", line 835, in _do_load
    partial=partial,
  File "/Users/SomeProject/venv/lib/python3.7/site-packages/marshmallow/schema.py", line 1014, in _invoke_load_processors
    partial=partial,
  File "/Users/SomeProject/venv/lib/python3.7/site-packages/marshmallow/schema.py", line 1135, in _invoke_processors
    data = processor(data, many=many, **kwargs)
TypeError: make() got an unexpected keyword argument 'many'

I also had to update the get method to post in this block to get past the error:
TypeError: Failed to execute 'fetch' on 'Window': Request with GET/HEAD method cannot have body.

@api.route("/restplus/make_a_widget")
    class WidgetResource(Resource):
        @accepts(
            "Doodad", dict(name="some_arg", type=str), schema=DoodadSchema, api=api
        )
        @responds("Widget", schema=WidgetSchema, api=api)
        def post(self):
            from flask import jsonify

            return request.parsed_obj

Support enveloping response

In flask-resplus marshall, I can use:

@api.marshal_with(User, envelope="data")

I don't find this in response. I would like to use something like:

@responds(schema=User, api=api, many=True, envlope='data')

I also can't do something like:

users = user_service.get_users()
return {"data": users}

My current workaround is to use @api.expect(User) (to include those param into swagger doc) and schema.dump()

    @api.expect(User)
    def get(self):
        """List all available users"""
        try:
            users = user_service.get_users()
            return {"data": user_schema.dump(users)}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.