diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 24eafbb2..dd976de8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,7 @@ Current - Ensure that exceptions raised in error handler, including programming errors, are logged (:issue:`705`, :pr:`706`) - Import the ABCs from 'collections.abc' instead of 'collections' by default as it is deprecated since Python3.7, and in 3.8 it will stop working. Python2.7 is still supported though. - Fix illegal characters in JSON references to model names (:issue:`651`) +- Support ``envelope`` parameter in Swagger documentation (:pr:`390`) 0.13.0 (2019-08-12) ------------------- @@ -21,7 +22,6 @@ Current - Per route Swagger documentation for multiple routes on a ``Resource`` - Fix Swagger `duplicate mapping key` problem from conflicts between response codes given as string or integer (:issue`661`) - 0.12.1 (2018-09-28) ------------------- diff --git a/flask_restplus/namespace.py b/flask_restplus/namespace.py index e9a0b980..9c1b7b57 100644 --- a/flask_restplus/namespace.py +++ b/flask_restplus/namespace.py @@ -240,7 +240,7 @@ def marshal_with(self, fields, as_list=False, code=HTTPStatus.OK, description=No def wrapper(func): doc = { 'responses': { - str(code): (description, [fields]) if as_list else (description, fields) + str(code): (description, [fields], kwargs) if as_list else (description, fields, kwargs) }, '__mask__': kwargs.get('mask', True), # Mask values can't be determined outside app context } diff --git a/flask_restplus/swagger.py b/flask_restplus/swagger.py index 2c61af3d..7c534b26 100644 --- a/flask_restplus/swagger.py +++ b/flask_restplus/swagger.py @@ -372,7 +372,7 @@ def register_errors(self): apidoc = getattr(handler, '__apidoc__', {}) self.process_headers(response, apidoc) if 'responses' in apidoc: - _, model = list(apidoc['responses'].values())[0] + _, model, _ = list(apidoc['responses'].values())[0] response['schema'] = self.serialize_schema(model) responses[exception.__name__] = not_none(response) return responses @@ -507,7 +507,11 @@ def responses_for(self, doc, method): else: responses[code] = {'description': description} if model: - responses[code]['schema'] = self.serialize_schema(model) + schema = self.serialize_schema(model) + envelope = kwargs.get('envelope') + if envelope: + schema = {'properties': {envelope: schema}} + responses[code]['schema'] = schema self.process_headers(responses[code], doc, method, kwargs.get('headers')) if 'model' in d: code = str(d.get('default_code', HTTPStatus.OK)) diff --git a/tests/test_swagger.py b/tests/test_swagger.py index d781334b..07337088 100644 --- a/tests/test_swagger.py +++ b/tests/test_swagger.py @@ -1752,6 +1752,38 @@ def get(self): } } + def test_marhsal_decorator_with_envelope(self, api, client): + person = api.model('Person', { + 'name': restplus.fields.String, + 'age': restplus.fields.Integer, + 'birthdate': restplus.fields.DateTime, + }) + + @api.route('/model-as-dict/') + class ModelAsDict(restplus.Resource): + @api.marshal_with(person, envelope='person') + def get(self): + return {} + + data = client.get_specs() + + assert 'definitions' in data + assert 'Person' in data['definitions'] + + responses = data['paths']['/model-as-dict/']['get']['responses'] + assert responses == { + '200': { + 'description': 'Success', + 'schema': { + 'properties': { + 'person': { + '$ref': '#/definitions/Person' + } + } + } + } + } + def test_model_as_flat_dict_with_marchal_decorator_list(self, api, client): fields = api.model('Person', { 'name': restplus.fields.String,