Skip to content

Commit 678e94d

Browse files
author
marat-ashraf
committed
Revert commit rXXXXXX, feat chaotic: use pydantic in jsonschema
commit_hash:17ef71ef6b70b3bb55e5d2254b0208688cfcba00
1 parent f764877 commit 678e94d

29 files changed

+304
-408
lines changed

.mapping.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@
191191
"chaotic/chaotic/cpp_names.py":"taxi/uservices/userver/chaotic/chaotic/cpp_names.py",
192192
"chaotic/chaotic/error.py":"taxi/uservices/userver/chaotic/chaotic/error.py",
193193
"chaotic/chaotic/front/__init__.py":"taxi/uservices/userver/chaotic/chaotic/front/__init__.py",
194-
"chaotic/chaotic/front/base_model.py":"taxi/uservices/userver/chaotic/chaotic/front/base_model.py",
195194
"chaotic/chaotic/front/parser.py":"taxi/uservices/userver/chaotic/chaotic/front/parser.py",
196195
"chaotic/chaotic/front/ref.py":"taxi/uservices/userver/chaotic/chaotic/front/ref.py",
197196
"chaotic/chaotic/front/ref_resolver.py":"taxi/uservices/userver/chaotic/chaotic/front/ref_resolver.py",

chaotic-openapi/chaotic_openapi/front/base_model.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,29 @@
1+
from typing import Any
2+
13
import pydantic
24

3-
from chaotic.front import base_model
45

5-
BaseModel = base_model.BaseModel
6+
class BaseModel(pydantic.BaseModel):
7+
model_config = pydantic.ConfigDict(extra='allow')
8+
_model_userver_tags: list[str] = []
9+
10+
def model_post_init(self, context: Any) -> None:
11+
super().model_post_init(context)
12+
13+
if not self.__pydantic_extra__:
14+
return
15+
for field in self.__pydantic_extra__:
16+
if field.startswith('x-taxi-py3'):
17+
continue
18+
if field.startswith('x-taxi-go-'):
19+
continue
20+
if field.startswith('x-taxi-') or field.startswith('x-usrv-'):
21+
assert field in self._model_userver_tags, f'Field {field} is not allowed in this context'
22+
continue
23+
24+
if field.startswith('x-'):
25+
continue
26+
raise Exception(f'Unknown field "{field}"')
627

728

829
class XMiddlewares(pydantic.BaseModel):
Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,39 @@
1-
from chaotic.front import parser
1+
import pydantic
22

3-
ERROR_MESSAGES = parser.ERROR_MESSAGES
3+
import chaotic.error
4+
5+
ERROR_MESSAGES = {
6+
'extra_forbidden': 'Extra fields are forbidden ({input})',
7+
'missing': 'Required field "{field}" is missing',
8+
'string_type': 'String type is expected, {input} is found',
9+
'bool_type': 'Boolean type is expected, {input} is found',
10+
'int_type': 'Integer type is expected, {input} is found',
11+
}
412

513

614
def missing_field_msg(field: str) -> str:
715
return ERROR_MESSAGES['missing'].format(field=field)
816

917

10-
convert_error = parser.convert_error
18+
def convert_error(full_filepath: str, schema_type: str, err: pydantic.ValidationError) -> chaotic.error.BaseError:
19+
assert len(err.errors()) >= 1
20+
21+
# show only the first error
22+
error = err.errors()[0]
23+
24+
if len(error['loc']) > 0:
25+
# the last location is the missing field name
26+
field = error['loc'][-1]
27+
else:
28+
field = ''
29+
30+
if error['type'] in ERROR_MESSAGES:
31+
msg = ERROR_MESSAGES[error['type']].format(**error, field=field)
32+
else:
33+
msg = error['msg']
34+
return chaotic.error.BaseError(
35+
full_filepath=full_filepath,
36+
infile_path='.'.join(map(str, error['loc'])),
37+
schema_type=schema_type,
38+
msg=msg,
39+
)

chaotic-openapi/chaotic_openapi/front/model.py

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import dataclasses
22
import enum
33
from typing import Any
4-
from typing import Callable
54
from typing import Optional
65
from typing import Union
76

@@ -157,45 +156,3 @@ class Service:
157156
headers: dict[str, Parameter] = dataclasses.field(default_factory=dict)
158157
requestBodies: dict[str, list[RequestBody]] = dataclasses.field(default_factory=dict)
159158
security: dict[str, Security] = dataclasses.field(default_factory=dict)
160-
161-
# For tests only
162-
def visit_all_schemas(
163-
self,
164-
callback: Callable[[types.Schema], None],
165-
) -> None:
166-
def callback2(child: types.Schema, _: types.Schema) -> None:
167-
callback(child)
168-
169-
def clear_response(response):
170-
for body2 in response.content.values():
171-
callback(body2.schema)
172-
body2.schema.visit_children(callback2)
173-
for header in response.headers.values():
174-
callback(header.schema)
175-
header.schema.visit_children(callback2)
176-
177-
for schema in self.schemas.values():
178-
callback(schema)
179-
schema.visit_children(callback2)
180-
for body in self.requestBodies.values():
181-
for b in body:
182-
callback(b.schema)
183-
b.schema.visit_children(callback2)
184-
for response in self.responses.values():
185-
clear_response(response)
186-
for parameter in self.parameters.values():
187-
callback(parameter.schema)
188-
parameter.schema.visit_children(callback2)
189-
190-
for operation in self.operations:
191-
if not isinstance(operation.requestBody, Ref):
192-
for body3 in operation.requestBody:
193-
callback(body3.schema)
194-
body3.schema.visit_children(callback2)
195-
for response2 in operation.responses.values():
196-
if isinstance(response2, Ref):
197-
continue
198-
clear_response(response2)
199-
for parameter in operation.parameters:
200-
callback(parameter.schema)
201-
parameter.schema.visit_children(callback2)

chaotic-openapi/chaotic_openapi/front/openapi.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Header(base_model.BaseModel):
4747
deprecated: bool = False
4848
allowEmptyValue: bool = False
4949

50-
style: Optional[Style] = pydantic.Field(default=None, strict=False)
50+
style: Optional[Style] = None
5151
explode: Optional[bool] = None
5252
allowReserved: bool = False
5353
schema_: Schema = pydantic.Field(alias='schema')
@@ -62,10 +62,10 @@ class MediaType(base_model.BaseModel):
6262
examples: dict[str, Any] = pydantic.Field(default_factory=dict)
6363
# encoding: dict[str, Encoding] = {}
6464

65-
x_non_std_type_reason: Optional[str] = pydantic.Field(
66-
default=None,
67-
validation_alias=pydantic.AliasChoices('x-taxi-non-std-type-reason', 'x-usrv-non-std-type-reason'),
68-
)
65+
_model_userver_tags: list[str] = [
66+
'x-taxi-non-std-type-reason',
67+
'x-usrv-non-std-type-reason',
68+
]
6969

7070

7171
# https://spec.openapis.org/oas/v3.0.0.html#reference-object
@@ -101,13 +101,13 @@ class QueryLogMode(str, enum.Enum):
101101
# https://spec.openapis.org/oas/v3.0.0.html#parameter-object
102102
class Parameter(base_model.BaseModel):
103103
name: str
104-
in_: In = pydantic.Field(alias='in', strict=False)
104+
in_: In = pydantic.Field(alias='in')
105105
description: Optional[str] = None
106106
required: bool = False
107107
deprecated: bool = False
108108
allowEmptyValue: bool = False
109109

110-
style: Optional[Style] = pydantic.Field(default=None, strict=False)
110+
style: Optional[Style] = None
111111
explode: Optional[bool] = None
112112
allowReserved: bool = False
113113
schema_: Schema = pydantic.Field(alias='schema')
@@ -127,7 +127,6 @@ class Parameter(base_model.BaseModel):
127127
x_query_log_mode: QueryLogMode = pydantic.Field(
128128
default=QueryLogMode.show,
129129
validation_alias=pydantic.AliasChoices('x-taxi-query-log-mode', 'x-usrv-query-log-mode'),
130-
strict=False,
131130
)
132131
x_explode_true_reason: str = pydantic.Field(
133132
default='',
@@ -202,10 +201,10 @@ class OAuthFlows(base_model.BaseModel):
202201

203202
# https://spec.openapis.org/oas/v3.0.0.html#security-scheme-object
204203
class SecurityScheme(base_model.BaseModel):
205-
type: SecurityType = pydantic.Field(strict=False)
204+
type: SecurityType
206205
description: Optional[str] = None
207206
name: Optional[str] = None
208-
in_: Optional[SecurityIn] = pydantic.Field(alias='in', default=None, strict=False)
207+
in_: Optional[SecurityIn] = pydantic.Field(alias='in', default=None)
209208
scheme_: Optional[str] = pydantic.Field(alias='scheme', default=None)
210209
bearerFormat: Optional[str] = None
211210
flows: Optional[OAuthFlows] = None
@@ -274,7 +273,6 @@ class Operation(base_model.BaseModel):
274273
x_query_log_mode: QueryLogMode = pydantic.Field(
275274
default=QueryLogMode.show,
276275
validation_alias=pydantic.AliasChoices('x-taxi-query-log-mode', 'x-usrv-query-log-mode'),
277-
strict=False,
278276
)
279277
x_client_codegen: bool = pydantic.Field(
280278
default=True,

chaotic-openapi/chaotic_openapi/front/parser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def parse_schema(self, schema: dict, full_filepath: str, full_vfilepath: str) ->
4343
try:
4444
parsed = parser(**schema)
4545
except pydantic.ValidationError as exc:
46-
raise errors.convert_error(self._state.full_filepath, '', parser.schema_type(), exc) from None
46+
raise errors.convert_error(full_filepath, parser.schema_type(), exc) from None
4747

4848
self._append_schema(parsed)
4949

@@ -636,11 +636,11 @@ def _parse_schema(self, schema: Any, infile_path: str, allow_file=False) -> Unio
636636

637637
if isinstance(schema_ref, types.Ref):
638638
ref_ = types.Ref(
639-
ref=chaotic_parser.SchemaParser._normalize_ref(schema_ref.ref),
639+
chaotic_parser.SchemaParser._normalize_ref(schema_ref.ref),
640640
indirect=schema_ref.indirect,
641641
self_ref=schema_ref.self_ref,
642642
)
643-
ref_.source_location_ = schema_ref.source_location_
643+
ref_._source_location = schema_ref._source_location # type: ignore
644644
return ref_
645645
else:
646646
return schema_ref

chaotic-openapi/chaotic_openapi/front/swagger.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class In(str, enum.Enum):
3131
# https://spec.openapis.org/oas/v2.0.html#parameter-object
3232
class Parameter(base_model.BaseModel):
3333
name: str
34-
in_: In = pydantic.Field(alias='in', strict=False)
34+
in_: In = pydantic.Field(alias='in')
3535
description: str = ''
3636
required: bool = False
3737

@@ -118,11 +118,11 @@ class OAuthFlow(str, enum.Enum):
118118

119119
# https://spec.openapis.org/oas/v2.0.html#security-definitions-object
120120
class SecurityDef(base_model.BaseModel):
121-
type: SecurityType = pydantic.Field(strict=False)
121+
type: SecurityType
122122
description: Optional[str] = None
123123
name: Optional[str] = None
124-
in_: Optional[SecurityIn] = pydantic.Field(alias='in', default=None, strict=False)
125-
flow: Optional[OAuthFlow] = pydantic.Field(default=None, strict=False)
124+
in_: Optional[SecurityIn] = pydantic.Field(alias='in', default=None)
125+
flow: Optional[OAuthFlow] = None
126126
authorizationUrl: Optional[str] = None
127127
tokenUrl: Optional[str] = None
128128
scopes: dict[str, str] = pydantic.Field(default_factory=dict)

chaotic-openapi/tests/back/conftest.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55

66
@pytest.fixture
77
def translate_single_schema():
8-
def clear_source_location(schema):
9-
schema.source_location_ = None
10-
118
def func(schema):
129
parser = front_parser.Parser('test')
1310
parser.parse_schema(schema, '<inline>', '<inline>')
@@ -20,7 +17,6 @@ def func(schema):
2017
include_dirs=[],
2118
middleware_plugins=[],
2219
)
23-
service.visit_all_schemas(clear_source_location)
2420
return tr.spec()
2521

2622
return func

chaotic-openapi/tests/back/test_parameters.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def test_parameters_schemas_ref(translate_single_schema):
182182
ref='<inline>#/components/schemas/Parameter',
183183
indirect=False,
184184
self_ref=False,
185-
schema_=chaotic_types.Integer(
185+
schema=chaotic_types.Integer(
186186
type='integer',
187187
),
188188
),
@@ -217,7 +217,7 @@ def test_parameters_schemas_ref(translate_single_schema):
217217
ref='<inline>#/components/schemas/Parameter',
218218
indirect=False,
219219
self_ref=False,
220-
schema_=chaotic_types.Integer(
220+
schema=chaotic_types.Integer(
221221
type='integer',
222222
default=None,
223223
nullable=False,

chaotic-openapi/tests/front/conftest.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,9 @@
44

55
@pytest.fixture
66
def simple_parser():
7-
def clear_source_location(schema):
8-
schema.source_location_ = None
9-
107
def _simple_parser(schema):
118
parser = front_parser.Parser('test')
129
parser.parse_schema(schema, '<inline>', '<inline>')
13-
parser.service().visit_all_schemas(clear_source_location)
1410
return parser.service()
1511

1612
return _simple_parser

0 commit comments

Comments
 (0)