Skip to content

Commit 43ad8a2

Browse files
Fix/path item handling (#53)
* Fix #5 - Fix bug in `MARKDOWN` view for `servers` (displaying twice the `description` instead of `description` and `url`). - Fix bug happening when a `path item` includes properties that are not of kind `operation item` (Neoteroi/mkdocs-plugins#5). - Add support for handling `parameters` defined on `path items` (common parameters for all operation under a certain path). Refer to the [`Path Item` specification](https://swagger.io/specification/#path-item-object). * Handle non-str param name property * Add Python 3.13 to the build matrix * Update requirements.txt
1 parent 5bafa37 commit 43ad8a2

File tree

11 files changed

+901
-15
lines changed

11 files changed

+901
-15
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
strategy:
2727
fail-fast: false
2828
matrix:
29-
python-version: [3.9, "3.10", "3.11", "3.12"]
29+
python-version: [3.9, "3.10", "3.11", "3.12", "3.13"]
3030

3131
steps:
3232
- uses: actions/checkout@v1

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.1.1] - 2025-03-20
9+
10+
- Fix bug in `MARKDOWN` view for `servers` (displaying twice the `description`
11+
instead of `description` and `url`).
12+
- Fix bug happening when a `path item` includes properties that are not of kind
13+
`operation item` (https://github.com/Neoteroi/mkdocs-plugins/issues/5).
14+
- Add support for handling `parameters` defined on `path items` (common
15+
parameters for all operation under a certain path).
16+
Refer to the [`Path Item` specification](https://swagger.io/specification/#path-item-object).
17+
- Fix bug happening when a parameter has a non-str `name` property.
18+
- Add Python 3.13 to the build matrix.
19+
820
## [1.1.0] - 2025-01-18
921

1022
- Add additionalProperties to Schema object, by @tyzhnenko.

openapidocs/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version__ = "1.1.0"
1+
__version__ = "1.1.1"
22
VERSION = __version__

openapidocs/mk/v3/__init__.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ def get_operations(self):
178178
paths = data["paths"]
179179

180180
for path, path_item in paths.items():
181+
if not isinstance(path_item, dict):
182+
continue
181183
tag = self.get_tag(path_item) or ""
182184

183185
for operation in path_item.values():
@@ -186,11 +188,32 @@ def get_operations(self):
186188
operation["requestBody"] = self._resolve_opt_ref(
187189
operation["requestBody"]
188190
)
189-
190-
groups[tag].append((path, path_item))
191+
groups[tag].append((path, self._keep_operations(path_item)))
191192

192193
return groups
193194

195+
def _keep_operations(self, path_item):
196+
# discard dictionary keys that are not of dict type
197+
198+
# if the path item defines common parameters, merge them into each operation:
199+
# https://swagger.io/specification/#path-item-object
200+
common_parameters = path_item.get("parameters", [])
201+
# Note: we don't need to resolve $ref here, because they are resolved in
202+
# get_parameters
203+
204+
return {
205+
key: self._merge_common_parameters(value, common_parameters)
206+
for key, value in path_item.items()
207+
if isinstance(value, dict)
208+
}
209+
210+
def _merge_common_parameters(self, operation, common_parameters):
211+
if not common_parameters:
212+
return operation
213+
data = copy.deepcopy(operation)
214+
data["parameters"] = common_parameters + data.get("parameters", [])
215+
return data
216+
194217
def get_schemas(self):
195218
schemas = read_dict(self.doc, "components", "schemas")
196219

@@ -215,8 +238,12 @@ def get_tag(self, path_item) -> Optional[str]:
215238
"""
216239
single_tag: Optional[str] = None
217240

218-
for operation in path_item.values():
219-
tags = operation.get("tags")
241+
for prop in path_item.values():
242+
if not isinstance(prop, dict):
243+
# This property is not an operation; in this context we ignore it.
244+
# See Path Item Object here: https://swagger.io/specification/
245+
continue
246+
tags = prop.get("tags")
220247

221248
if not tags:
222249
continue
@@ -383,6 +410,11 @@ def _resolve_opt_ref(self, obj):
383410
return self.resolve_reference(obj)
384411
return obj
385412

413+
def _lower(self, obj):
414+
if isinstance(obj, str):
415+
return obj.lower()
416+
return str(obj)
417+
386418
def get_parameters(self, operation) -> List[dict]:
387419
"""
388420
Returns a list of objects describing the input parameters for a given operation.
@@ -397,7 +429,7 @@ def get_parameters(self, operation) -> List[dict]:
397429
param
398430
for param in sorted(
399431
parameters,
400-
key=lambda x: x["name"].lower() if (x and "name" in x) else "",
432+
key=lambda x: self._lower(x["name"]) if (x and "name" in x) else "",
401433
)
402434
if param
403435
]

openapidocs/mk/v3/views_markdown/partial/servers.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
{% with rows = [[texts.description, texts.url]] %}
55
{%- for server in servers -%}
6-
{%- set _ = rows.append([server.description, server.description]) -%}
6+
{%- set _ = rows.append([server.description, server.url]) -%}
77
{%- endfor -%}
88
{{ rows | table }}
99
{%- endwith -%}

requirements.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,13 @@ pathspec==0.11.2
2626
platformdirs==4.0.0
2727
pluggy==1.3.0
2828
pycodestyle==2.11.1
29-
pydantic==2.5.1
30-
pydantic_core==2.14.3
29+
pydantic==2.10.6
3130
pyflakes==3.1.0
3231
Pygments==2.17.1
3332
pytest==7.4.3
3433
pytest-cov==4.1.0
3534
PyYAML==6.0.1
3635
rich==13.7.0
3736
sniffio==1.3.0
38-
typing_extensions==4.8.0
37+
typing_extensions>=4.8.0
3938
Werkzeug==3.0.1

tests/res/example1-output-plain.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ Optional multiline or single-line description in
2020

2121
## Servers
2222

23-
| Description | URL |
24-
| ----------------- | ----------------- |
25-
| Production server | Production server |
23+
| Description | URL |
24+
| ----------------- | ------------------------------------------- |
25+
| Production server | https://www.neoteroi.xyz/software-center/v1 |
2626

2727

2828
## Blobs

tests/res/example8-openapi.yaml

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
openapi: 3.0.0
2+
info:
3+
version: 1.0.0
4+
title: Swagger Petstore
5+
license:
6+
name: MIT
7+
servers:
8+
- url: http://petstore.swagger.io/v1
9+
description: Petstore server
10+
paths:
11+
/pets:
12+
summary: Everything about pets
13+
description: This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).
14+
parameters:
15+
- name: X-Country
16+
in: header
17+
description: Country code.
18+
required: false
19+
schema:
20+
type: string
21+
default: PL
22+
get:
23+
summary: List all pets
24+
operationId: listPets
25+
tags:
26+
- pets
27+
parameters:
28+
- name: limit
29+
in: query
30+
description: How many items to return at one time (max 100)
31+
required: false
32+
schema:
33+
type: integer
34+
format: int32
35+
default: 100
36+
responses:
37+
"200":
38+
description: A paged array of pets
39+
headers:
40+
x-next:
41+
description: A link to the next page of responses
42+
schema:
43+
type: string
44+
content:
45+
application/json:
46+
schema:
47+
$ref: "#/components/schemas/Pets"
48+
default:
49+
description: unexpected error
50+
content:
51+
application/json:
52+
schema:
53+
$ref: "#/components/schemas/Error"
54+
post:
55+
summary: Create a pet
56+
operationId: createPets
57+
tags:
58+
- pets
59+
responses:
60+
"201":
61+
description: Null response
62+
default:
63+
description: unexpected error
64+
content:
65+
application/json:
66+
schema:
67+
$ref: "#/components/schemas/Error"
68+
/pets/{petId}:
69+
get:
70+
summary: Info for a specific pet
71+
operationId: showPetById
72+
tags:
73+
- pets
74+
parameters:
75+
- name: petId
76+
in: path
77+
required: true
78+
description: The id of the pet to retrieve
79+
schema:
80+
type: string
81+
responses:
82+
"200":
83+
description: Expected response to a valid request
84+
content:
85+
application/json:
86+
schema:
87+
$ref: "#/components/schemas/Pet"
88+
default:
89+
description: unexpected error
90+
content:
91+
application/json:
92+
schema:
93+
$ref: "#/components/schemas/Error"
94+
components:
95+
schemas:
96+
Pet:
97+
type: object
98+
required:
99+
- id
100+
- name
101+
properties:
102+
id:
103+
type: integer
104+
format: int64
105+
name:
106+
type: string
107+
tag:
108+
type: string
109+
Pets:
110+
type: array
111+
items:
112+
$ref: "#/components/schemas/Pet"
113+
PetsIds:
114+
type: array
115+
items:
116+
type: integer
117+
format: int64
118+
Error:
119+
type: object
120+
required:
121+
- code
122+
- message
123+
properties:
124+
code:
125+
type: integer
126+
format: int32
127+
message:
128+
type: string

0 commit comments

Comments
 (0)