Skip to content

Commit ea47c84

Browse files
authored
Merge pull request #83 from khizunov/anton/add-extensions
feat: extensions support and add path parameters to operation params
2 parents c0c91ec + c7bd06e commit ea47c84

21 files changed

Lines changed: 295 additions & 30 deletions

src/openapi_parser/builders/external_doc.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22

3+
from .common import extract_extension_attributes
34
from ..specification import ExternalDoc
45

56
logger = logging.getLogger(__name__)
@@ -12,7 +13,11 @@ def build(data: dict) -> ExternalDoc:
1213

1314
attrs = {
1415
"url": data['url'],
15-
"description": data.get('description')
16+
"description": data.get('description'),
17+
"extensions": extract_extension_attributes(data),
1618
}
1719

20+
if attrs['extensions']:
21+
logger.debug(f"Extracted custom properties [{attrs['extensions'].keys()}]")
22+
1823
return ExternalDoc(**attrs)

src/openapi_parser/builders/header.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22

33
from . import SchemaFactory
4-
from .common import extract_typed_props, PropertyMeta
4+
from .common import extract_typed_props, PropertyMeta, extract_extension_attributes
55
from ..specification import Header
66

77
logger = logging.getLogger(__name__)
@@ -33,5 +33,9 @@ def _build(self, name: str, data: dict) -> Header:
3333
attrs = extract_typed_props(data, attrs_map)
3434

3535
attrs['name'] = name
36+
attrs["extensions"] = extract_extension_attributes(data)
37+
38+
if attrs['extensions']:
39+
logger.debug(f"Extracted custom properties [{attrs['extensions'].keys()}]")
3640

3741
return Header(**attrs)

src/openapi_parser/builders/info.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
22

3-
from .common import extract_typed_props, PropertyMeta
3+
from .common import extract_typed_props, PropertyMeta, extract_extension_attributes
44
from ..specification import Contact, Info, License
55

66
logger = logging.getLogger(__name__)
@@ -20,6 +20,10 @@ def build(self, data: dict) -> Info:
2020
}
2121

2222
attrs = extract_typed_props(data, attrs_map)
23+
attrs["extensions"] = extract_extension_attributes(data)
24+
25+
if attrs['extensions']:
26+
logger.debug(f"Extracted custom properties [{attrs['extensions'].keys()}]")
2327

2428
return Info(**attrs)
2529

src/openapi_parser/builders/oauth_flow.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22
from typing import Dict
33

4-
from .common import extract_typed_props, PropertyMeta
4+
from .common import extract_typed_props, PropertyMeta, extract_extension_attributes
55
from ..enumeration import OAuthFlowType
66
from ..specification import OAuthFlow
77

@@ -22,10 +22,18 @@ def build_collection(data: dict) -> Dict[OAuthFlowType, OAuthFlow]:
2222

2323
result_oauth_dict = {
2424
OAuthFlowType(oauth_type): OAuthFlow(
25+
extensions=extract_extension_attributes(oauth_value),
2526
**extract_typed_props(oauth_value, attrs_map)
2627
)
2728
for oauth_type, oauth_value
2829
in data.items()
30+
if not oauth_type.startswith("x-")
2931
}
3032

33+
extensions = extract_extension_attributes(data)
34+
if extensions:
35+
logger.debug(f"Extracted custom properties [{extensions.keys()}]")
36+
for extension in extensions.keys():
37+
result_oauth_dict[extension] = extensions[extension]
38+
3139
return result_oauth_dict

src/openapi_parser/builders/operation.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import Dict
33

44
from . import ExternalDocBuilder, ParameterBuilder, RequestBuilder, ResponseBuilder
5-
from .common import extract_typed_props, PropertyMeta
5+
from .common import extract_typed_props, PropertyMeta, extract_extension_attributes
66
from ..enumeration import OperationMethod
77
from ..specification import Operation, Response
88

@@ -42,6 +42,10 @@ def build(self, method: OperationMethod, data: dict) -> Operation:
4242
}
4343

4444
attrs = extract_typed_props(data, attrs_map)
45+
attrs['extensions'] = extract_extension_attributes(data)
46+
47+
if attrs['extensions']:
48+
logger.debug(f"Extracted custom properties [{attrs['extensions'].keys()}]")
4549

4650
attrs['method'] = method
4751

src/openapi_parser/builders/parameter.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import List
33

44
from . import SchemaFactory
5-
from .common import extract_typed_props, PropertyMeta
5+
from .common import extract_typed_props, PropertyMeta, extract_extension_attributes
66
from ..enumeration import ParameterLocation, HeaderParameterStyle, PathParameterStyle, QueryParameterStyle, \
77
CookieParameterStyle
88
from ..specification import Parameter
@@ -56,4 +56,9 @@ def build(self, data: dict) -> Parameter:
5656
if not attrs.get("explode") and attrs["style"].value == "form":
5757
attrs["explode"] = True
5858

59+
attrs['extensions'] = extract_extension_attributes(data)
60+
61+
if attrs['extensions']:
62+
logger.debug(f"Extracted custom properties [{attrs['extensions'].keys()}]")
63+
5964
return Parameter(**attrs)

src/openapi_parser/builders/path.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import Dict
33

44
from . import OperationBuilder, ParameterBuilder
5-
from .common import extract_typed_props, PropertyMeta
5+
from .common import extract_typed_props, PropertyMeta, extract_extension_attributes
66
from ..enumeration import OperationMethod
77
from ..specification import Path
88

@@ -42,4 +42,13 @@ def _build_path(self, url: str, data: dict) -> Path:
4242
if method.value in data
4343
]
4444

45+
if attrs.get("parameters"):
46+
for operation in attrs["operations"]:
47+
operation.parameters += attrs["parameters"]
48+
49+
attrs['extensions'] = extract_extension_attributes(data)
50+
51+
if attrs['extensions']:
52+
logger.debug(f"Extracted custom properties [{attrs['extensions'].keys()}]")
53+
4554
return Path(**attrs)

src/openapi_parser/builders/security.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
22

3-
from .common import extract_typed_props, PropertyMeta
3+
from .common import extract_typed_props, PropertyMeta, extract_extension_attributes
44
from .oauth_flow import OAuthFlowBuilder
55
from ..enumeration import AuthenticationScheme, BaseLocation, SecurityType
66
from ..specification import Security
@@ -29,6 +29,10 @@ def build(self, data: dict) -> Security:
2929
}
3030

3131
attrs = extract_typed_props(data, attrs_map)
32+
attrs['extensions'] = extract_extension_attributes(data)
33+
34+
if attrs['extensions']:
35+
logger.debug(f"Extracted custom properties [{attrs['extensions'].keys()}]")
3236

3337
return Security(**attrs)
3438

src/openapi_parser/builders/server.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import logging
22

3-
from .common import extract_typed_props, PropertyMeta
3+
from .common import extract_typed_props, PropertyMeta, extract_extension_attributes
44
from ..specification import Server
55

66
logger = logging.getLogger(__name__)
@@ -21,5 +21,9 @@ def _build_server(data: dict) -> Server:
2121
}
2222

2323
attrs = extract_typed_props(data, attrs_map)
24+
attrs['extensions'] = extract_extension_attributes(data)
25+
26+
if attrs['extensions']:
27+
logger.debug(f"Extracted custom properties [{attrs['extensions'].keys()}]")
2428

2529
return Server(**attrs)

src/openapi_parser/specification.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class Contact:
2121
class License:
2222
name: str
2323
url: Optional[str] = None
24+
extensions: Optional[dict] = field(default_factory=dict)
2425

2526

2627
@dataclass
@@ -31,19 +32,22 @@ class Info:
3132
terms_of_service: Optional[str] = None
3233
contact: Optional[Contact] = None
3334
license: Optional[License] = None
35+
extensions: Optional[dict] = field(default_factory=dict)
3436

3537

3638
@dataclass
3739
class Server:
3840
url: str
3941
description: Optional[str] = None
4042
variables: Optional[dict] = field(default_factory=dict)
43+
extensions: Optional[dict] = field(default_factory=dict)
4144

4245

4346
@dataclass
4447
class ExternalDoc:
4548
url: str
4649
description: Optional[str] = None
50+
extensions: Optional[dict] = field(default_factory=dict)
4751

4852

4953
@dataclass
@@ -157,6 +161,7 @@ class Parameter:
157161
deprecated: Optional[bool] = field(default=False)
158162
style: Optional[str] = None
159163
explode: Optional[bool] = field(default=False)
164+
extensions: Optional[dict] = field(default_factory=dict)
160165

161166

162167
@dataclass
@@ -182,6 +187,7 @@ class Header:
182187
description: Optional[str] = None
183188
required: Optional[bool] = field(default=False)
184189
deprecated: Optional[bool] = field(default=False)
190+
extensions: Optional[dict] = field(default_factory=dict)
185191

186192

187193
@dataclass
@@ -200,6 +206,7 @@ class OAuthFlow:
200206
authorization_url: Optional[str] = None
201207
token_url: Optional[str] = None
202208
scopes: dict[str, str] = field(default_factory=dict)
209+
extensions: Optional[dict] = field(default_factory=dict)
203210

204211

205212
@dataclass
@@ -212,6 +219,7 @@ class Security:
212219
bearer_format: Optional[str] = None
213220
flows: dict[OAuthFlowType, OAuthFlow] = field(default_factory=dict)
214221
url: Optional[str] = None
222+
extensions: Optional[dict] = field(default_factory=dict)
215223

216224

217225
@dataclass
@@ -227,6 +235,7 @@ class Operation:
227235
parameters: list[Parameter] = field(default_factory=list)
228236
tags: list[str] = field(default_factory=list)
229237
security: list[dict[str, Any]] = field(default_factory=list)
238+
extensions: Optional[dict] = field(default_factory=dict)
230239
# callbacks: dict[str, Callback] = field(default_factory=dict) # TODO
231240

232241

@@ -237,6 +246,7 @@ class Path:
237246
description: Optional[str] = None
238247
operations: list[Operation] = field(default_factory=list)
239248
parameters: list[Parameter] = field(default_factory=list)
249+
extensions: Optional[dict] = field(default_factory=dict)
240250

241251

242252
@dataclass
@@ -257,3 +267,4 @@ class Specification:
257267
schemas: dict[str, Schema] = field(default_factory=dict)
258268
external_docs: Optional[ExternalDoc] = None
259269
paths: list[Path] = field(default_factory=list)
270+
extensions: Optional[dict] = field(default_factory=dict)

0 commit comments

Comments
 (0)