python-injector / flask_injector

Adds Injector support to Flask.
BSD 3-Clause "New" or "Revised" License
276 stars 42 forks source link

Error while using flask-injector decorator and flask-apispec doc in Flask together. #77

Open pratik261199 opened 1 year ago

pratik261199 commented 1 year ago

I have upgraded my packages to: flask-2.2.2 injector-0.20.1 Flask-injector-0.14.1 apispec-6.0.2 flask-apispec-0.11.4

I'm using Flask-apispec to auto-generate api documentation, and I'm using injector library. both independently works well in my code but when I use them together, somehow @inject decorator doesn't work. and it throws the error missing positional argument. I tried to debug the code, in stack trace, it completely skips the inject decorator.

Here is a sample code

import marshmallow as ma
from flask_apispec import doc, marshal_with, use_kwargs
from injector import inject
from flask_injector import FlaskInjector
from injector import inject, singleton

def configure(binder):
    binder.bind(
        str,
        to="MyCat",
        scope=singleton,
    )

class Pet:
    def __init__(self, name, type):
        self.name = name
        self.type = type

class PetSchema(ma.Schema):
    name = ma.fields.Str()
    type = ma.fields.Str()

###

import flask
import flask.views

from flask_apispec import FlaskApiSpec, MethodResource

app = flask.Flask(__name__)
docs = FlaskApiSpec(app)

@doc(
    tags=['pets'],
    params={'pet_id': {'description': 'the pet name'}},
)
class CatResource(MethodResource):
    @inject
    def __init__(self, pet_name: str):
        self.pet_name = pet_name
        super().__init__()
    @marshal_with(PetSchema)
    def get(self, pet_id):
        return Pet(self.pet_name, 'cat')

    @marshal_with(PetSchema)
    def put(self, pet_id):
        return Pet('calici', 'cat')

app.add_url_rule('/cat/<pet_id>', view_func=CatResource.as_view('CatResource'))

# registering view
docs.register(CatResource, endpoint='CatResource')
FlaskInjector(app=app, modules=[configure])

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

Everything works well if I comment out the "docs.register(CatResource, endpoint='CatResource')"' Note: Everything was working fine before upgrading libraries to the latest

pratik261199 commented 1 year ago

Stack trace:

Traceback (most recent call last):
  File "/Users/pratikghodke/test_project.py", line 63, in <module>
    docs.register(CatResource, endpoint='CatResource')
  File "/Users/pratikghodke/.virtualenvs/test_env/lib/python3.8/site-packages/flask_apispec/extension.py", line 127, in register
    self._defer(self._register, target, endpoint, blueprint,
  File "/Users/pratikghodke/.virtualenvs/test_env/lib/python3.8/site-packages/flask_apispec/extension.py", line 71, in _defer
    bound()
  File "/Users/pratikghodke/.virtualenvs/test_env/lib/python3.8/site-packages/flask_apispec/extension.py", line 147, in _register
    paths = self.resource_converter.convert(
  File "/Users/pratikghodke/.virtualenvs/test_env/lib/python3.8/site-packages/flask_apispec/apidoc.py", line 39, in convert
    return [self.get_path(rule, target, **kwargs) for rule in rules]
  File "/Users/pratikghodke/.virtualenvs/test_env/lib/python3.8/site-packages/flask_apispec/apidoc.py", line 39, in <listcomp>
    return [self.get_path(rule, target, **kwargs) for rule in rules]
  File "/Users/pratikghodke/.virtualenvs/test_env/lib/python3.8/site-packages/flask_apispec/apidoc.py", line 43, in get_path
    parent = self.get_parent(target, **kwargs)
  File "/Users/pratikghodke/.virtualenvs/test_env/lib/python3.8/site-packages/flask_apispec/apidoc.py", line 144, in get_parent
    return resolve_resource(resource, **kwargs)
  File "/Users/pratikghodke/.virtualenvs/test_env/lib/python3.8/site-packages/flask_apispec/utils.py", line 10, in resolve_resource
    return resource(*resource_class_args, **resource_class_kwargs)
TypeError: __init__() missing 1 required positional argument: 'pet_name'
jstasiak commented 1 year ago

Hey @pratik261199, thank you for the code to reproduce this, this is a very thorough report.

Note: Everything was working fine before upgrading libraries to the latest

Do you maybe know the upgrade of which library broke your code?

pratik261199 commented 1 year ago

I upgraded

flask-2.2.2 previously 0.10.1
injector-0.20.1 previously 0.9.1
Flask-injector-0.14.0 previously 0.7.1
apispec-6.0.2 previously 3.2.0
flask-apispec-0.11.4 previously 0.8.5

I want flask-2.2.2; since it requires Flask injector >=0.13.0 I upgraded it to the latest i.e (0.14.0). tried downgrading it to 0.13.0 as well, still code is breaking.

pratik261199 commented 1 year ago

@jstasiak Have you got any work-around this issue?

jstasiak commented 1 year ago

Sorry, I don't know what the error is and why it happens. Pull requests are welcome if someone knows how to fix it.