noirbizarre / flask-restplus

Fully featured framework for fast, easy and documented API development with Flask
http://flask-restplus.readthedocs.org
Other
2.73k stars 507 forks source link

Swagger UI crashes when circular model defined #190

Open miszczu opened 8 years ago

miszczu commented 8 years ago

I have defined following circular model in my API:

tree_model = api.model('TreeModel', {
    'node': fields.Nested(node_model)
})
tree['children'] = fields.List(fields.Nested(tree_model), default=[])

Marshalling such model with api.marshal_with works ok, but app crashes when I try to open swagger documentation:

RecursionError: maximum recursion depth exceeded Fatal Python error: Cannot recover from stack overflow.

Current thread 0x00007f8731cf2700 (most recent call first): File "/home/karol/App/pycharm-2016.2/helpers/pydev/_pydevd_bundle/pydevd_trace_dispatch_regular.py", line 139 in call File "/home/karol/test-api/venv/lib/python3.5/site-packages/werkzeug/utils.py", line 68 in get File "/home/karol/test-api/venv/lib/python3.5/site-packages/flask_restplus/fields.py", line 207 in nested File "/home/karol/test-api/venv/lib/python3.5/site-packages/flask_restplus/swagger.py", line 468 in register_field File "/home/karol/test-api/venv/lib/python3.5/site-packages/flask_restplus/swagger.py", line 460 in register_model File "/home/karol/test-api/venv/lib/python3.5/site-packages/flask_restplus/swagger.py", line 468 in register_field File "/home/karol/test-api/venv/lib/python3.5/site-packages/flask_restplus/swagger.py", line 470 in register_field File "/home/karol/test-api/venv/lib/python3.5/site-packages/flask_restplus/swagger.py", line 460 in register_model File "/home/karol/test-api/venv/lib/python3.5/site-packages/flask_restplus/swagger.py", line 468 in register_field File "/home/karol/test-api/venv/lib/python3.5/site-packages/flask_restplus/swagger.py", line 470 in register_field ...

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

Swagger 2.0 accepts circular (recursive) models, so I think this library should handle such cases. Quick fix could be to just check if model is already registered in Swagger.register_model method.

I am using 0.9.2 version

edwardfung123 commented 7 years ago

Just in case someone is looking for a quick fix.

I follow @miszczu suggestion and patch the swagger.py. I didn't test it properly but so far it works for me.

--- venv/lib/python2.7/site-packages/flask_restplus/swagger.py  2016-12-15 04:43:48.177600793 +0000
+++ patched_flask_restplus_swagger2.py  2016-12-15 04:43:21.864703858 +0000
@@ -452,6 +452,8 @@
         if name not in self.api.models:
             raise ValueError('Model {0} not registered'.format(name))
         specs = self.api.models[name]
+        if name in self._registered_models:
+          return ref(model)
         self._registered_models[name] = specs
         if isinstance(specs, Model):
             for parent in specs.__parents__: