Skip to content

Commit 3bf3ae4

Browse files
committed
feat chaotic: allow non-userver tags
commit_hash:9b1cad51c0fe0d11ff96088594783942a42aec95
1 parent bb8a9a4 commit 3bf3ae4

6 files changed

Lines changed: 93 additions & 27 deletions

File tree

.mapping.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"chaotic-openapi/chaotic_openapi/back/linter/__main__.py":"taxi/uservices/userver/chaotic-openapi/chaotic_openapi/back/linter/__main__.py",
6161
"chaotic-openapi/chaotic_openapi/back/linter/validators.py":"taxi/uservices/userver/chaotic-openapi/chaotic_openapi/back/linter/validators.py",
6262
"chaotic-openapi/chaotic_openapi/front/__init__.py":"taxi/uservices/userver/chaotic-openapi/chaotic_openapi/front/__init__.py",
63+
"chaotic-openapi/chaotic_openapi/front/base_model.py":"taxi/uservices/userver/chaotic-openapi/chaotic_openapi/front/base_model.py",
6364
"chaotic-openapi/chaotic_openapi/front/errors.py":"taxi/uservices/userver/chaotic-openapi/chaotic_openapi/front/errors.py",
6465
"chaotic-openapi/chaotic_openapi/front/model.py":"taxi/uservices/userver/chaotic-openapi/chaotic_openapi/front/model.py",
6566
"chaotic-openapi/chaotic_openapi/front/openapi.py":"taxi/uservices/userver/chaotic-openapi/chaotic_openapi/front/openapi.py",
@@ -107,6 +108,7 @@
107108
"chaotic-openapi/integration_tests/clients/multiple-content-types/openapi.yaml":"taxi/uservices/userver/chaotic-openapi/integration_tests/clients/multiple-content-types/openapi.yaml",
108109
"chaotic-openapi/integration_tests/clients/parameters/openapi.yaml":"taxi/uservices/userver/chaotic-openapi/integration_tests/clients/parameters/openapi.yaml",
109110
"chaotic-openapi/integration_tests/clients/swagger/swagger.yaml":"taxi/uservices/userver/chaotic-openapi/integration_tests/clients/swagger/swagger.yaml",
111+
"chaotic-openapi/integration_tests/clients/tags/openapi.yaml":"taxi/uservices/userver/chaotic-openapi/integration_tests/clients/tags/openapi.yaml",
110112
"chaotic-openapi/integration_tests/clients/test-middleware/openapi.yaml":"taxi/uservices/userver/chaotic-openapi/integration_tests/clients/test-middleware/openapi.yaml",
111113
"chaotic-openapi/integration_tests/clients/test-object/openapi.yaml":"taxi/uservices/userver/chaotic-openapi/integration_tests/clients/test-object/openapi.yaml",
112114
"chaotic-openapi/integration_tests/src/middleware_test.cpp":"taxi/uservices/userver/chaotic-openapi/integration_tests/src/middleware_test.cpp",
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from typing import Any
2+
from typing import List
3+
4+
import pydantic
5+
6+
7+
class BaseModel(pydantic.BaseModel):
8+
model_config = pydantic.ConfigDict(extra='allow')
9+
_model_userver_tags: List[str] = []
10+
11+
def model_post_init(self, __context: Any) -> None:
12+
if not self.__pydantic_extra__:
13+
return
14+
for field in self.__pydantic_extra__:
15+
if field.startswith('x-taxi-') or field.startswith('x-usrv-'):
16+
assert field in self._model_userver_tags, f'Field {field} is not allowed in this context'
17+
# ignore any other tag

chaotic-openapi/chaotic_openapi/front/openapi.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77

88
import pydantic
99

10+
from . import base_model
1011
from . import errors
1112

1213

1314
# https://spec.openapis.org/oas/v3.0.0.html#info-object
14-
class Info(pydantic.BaseModel):
15+
class Info(base_model.BaseModel):
1516
title: str
1617
description: Optional[str] = None
1718
termsOfService: Optional[str] = None
@@ -21,7 +22,7 @@ class Info(pydantic.BaseModel):
2122

2223

2324
# https://spec.openapis.org/oas/v3.0.0.html#server-object
24-
class Server(pydantic.BaseModel):
25+
class Server(base_model.BaseModel):
2526
url: str
2627
description: Optional[str] = None
2728
variables: Dict[str, Any] = pydantic.Field(default_factory=dict)
@@ -42,7 +43,7 @@ class Style(str, enum.Enum):
4243

4344

4445
# https://spec.openapis.org/oas/v3.0.0.html#header-object
45-
class Header(pydantic.BaseModel):
46+
class Header(base_model.BaseModel):
4647
description: Optional[str] = None
4748
required: bool = False
4849
deprecated: bool = False
@@ -57,20 +58,20 @@ class Header(pydantic.BaseModel):
5758

5859

5960
# https://spec.openapis.org/oas/v3.0.0.html#media-type-object
60-
class MediaType(pydantic.BaseModel):
61+
class MediaType(base_model.BaseModel):
6162
schema_: Schema = pydantic.Field(alias='schema', default=None)
6263
example: Any = None
6364
examples: Dict[str, Any] = pydantic.Field(default_factory=dict)
6465
# encoding: Dict[str, Encoding] = {}
6566

6667

6768
# https://spec.openapis.org/oas/v3.0.0.html#reference-object
68-
class Ref(pydantic.BaseModel):
69+
class Ref(base_model.BaseModel):
6970
ref: str = pydantic.Field(alias='$ref')
7071

7172

7273
# https://spec.openapis.org/oas/v3.0.0.html#responses-object
73-
class Response(pydantic.BaseModel):
74+
class Response(base_model.BaseModel):
7475
description: str
7576
headers: Dict[str, Union[Header, Ref]] = pydantic.Field(default_factory=dict)
7677
content: Dict[str, MediaType] = pydantic.Field(default_factory=dict)
@@ -85,7 +86,7 @@ class In(str, enum.Enum):
8586

8687

8788
# https://spec.openapis.org/oas/v3.0.0.html#parameter-object
88-
class Parameter(pydantic.BaseModel):
89+
class Parameter(base_model.BaseModel):
8990
name: str
9091
in_: In = pydantic.Field(alias='in')
9192
description: Optional[str] = None
@@ -115,7 +116,7 @@ def model_post_init(self, context: Any, /) -> None:
115116

116117

117118
# https://spec.openapis.org/oas/v3.0.0.html#request-body-object
118-
class RequestBody(pydantic.BaseModel):
119+
class RequestBody(base_model.BaseModel):
119120
description: Optional[str] = None
120121
content: Dict[str, MediaType]
121122
required: bool = False
@@ -134,41 +135,41 @@ class SecurityIn(str, enum.Enum):
134135
cookie = 'cookie'
135136

136137

137-
class ImplicitFlow(pydantic.BaseModel):
138+
class ImplicitFlow(base_model.BaseModel):
138139
refreshUrl: Optional[str] = None
139140
scopes: Dict[str, str] = pydantic.Field(default_factory=dict)
140141
authorizationUrl: str
141142

142143

143-
class PasswordFlow(pydantic.BaseModel):
144+
class PasswordFlow(base_model.BaseModel):
144145
refreshUrl: Optional[str] = None
145146
scopes: Dict[str, str] = pydantic.Field(default_factory=dict)
146147
tokenUrl: str
147148

148149

149-
class ClientCredFlow(pydantic.BaseModel):
150+
class ClientCredFlow(base_model.BaseModel):
150151
refreshUrl: Optional[str] = None
151152
scopes: Dict[str, str] = pydantic.Field(default_factory=dict)
152153
tokenUrl: str
153154

154155

155-
class AuthCodeFlow(pydantic.BaseModel):
156+
class AuthCodeFlow(base_model.BaseModel):
156157
refreshUrl: Optional[str] = None
157158
scopes: Dict[str, str] = pydantic.Field(default_factory=dict)
158159
authorizationUrl: str
159160
tokenUrl: str
160161

161162

162163
# https://spec.openapis.org/oas/v3.0.0.html#oauth-flows-object
163-
class OAuthFlows(pydantic.BaseModel):
164+
class OAuthFlows(base_model.BaseModel):
164165
implicit: Optional[ImplicitFlow] = None
165166
password: Optional[PasswordFlow] = None
166167
clientCredentials: Optional[ClientCredFlow] = None
167168
authorizationCode: Optional[AuthCodeFlow] = None
168169

169170

170171
# https://spec.openapis.org/oas/v3.0.0.html#security-scheme-object
171-
class SecurityScheme(pydantic.BaseModel):
172+
class SecurityScheme(base_model.BaseModel):
172173
type: SecurityType
173174
description: Optional[str] = None
174175
name: Optional[str] = None
@@ -203,7 +204,7 @@ def model_post_init(self, context: Any, /) -> None:
203204

204205

205206
# https://spec.openapis.org/oas/v3.0.0.html#components-object
206-
class Components(pydantic.BaseModel):
207+
class Components(base_model.BaseModel):
207208
schemas: Dict[str, Schema] = pydantic.Field(default_factory=dict)
208209
responses: Dict[str, Response] = pydantic.Field(default_factory=dict)
209210
parameters: Dict[str, Parameter] = pydantic.Field(default_factory=dict)
@@ -213,7 +214,7 @@ class Components(pydantic.BaseModel):
213214

214215

215216
# https://spec.openapis.org/oas/v3.0.0.html#operation-object
216-
class Operation(pydantic.BaseModel):
217+
class Operation(base_model.BaseModel):
217218
tags: List[str] = pydantic.Field(default_factory=list)
218219
summary: Optional[str] = None
219220
description: str = ''
@@ -229,7 +230,7 @@ class Operation(pydantic.BaseModel):
229230

230231

231232
# https://spec.openapis.org/oas/v3.0.0.html#path-item-object
232-
class Path(pydantic.BaseModel):
233+
class Path(base_model.BaseModel):
233234
summary: Optional[str] = None
234235
description: str = ''
235236

@@ -247,7 +248,7 @@ class Path(pydantic.BaseModel):
247248

248249

249250
# https://spec.openapis.org/oas/v3.0.0.html#schema
250-
class OpenApi(pydantic.BaseModel):
251+
class OpenApi(base_model.BaseModel):
251252
openapi: str = '3.0.0'
252253
info: Optional[Info] = None
253254
servers: List[Server] = pydantic.Field(default_factory=list)

chaotic-openapi/chaotic_openapi/front/swagger.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@
77

88
import pydantic
99

10+
from . import base_model
1011
from . import errors
1112

1213

13-
class Info(pydantic.BaseModel):
14+
class Info(base_model.BaseModel):
1415
pass
1516

1617

1718
# https://spec.openapis.org/oas/v2.0.html#reference-object
18-
class Ref(pydantic.BaseModel):
19+
class Ref(base_model.BaseModel):
1920
ref: str = pydantic.Field(alias='$ref')
2021

2122

@@ -28,7 +29,7 @@ class In(str, enum.Enum):
2829

2930

3031
# https://spec.openapis.org/oas/v2.0.html#parameter-object
31-
class Parameter(pydantic.BaseModel):
32+
class Parameter(base_model.BaseModel):
3233
name: str
3334
in_: In = pydantic.Field(alias='in')
3435
description: str = ''
@@ -60,7 +61,7 @@ def model_post_init(self, context: Any, /) -> None:
6061

6162

6263
# https://spec.openapis.org/oas/v2.0.html#header-object
63-
class Header(pydantic.BaseModel):
64+
class Header(base_model.BaseModel):
6465
description: Optional[str] = None
6566
type: str
6667
format: Optional[str] = None
@@ -82,7 +83,7 @@ def model_post_init(self, context: Any, /) -> None:
8283

8384

8485
# https://spec.openapis.org/oas/v2.0.html#response-object
85-
class Response(pydantic.BaseModel):
86+
class Response(base_model.BaseModel):
8687
description: str
8788
schema_: Schema = pydantic.Field(alias='schema', default=None)
8889
headers: Dict[str, Header] = pydantic.Field(default_factory=dict)
@@ -111,7 +112,7 @@ class OAuthFlow(str, enum.Enum):
111112

112113

113114
# https://spec.openapis.org/oas/v2.0.html#security-definitions-object
114-
class SecurityDef(pydantic.BaseModel):
115+
class SecurityDef(base_model.BaseModel):
115116
type: SecurityType
116117
description: Optional[str] = None
117118
name: Optional[str] = None
@@ -153,7 +154,7 @@ def model_post_init(self, context: Any, /) -> None:
153154

154155

155156
# https://spec.openapis.org/oas/v2.0.html#operation-object
156-
class Operation(pydantic.BaseModel):
157+
class Operation(base_model.BaseModel):
157158
tags: Optional[List[str]] = None
158159
summary: Optional[str] = None
159160
description: str = ''
@@ -169,7 +170,7 @@ class Operation(pydantic.BaseModel):
169170

170171

171172
# https://spec.openapis.org/oas/v2.0.html#paths-object
172-
class Path(pydantic.BaseModel):
173+
class Path(base_model.BaseModel):
173174
get: Optional[Operation] = None
174175
post: Optional[Operation] = None
175176
put: Optional[Operation] = None
@@ -184,7 +185,7 @@ class Path(pydantic.BaseModel):
184185

185186

186187
# https://spec.openapis.org/oas/v2.0.html#schema
187-
class Swagger(pydantic.BaseModel):
188+
class Swagger(base_model.BaseModel):
188189
swagger: str = '2.0'
189190
info: Optional[Info] = None
190191
host: Optional[str] = None
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
openapi: 3.0.0
2+
info:
3+
title: test-object client
4+
version: '1.0'
5+
6+
paths:
7+
/test1:
8+
x-tag: test
9+
post:
10+
responses:
11+
'200':
12+
description: OK
13+
content:
14+
application/json:
15+
schema:
16+
type: object
17+
additionalProperties: false
18+
properties: {}
19+
components: {}

chaotic-openapi/tests/front/test_openapi.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from chaotic_openapi.front import model
2+
import pytest
23

4+
from chaotic import error
35
from chaotic.front import types
46

57

@@ -356,3 +358,27 @@ def test_openapi_parameters(simple_parser):
356358
)
357359
],
358360
)
361+
362+
363+
def test_unknown_usrv_tag(simple_parser):
364+
expected = """
365+
===============================================================
366+
Unhandled error while processing <inline>
367+
Path "paths./.get", Format "openapi"
368+
Error:
369+
Assertion failed, Field x-usrv-tag is not allowed in this context
370+
==============================================================="""
371+
372+
with pytest.raises(error.BaseError, match=expected):
373+
simple_parser({
374+
'openapi': '3.0.0',
375+
'info': {'title': '', 'version': '1.0'},
376+
'paths': {
377+
'/': {
378+
'get': {
379+
'x-usrv-tag': '1',
380+
'responses': {},
381+
},
382+
},
383+
},
384+
})

0 commit comments

Comments
 (0)