Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse extended operation description #73

Merged
merged 1 commit into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apistrap/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,10 @@ def _extract_operation_spec(self, route: AbstractRoute) -> dict:
handler = getattr(route.handler, self.SYNTHETIC_WRAPPER_ATTR, route.handler)

specs_dict = deepcopy(getattr(handler, "specs_dict", {"parameters": [], "responses": {}}))
specs_dict["summary"] = self._summary_from_docblock(handler.__doc__)
specs_dict["operationId"] = snake_to_camel(handler.__name__)

self._descriptions_from_docblock(handler.__doc__, specs_dict)

signature = inspect.signature(handler)
param_doc = self._parameters_from_docblock(handler.__doc__)

Expand Down
17 changes: 9 additions & 8 deletions apistrap/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,20 +160,21 @@ def _is_route_ignored(self, method: str, handler) -> bool:
def _parameter_annotation_to_openapi_type(self, annotation):
return self.PARAMETER_TYPE_MAP.get(annotation, "string")

def _summary_from_docblock(self, docblock: Optional[str]) -> str:
if docblock is None:
return ""

return parse_doc(docblock).short_description

def _parameters_from_docblock(self, docblock: Optional[str]) -> Dict[str, str]:
if docblock is None:
return {}

return {
param.arg_name: param.description for param in parse_doc(docblock).params if param.description.strip() != ""
}

def _descriptions_from_docblock(self, docblock: Optional[str], target: dict):
if docblock is None:
return {}

parsed = parse_doc(docblock)

target["summary"] = parsed.short_description
target["description"] = parsed.long_description

############################
# Configuration properties #
############################
Expand Down
4 changes: 3 additions & 1 deletion apistrap/flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ def _extract_operation_specs(self, handler):
"""

specs_dict = deepcopy(getattr(handler, "specs_dict", {"parameters": [], "responses": {}}))
specs_dict["summary"] = self._summary_from_docblock(handler.__doc__)

self._descriptions_from_docblock(handler.__doc__, specs_dict)

specs_dict["operationId"] = snake_to_camel(handler.__name__)

signature = inspect.signature(handler)
Expand Down
20 changes: 20 additions & 0 deletions tests/test_aiohttp_docblocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ async def view(param_a: str, param_b: int):
"b": param_b
}))

@routes.get('/extended')
async def view_extended():
"""
A summary.

An extended description.
"""

app.add_routes(routes)

yield app
Expand Down Expand Up @@ -57,3 +65,15 @@ async def test_parameters_from_docblock(app_with_params_as_args, aiohttp_initial

assert param_a["description"] == "Parameter A"
assert param_b["description"] == "Parameter B"


async def test_extended_description_from_docblock(app_with_params_as_args, aiohttp_initialized_client):
client = await aiohttp_initialized_client(app_with_params_as_args)
response = await client.get("/spec.json")

assert response.status == 200
data = await response.json()
path = data["paths"]["/extended"]["get"]

assert path["summary"] == "A summary."
assert path["description"] == "An extended description."
18 changes: 18 additions & 0 deletions tests/test_flask_docblocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ def view(param_a: str, param_b: int):
"b": param_b
})

@app.route('/extended', methods=["get"])
def view_extended():
"""
A summary.

An extended description.
"""

yield app


Expand All @@ -41,3 +49,13 @@ def test_parameters_from_docblock(app_with_params_as_args, client):

assert param_a["description"] == "Parameter A"
assert param_b["description"] == "Parameter B"


def test_extended_description_from_docblock(app_with_params_as_args, client):
response = client.get("/spec.json")

assert response.status_code == 200
path = response.json["paths"]["/extended"]["get"]

assert path["summary"] == "A summary."
assert path["description"] == "An extended description."