jentic-openapi-datamodels 1.0.0a18__py3-none-any.whl → 1.0.0a19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jentic/apitools/openapi/datamodels/low/extractors.py +3 -3
- jentic/apitools/openapi/datamodels/low/v30/__init__.py +76 -0
- jentic/apitools/openapi/datamodels/low/v30/builders/__init__.py +312 -0
- jentic/apitools/openapi/datamodels/low/v30/callback.py +131 -0
- jentic/apitools/openapi/datamodels/low/v30/components.py +236 -0
- jentic/apitools/openapi/datamodels/low/v30/contact.py +4 -10
- jentic/apitools/openapi/datamodels/low/v30/discriminator.py +4 -9
- jentic/apitools/openapi/datamodels/low/v30/encoding.py +81 -0
- jentic/apitools/openapi/datamodels/low/v30/example.py +91 -0
- jentic/apitools/openapi/datamodels/low/v30/external_documentation.py +4 -10
- jentic/apitools/openapi/datamodels/low/v30/header.py +120 -0
- jentic/apitools/openapi/datamodels/low/v30/info.py +14 -23
- jentic/apitools/openapi/datamodels/low/v30/license.py +4 -10
- jentic/apitools/openapi/datamodels/low/v30/link.py +141 -0
- jentic/apitools/openapi/datamodels/low/v30/media_type.py +110 -0
- jentic/apitools/openapi/datamodels/low/v30/oauth_flow.py +4 -10
- jentic/apitools/openapi/datamodels/low/v30/oauth_flows.py +7 -15
- jentic/apitools/openapi/datamodels/low/v30/openapi.py +149 -0
- jentic/apitools/openapi/datamodels/low/v30/operation.py +134 -0
- jentic/apitools/openapi/datamodels/low/v30/parameter.py +123 -0
- jentic/apitools/openapi/datamodels/low/v30/path_item.py +125 -0
- jentic/apitools/openapi/datamodels/low/v30/paths.py +108 -0
- jentic/apitools/openapi/datamodels/low/v30/reference.py +5 -9
- jentic/apitools/openapi/datamodels/low/v30/request_body.py +108 -0
- jentic/apitools/openapi/datamodels/low/v30/response.py +104 -0
- jentic/apitools/openapi/datamodels/low/v30/responses.py +109 -0
- jentic/apitools/openapi/datamodels/low/v30/schema.py +81 -97
- jentic/apitools/openapi/datamodels/low/v30/security_requirement.py +14 -9
- jentic/apitools/openapi/datamodels/low/v30/security_scheme.py +42 -22
- jentic/apitools/openapi/datamodels/low/v30/server.py +111 -0
- jentic/apitools/openapi/datamodels/low/v30/server_variable.py +4 -10
- jentic/apitools/openapi/datamodels/low/v30/tag.py +8 -46
- jentic/apitools/openapi/datamodels/low/v30/xml.py +4 -10
- jentic/apitools/openapi/datamodels/low/v31/__init__.py +77 -0
- jentic/apitools/openapi/datamodels/low/v31/builders/__init__.py +347 -0
- jentic/apitools/openapi/datamodels/low/v31/callback.py +131 -0
- jentic/apitools/openapi/datamodels/low/v31/components.py +240 -0
- jentic/apitools/openapi/datamodels/low/v31/contact.py +61 -0
- jentic/apitools/openapi/datamodels/low/v31/discriminator.py +62 -0
- jentic/apitools/openapi/datamodels/low/v31/encoding.py +81 -0
- jentic/apitools/openapi/datamodels/low/v31/example.py +91 -0
- jentic/apitools/openapi/datamodels/low/v31/external_documentation.py +59 -0
- jentic/apitools/openapi/datamodels/low/v31/header.py +120 -0
- jentic/apitools/openapi/datamodels/low/v31/info.py +116 -0
- jentic/apitools/openapi/datamodels/low/v31/license.py +61 -0
- jentic/apitools/openapi/datamodels/low/v31/link.py +141 -0
- jentic/apitools/openapi/datamodels/low/v31/media_type.py +110 -0
- jentic/apitools/openapi/datamodels/low/v31/oauth_flow.py +65 -0
- jentic/apitools/openapi/datamodels/low/v31/oauth_flows.py +108 -0
- jentic/apitools/openapi/datamodels/low/v31/openapi.py +168 -0
- jentic/apitools/openapi/datamodels/low/v31/operation.py +133 -0
- jentic/apitools/openapi/datamodels/low/v31/parameter.py +123 -0
- jentic/apitools/openapi/datamodels/low/v31/path_item.py +125 -0
- jentic/apitools/openapi/datamodels/low/v31/paths.py +108 -0
- jentic/apitools/openapi/datamodels/low/v31/reference.py +65 -0
- jentic/apitools/openapi/datamodels/low/v31/request_body.py +108 -0
- jentic/apitools/openapi/datamodels/low/v31/response.py +104 -0
- jentic/apitools/openapi/datamodels/low/v31/responses.py +109 -0
- jentic/apitools/openapi/datamodels/low/v31/schema.py +498 -0
- jentic/apitools/openapi/datamodels/low/v31/security_requirement.py +106 -0
- jentic/apitools/openapi/datamodels/low/v31/security_scheme.py +129 -0
- jentic/apitools/openapi/datamodels/low/v31/server.py +111 -0
- jentic/apitools/openapi/datamodels/low/v31/server_variable.py +70 -0
- jentic/apitools/openapi/datamodels/low/v31/tag.py +63 -0
- jentic/apitools/openapi/datamodels/low/v31/xml.py +54 -0
- jentic_openapi_datamodels-1.0.0a19.dist-info/METADATA +372 -0
- jentic_openapi_datamodels-1.0.0a19.dist-info/RECORD +75 -0
- jentic/apitools/openapi/datamodels/low/model_builder.py +0 -129
- jentic_openapi_datamodels-1.0.0a18.dist-info/METADATA +0 -211
- jentic_openapi_datamodels-1.0.0a18.dist-info/RECORD +0 -27
- {jentic_openapi_datamodels-1.0.0a18.dist-info → jentic_openapi_datamodels-1.0.0a19.dist-info}/WHEEL +0 -0
- {jentic_openapi_datamodels-1.0.0a18.dist-info → jentic_openapi_datamodels-1.0.0a19.dist-info}/licenses/LICENSE +0 -0
- {jentic_openapi_datamodels-1.0.0a18.dist-info → jentic_openapi_datamodels-1.0.0a19.dist-info}/licenses/NOTICE +0 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
from dataclasses import dataclass, field, replace
|
|
2
|
+
|
|
3
|
+
from ruamel import yaml
|
|
4
|
+
|
|
5
|
+
from ..context import Context
|
|
6
|
+
from ..fields import fixed_field
|
|
7
|
+
from ..sources import FieldSource, KeySource, ValueSource, YAMLInvalidValue, YAMLValue
|
|
8
|
+
from .builders import build_field_source, build_model
|
|
9
|
+
from .callback import Callback
|
|
10
|
+
from .example import Example, build_example_or_reference
|
|
11
|
+
from .header import Header
|
|
12
|
+
from .link import Link
|
|
13
|
+
from .parameter import Parameter, build_parameter_or_reference
|
|
14
|
+
from .path_item import PathItem
|
|
15
|
+
from .reference import Reference
|
|
16
|
+
from .request_body import RequestBody, build_request_body_or_reference
|
|
17
|
+
from .response import Response, build_response_or_reference
|
|
18
|
+
from .schema import BooleanJSONSchema, Schema
|
|
19
|
+
from .schema import build as build_schema
|
|
20
|
+
from .security_scheme import SecurityScheme, build_security_scheme_or_reference
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
__all__ = ["Components", "build"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True, slots=True)
|
|
27
|
+
class Components:
|
|
28
|
+
r"""
|
|
29
|
+
Components Object representation for OpenAPI 3.1.
|
|
30
|
+
|
|
31
|
+
Holds reusable objects for different aspects of the OAS. All objects defined within
|
|
32
|
+
the components object have no effect on the API unless they are explicitly referenced
|
|
33
|
+
from properties outside the components object.
|
|
34
|
+
|
|
35
|
+
All component keys MUST match the regex pattern: ^[a-zA-Z0-9\.\-_]+$
|
|
36
|
+
(Note: This is a validation concern and not enforced by this low-level model)
|
|
37
|
+
|
|
38
|
+
Attributes:
|
|
39
|
+
root_node: The top-level node representing the entire Components object in the original source file
|
|
40
|
+
schemas: Reusable Schema Objects (can include $ref directly in OpenAPI 3.1)
|
|
41
|
+
responses: Reusable Response Objects or Reference Objects
|
|
42
|
+
parameters: Reusable Parameter Objects or Reference Objects
|
|
43
|
+
examples: Reusable Example Objects or Reference Objects
|
|
44
|
+
request_bodies: Reusable Request Body Objects or Reference Objects
|
|
45
|
+
headers: Reusable Header Objects or Reference Objects
|
|
46
|
+
security_schemes: Reusable Security Scheme Objects or Reference Objects
|
|
47
|
+
links: Reusable Link Objects or Reference Objects
|
|
48
|
+
callbacks: Reusable Callback Objects or Reference Objects
|
|
49
|
+
path_items: Reusable Path Item Objects (new in OpenAPI 3.1)
|
|
50
|
+
extensions: Specification extensions (x-* fields)
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
root_node: yaml.Node
|
|
54
|
+
schemas: FieldSource[dict[KeySource[str], Schema | BooleanJSONSchema]] | None = fixed_field()
|
|
55
|
+
responses: FieldSource[dict[KeySource[str], Response | Reference]] | None = fixed_field()
|
|
56
|
+
parameters: FieldSource[dict[KeySource[str], Parameter | Reference]] | None = fixed_field()
|
|
57
|
+
examples: FieldSource[dict[KeySource[str], Example | Reference]] | None = fixed_field()
|
|
58
|
+
request_bodies: FieldSource[dict[KeySource[str], RequestBody | Reference]] | None = fixed_field(
|
|
59
|
+
metadata={"yaml_name": "requestBodies"}
|
|
60
|
+
)
|
|
61
|
+
headers: FieldSource[dict[KeySource[str], "Header | Reference"]] | None = fixed_field()
|
|
62
|
+
security_schemes: FieldSource[dict[KeySource[str], SecurityScheme | Reference]] | None = (
|
|
63
|
+
fixed_field(metadata={"yaml_name": "securitySchemes"})
|
|
64
|
+
)
|
|
65
|
+
links: FieldSource[dict[KeySource[str], "Link | Reference"]] | None = fixed_field()
|
|
66
|
+
callbacks: FieldSource[dict[KeySource[str], "Callback | Reference"]] | None = fixed_field()
|
|
67
|
+
path_items: FieldSource[dict[KeySource[str], "PathItem"]] | None = fixed_field(
|
|
68
|
+
metadata={"yaml_name": "pathItems"}
|
|
69
|
+
)
|
|
70
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def build(
|
|
74
|
+
root: yaml.Node, context: Context | None = None
|
|
75
|
+
) -> Components | ValueSource[YAMLInvalidValue]:
|
|
76
|
+
"""
|
|
77
|
+
Build a Components object from a YAML node.
|
|
78
|
+
|
|
79
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
80
|
+
model that provides complete source fidelity for inspection and validation.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
84
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
A Components object if the node is valid, or a ValueSource containing
|
|
88
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
89
|
+
and its source location for validation).
|
|
90
|
+
|
|
91
|
+
Example:
|
|
92
|
+
from ruamel.yaml import YAML
|
|
93
|
+
yaml = YAML()
|
|
94
|
+
root = yaml.compose('''
|
|
95
|
+
schemas:
|
|
96
|
+
User:
|
|
97
|
+
type: object
|
|
98
|
+
properties:
|
|
99
|
+
id:
|
|
100
|
+
type: integer
|
|
101
|
+
name:
|
|
102
|
+
type: string
|
|
103
|
+
responses:
|
|
104
|
+
NotFound:
|
|
105
|
+
description: Entity not found
|
|
106
|
+
''')
|
|
107
|
+
components = build(root)
|
|
108
|
+
assert 'User' in {k.value for k in components.schemas.value.keys()}
|
|
109
|
+
"""
|
|
110
|
+
context = context or Context()
|
|
111
|
+
|
|
112
|
+
# Use build_model for initial construction
|
|
113
|
+
components_obj = build_model(root, Components, context=context)
|
|
114
|
+
|
|
115
|
+
# If build_model returned ValueSource (invalid node), return it immediately
|
|
116
|
+
if not isinstance(components_obj, Components):
|
|
117
|
+
return components_obj
|
|
118
|
+
|
|
119
|
+
# Manually handle nested complex fields that aren't covered by build_model
|
|
120
|
+
replacements = {}
|
|
121
|
+
for key_node, value_node in root.value:
|
|
122
|
+
key = context.yaml_constructor.construct_yaml_str(key_node)
|
|
123
|
+
|
|
124
|
+
if key == "schemas":
|
|
125
|
+
# Handle schemas field - map of Schema objects (in 3.1, schemas can have $ref directly)
|
|
126
|
+
if isinstance(value_node, yaml.MappingNode):
|
|
127
|
+
schemas_dict = {}
|
|
128
|
+
for schema_key_node, schema_value_node in value_node.value:
|
|
129
|
+
schema_key = context.yaml_constructor.construct_yaml_str(schema_key_node)
|
|
130
|
+
schema = build_schema(schema_value_node, context)
|
|
131
|
+
schemas_dict[KeySource(value=schema_key, key_node=schema_key_node)] = schema
|
|
132
|
+
replacements["schemas"] = FieldSource(
|
|
133
|
+
value=schemas_dict, key_node=key_node, value_node=value_node
|
|
134
|
+
)
|
|
135
|
+
else:
|
|
136
|
+
# Not a mapping - preserve as-is for validation
|
|
137
|
+
replacements["schemas"] = build_field_source(key_node, value_node, context)
|
|
138
|
+
|
|
139
|
+
elif key == "responses":
|
|
140
|
+
# Handle responses field - map of Response or Reference objects
|
|
141
|
+
if isinstance(value_node, yaml.MappingNode):
|
|
142
|
+
responses_dict = {}
|
|
143
|
+
for response_key_node, response_value_node in value_node.value:
|
|
144
|
+
response_key = context.yaml_constructor.construct_yaml_str(response_key_node)
|
|
145
|
+
response_or_reference = build_response_or_reference(
|
|
146
|
+
response_value_node, context
|
|
147
|
+
)
|
|
148
|
+
responses_dict[KeySource(value=response_key, key_node=response_key_node)] = (
|
|
149
|
+
response_or_reference
|
|
150
|
+
)
|
|
151
|
+
replacements["responses"] = FieldSource(
|
|
152
|
+
value=responses_dict, key_node=key_node, value_node=value_node
|
|
153
|
+
)
|
|
154
|
+
else:
|
|
155
|
+
# Not a mapping - preserve as-is for validation
|
|
156
|
+
replacements["responses"] = build_field_source(key_node, value_node, context)
|
|
157
|
+
|
|
158
|
+
elif key == "parameters":
|
|
159
|
+
# Handle parameters field - map of Parameter or Reference objects
|
|
160
|
+
if isinstance(value_node, yaml.MappingNode):
|
|
161
|
+
parameters_dict = {}
|
|
162
|
+
for parameter_key_node, parameter_value_node in value_node.value:
|
|
163
|
+
parameter_key = context.yaml_constructor.construct_yaml_str(parameter_key_node)
|
|
164
|
+
parameter_or_reference = build_parameter_or_reference(
|
|
165
|
+
parameter_value_node, context
|
|
166
|
+
)
|
|
167
|
+
parameters_dict[KeySource(value=parameter_key, key_node=parameter_key_node)] = (
|
|
168
|
+
parameter_or_reference
|
|
169
|
+
)
|
|
170
|
+
replacements["parameters"] = FieldSource(
|
|
171
|
+
value=parameters_dict, key_node=key_node, value_node=value_node
|
|
172
|
+
)
|
|
173
|
+
else:
|
|
174
|
+
# Not a mapping - preserve as-is for validation
|
|
175
|
+
replacements["parameters"] = build_field_source(key_node, value_node, context)
|
|
176
|
+
|
|
177
|
+
elif key == "examples":
|
|
178
|
+
# Handle examples field - map of Example or Reference objects
|
|
179
|
+
if isinstance(value_node, yaml.MappingNode):
|
|
180
|
+
examples_dict = {}
|
|
181
|
+
for example_key_node, example_value_node in value_node.value:
|
|
182
|
+
example_key = context.yaml_constructor.construct_yaml_str(example_key_node)
|
|
183
|
+
example_or_reference = build_example_or_reference(example_value_node, context)
|
|
184
|
+
examples_dict[KeySource(value=example_key, key_node=example_key_node)] = (
|
|
185
|
+
example_or_reference
|
|
186
|
+
)
|
|
187
|
+
replacements["examples"] = FieldSource(
|
|
188
|
+
value=examples_dict, key_node=key_node, value_node=value_node
|
|
189
|
+
)
|
|
190
|
+
else:
|
|
191
|
+
# Not a mapping - preserve as-is for validation
|
|
192
|
+
replacements["examples"] = build_field_source(key_node, value_node, context)
|
|
193
|
+
|
|
194
|
+
elif key == "requestBodies":
|
|
195
|
+
# Handle requestBodies field - map of RequestBody or Reference objects
|
|
196
|
+
if isinstance(value_node, yaml.MappingNode):
|
|
197
|
+
request_bodies_dict = {}
|
|
198
|
+
for request_body_key_node, request_body_value_node in value_node.value:
|
|
199
|
+
request_body_key = context.yaml_constructor.construct_yaml_str(
|
|
200
|
+
request_body_key_node
|
|
201
|
+
)
|
|
202
|
+
request_body_or_reference = build_request_body_or_reference(
|
|
203
|
+
request_body_value_node, context
|
|
204
|
+
)
|
|
205
|
+
request_bodies_dict[
|
|
206
|
+
KeySource(value=request_body_key, key_node=request_body_key_node)
|
|
207
|
+
] = request_body_or_reference
|
|
208
|
+
replacements["request_bodies"] = FieldSource(
|
|
209
|
+
value=request_bodies_dict, key_node=key_node, value_node=value_node
|
|
210
|
+
)
|
|
211
|
+
else:
|
|
212
|
+
# Not a mapping - preserve as-is for validation
|
|
213
|
+
replacements["request_bodies"] = build_field_source(key_node, value_node, context)
|
|
214
|
+
|
|
215
|
+
elif key == "securitySchemes":
|
|
216
|
+
# Handle securitySchemes field - map of SecurityScheme or Reference objects
|
|
217
|
+
if isinstance(value_node, yaml.MappingNode):
|
|
218
|
+
security_schemes_dict = {}
|
|
219
|
+
for security_scheme_key_node, security_scheme_value_node in value_node.value:
|
|
220
|
+
security_scheme_key = context.yaml_constructor.construct_yaml_str(
|
|
221
|
+
security_scheme_key_node
|
|
222
|
+
)
|
|
223
|
+
security_scheme_or_reference = build_security_scheme_or_reference(
|
|
224
|
+
security_scheme_value_node, context
|
|
225
|
+
)
|
|
226
|
+
security_schemes_dict[
|
|
227
|
+
KeySource(value=security_scheme_key, key_node=security_scheme_key_node)
|
|
228
|
+
] = security_scheme_or_reference
|
|
229
|
+
replacements["security_schemes"] = FieldSource(
|
|
230
|
+
value=security_schemes_dict, key_node=key_node, value_node=value_node
|
|
231
|
+
)
|
|
232
|
+
else:
|
|
233
|
+
# Not a mapping - preserve as-is for validation
|
|
234
|
+
replacements["security_schemes"] = build_field_source(key_node, value_node, context)
|
|
235
|
+
|
|
236
|
+
# Apply all replacements at once
|
|
237
|
+
if replacements:
|
|
238
|
+
components_obj = replace(components_obj, **replacements)
|
|
239
|
+
|
|
240
|
+
return components_obj
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
from ruamel import yaml
|
|
4
|
+
|
|
5
|
+
from ..context import Context
|
|
6
|
+
from ..fields import fixed_field
|
|
7
|
+
from ..sources import FieldSource, KeySource, ValueSource, YAMLInvalidValue, YAMLValue
|
|
8
|
+
from .builders import build_model
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
__all__ = ["Contact", "build"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True, slots=True)
|
|
15
|
+
class Contact:
|
|
16
|
+
"""
|
|
17
|
+
Contact Object representation for OpenAPI 3.1.
|
|
18
|
+
|
|
19
|
+
Contact information for the exposed API.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
root_node: The top-level node representing the entire Contact object in the original source file
|
|
23
|
+
name: The identifying name of the contact person/organization.
|
|
24
|
+
url: The URL pointing to the contact information. Value MUST be in the format of a URL.
|
|
25
|
+
email: The email address of the contact person/organization. Value MUST be in the format of an email address.
|
|
26
|
+
extensions: Specification extensions (x-* fields)
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
root_node: yaml.Node
|
|
30
|
+
name: FieldSource[str] | None = fixed_field()
|
|
31
|
+
url: FieldSource[str] | None = fixed_field()
|
|
32
|
+
email: FieldSource[str] | None = fixed_field()
|
|
33
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def build(
|
|
37
|
+
root: yaml.Node, context: Context | None = None
|
|
38
|
+
) -> Contact | ValueSource[YAMLInvalidValue]:
|
|
39
|
+
"""
|
|
40
|
+
Build a Contact object from a YAML node.
|
|
41
|
+
|
|
42
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
43
|
+
model that provides complete source fidelity for inspection and validation.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
47
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
A Contact object if the node is valid, or a ValueSource containing
|
|
51
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
52
|
+
and its source location for validation).
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
from ruamel.yaml import YAML
|
|
56
|
+
yaml = YAML()
|
|
57
|
+
root = yaml.compose("name: API Support\\nemail: support@example.com")
|
|
58
|
+
contact = build(root)
|
|
59
|
+
assert contact.name.value == 'API Support'
|
|
60
|
+
"""
|
|
61
|
+
return build_model(root, Contact, context=context)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
from ruamel import yaml
|
|
4
|
+
|
|
5
|
+
from ..context import Context
|
|
6
|
+
from ..fields import fixed_field
|
|
7
|
+
from ..sources import FieldSource, KeySource, ValueSource, YAMLInvalidValue, YAMLValue
|
|
8
|
+
from .builders import build_model
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
__all__ = ["Discriminator", "build"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True, slots=True)
|
|
15
|
+
class Discriminator:
|
|
16
|
+
"""
|
|
17
|
+
Discriminator Object representation for OpenAPI 3.1.
|
|
18
|
+
|
|
19
|
+
When request bodies or response payloads may be one of a number of different schemas,
|
|
20
|
+
a discriminator object can be used to aid in serialization, deserialization, and validation.
|
|
21
|
+
|
|
22
|
+
In OpenAPI 3.1, the Discriminator Object supports Specification Extensions (x-* fields).
|
|
23
|
+
|
|
24
|
+
Attributes:
|
|
25
|
+
root_node: The top-level node representing the entire Discriminator object in the original source file
|
|
26
|
+
property_name: REQUIRED. The name of the property in the payload that will hold the discriminator value
|
|
27
|
+
mapping: An optional mapping of discriminator values to schema names or references
|
|
28
|
+
extensions: Specification extensions (x-* fields)
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
root_node: yaml.Node
|
|
32
|
+
property_name: FieldSource[str] | None = fixed_field(metadata={"yaml_name": "propertyName"})
|
|
33
|
+
mapping: FieldSource[dict[KeySource[str], ValueSource[str]]] | None = fixed_field()
|
|
34
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def build(
|
|
38
|
+
root: yaml.Node, context: Context | None = None
|
|
39
|
+
) -> Discriminator | ValueSource[YAMLInvalidValue]:
|
|
40
|
+
"""
|
|
41
|
+
Build a Discriminator object from a YAML node.
|
|
42
|
+
|
|
43
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
44
|
+
model that provides complete source fidelity for inspection and validation.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
48
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
A Discriminator object if the node is valid, or a ValueSource containing
|
|
52
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
53
|
+
and its source location for validation).
|
|
54
|
+
|
|
55
|
+
Example:
|
|
56
|
+
from ruamel.yaml import YAML
|
|
57
|
+
yaml = YAML()
|
|
58
|
+
root = yaml.compose("propertyName: petType\\nmapping:\\n dog: Dog\\n cat: Cat")
|
|
59
|
+
discriminator = build(root)
|
|
60
|
+
assert discriminator.property_name.value == 'petType'
|
|
61
|
+
"""
|
|
62
|
+
return build_model(root, Discriminator, context=context)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
from ruamel import yaml
|
|
4
|
+
|
|
5
|
+
from ..context import Context
|
|
6
|
+
from ..fields import fixed_field
|
|
7
|
+
from ..sources import FieldSource, KeySource, ValueSource, YAMLInvalidValue, YAMLValue
|
|
8
|
+
from .builders import build_model
|
|
9
|
+
from .header import Header
|
|
10
|
+
from .reference import Reference
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
__all__ = ["Encoding", "build"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True, slots=True)
|
|
17
|
+
class Encoding:
|
|
18
|
+
"""
|
|
19
|
+
Encoding Object representation for OpenAPI 3.1.
|
|
20
|
+
|
|
21
|
+
A single encoding definition applied to a single schema property.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
root_node: The top-level node representing the entire Encoding object in the original source file
|
|
25
|
+
contentType: The Content-Type for encoding a specific property. Default value depends on the property type:
|
|
26
|
+
for string with format being binary – application/octet-stream;
|
|
27
|
+
for other primitive types – text/plain;
|
|
28
|
+
for object - application/json;
|
|
29
|
+
for array – the default is defined based on the inner type.
|
|
30
|
+
headers: A map allowing additional information to be provided as headers. Content-Type is described
|
|
31
|
+
separately and SHALL be ignored if included.
|
|
32
|
+
style: Describes how a specific property value will be serialized depending on its type.
|
|
33
|
+
explode: When this is true, property values of type array or object generate separate parameters
|
|
34
|
+
for each value of the array, or key-value-pair of the map. For other data types this property
|
|
35
|
+
has no effect. Default value is true.
|
|
36
|
+
allowReserved: Determines whether the parameter value SHOULD allow reserved characters, as defined by
|
|
37
|
+
RFC3986 :/?#[]@!$&'()*+,;= to be included without percent-encoding. The default value is false.
|
|
38
|
+
extensions: Specification extensions (x-* fields)
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
root_node: yaml.Node
|
|
42
|
+
contentType: FieldSource[str] | None = fixed_field()
|
|
43
|
+
headers: FieldSource[dict[KeySource[str], "Header | Reference"]] | None = fixed_field()
|
|
44
|
+
style: FieldSource[str] | None = fixed_field()
|
|
45
|
+
explode: FieldSource[bool] | None = fixed_field()
|
|
46
|
+
allowReserved: FieldSource[bool] | None = fixed_field()
|
|
47
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def build(
|
|
51
|
+
root: yaml.Node, context: Context | None = None
|
|
52
|
+
) -> Encoding | ValueSource[YAMLInvalidValue]:
|
|
53
|
+
"""
|
|
54
|
+
Build an Encoding object from a YAML node.
|
|
55
|
+
|
|
56
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
57
|
+
model that provides complete source fidelity for inspection and validation.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
61
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
An Encoding object if the node is valid, or a ValueSource containing
|
|
65
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
66
|
+
and its source location for validation).
|
|
67
|
+
|
|
68
|
+
Example:
|
|
69
|
+
from ruamel.yaml import YAML
|
|
70
|
+
yaml = YAML()
|
|
71
|
+
root = yaml.compose('''
|
|
72
|
+
contentType: application/xml
|
|
73
|
+
headers:
|
|
74
|
+
X-Rate-Limit:
|
|
75
|
+
schema:
|
|
76
|
+
type: integer
|
|
77
|
+
''')
|
|
78
|
+
encoding = build(root)
|
|
79
|
+
assert encoding.contentType.value == 'application/xml'
|
|
80
|
+
"""
|
|
81
|
+
return build_model(root, Encoding, context=context)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
from ruamel import yaml
|
|
4
|
+
|
|
5
|
+
from ..context import Context
|
|
6
|
+
from ..fields import fixed_field
|
|
7
|
+
from ..sources import FieldSource, KeySource, ValueSource, YAMLInvalidValue, YAMLValue
|
|
8
|
+
from .builders import build_model
|
|
9
|
+
from .reference import Reference
|
|
10
|
+
from .reference import build as build_reference
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
__all__ = ["Example", "build", "build_example_or_reference"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True, slots=True)
|
|
17
|
+
class Example:
|
|
18
|
+
"""
|
|
19
|
+
Example Object representation for OpenAPI 3.1.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
root_node: The top-level node representing the entire Example object in the original source file
|
|
23
|
+
summary: A short description of the example.
|
|
24
|
+
description: A long description for the example. CommonMark syntax MAY be used for rich text representation.
|
|
25
|
+
value: Embedded literal example. The value field and externalValue field are mutually exclusive.
|
|
26
|
+
external_value: A URL that points to the literal example. This provides the capability to reference
|
|
27
|
+
examples that cannot be inlined. The value field and externalValue field are mutually exclusive.
|
|
28
|
+
extensions: Specification extensions (x-* fields)
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
root_node: yaml.Node
|
|
32
|
+
summary: FieldSource[str] | None = fixed_field()
|
|
33
|
+
description: FieldSource[str] | None = fixed_field()
|
|
34
|
+
value: FieldSource[YAMLValue] | None = fixed_field()
|
|
35
|
+
external_value: FieldSource[str] | None = fixed_field(metadata={"yaml_name": "externalValue"})
|
|
36
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def build(
|
|
40
|
+
root: yaml.Node, context: Context | None = None
|
|
41
|
+
) -> Example | ValueSource[YAMLInvalidValue]:
|
|
42
|
+
"""
|
|
43
|
+
Build an Example object from a YAML node.
|
|
44
|
+
|
|
45
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
46
|
+
model that provides complete source fidelity for inspection and validation.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
50
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
An Example object if the node is valid, or a ValueSource containing
|
|
54
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
55
|
+
and its source location for validation).
|
|
56
|
+
|
|
57
|
+
Example:
|
|
58
|
+
from ruamel.yaml import YAML
|
|
59
|
+
yaml = YAML()
|
|
60
|
+
root = yaml.compose("summary: A user example\\nvalue:\\n id: 1\\n name: John")
|
|
61
|
+
example = build(root)
|
|
62
|
+
assert example.summary.value == 'A user example'
|
|
63
|
+
"""
|
|
64
|
+
return build_model(root, Example, context=context)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def build_example_or_reference(
|
|
68
|
+
node: yaml.Node, context: Context
|
|
69
|
+
) -> Example | Reference | ValueSource[YAMLInvalidValue]:
|
|
70
|
+
"""
|
|
71
|
+
Build either an Example or Reference from a YAML node.
|
|
72
|
+
|
|
73
|
+
This helper handles the polymorphic nature of OpenAPI where many fields
|
|
74
|
+
can contain either an Example object or a Reference object ($ref).
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
node: The YAML node to parse
|
|
78
|
+
context: Parsing context
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
An Example, Reference, or ValueSource if the node is invalid
|
|
82
|
+
"""
|
|
83
|
+
# Check if it's a reference (has $ref key)
|
|
84
|
+
if isinstance(node, yaml.MappingNode):
|
|
85
|
+
for key_node, _ in node.value:
|
|
86
|
+
key = context.yaml_constructor.construct_yaml_str(key_node)
|
|
87
|
+
if key == "$ref":
|
|
88
|
+
return build_reference(node, context)
|
|
89
|
+
|
|
90
|
+
# Otherwise, try to build as Example
|
|
91
|
+
return build(node, context)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
from ruamel import yaml
|
|
4
|
+
|
|
5
|
+
from ..context import Context
|
|
6
|
+
from ..fields import fixed_field
|
|
7
|
+
from ..sources import FieldSource, KeySource, ValueSource, YAMLInvalidValue, YAMLValue
|
|
8
|
+
from .builders import build_model
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
__all__ = ["ExternalDocumentation", "build"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True, slots=True)
|
|
15
|
+
class ExternalDocumentation:
|
|
16
|
+
"""
|
|
17
|
+
External Documentation Object representation for OpenAPI 3.1.
|
|
18
|
+
|
|
19
|
+
Allows referencing an external resource for extended documentation.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
root_node: The top-level node representing the entire External Documentation object in the original source file
|
|
23
|
+
description: A short description of the target documentation. CommonMark syntax MAY be used for rich text representation.
|
|
24
|
+
url: The URL for the target documentation. REQUIRED. Value MUST be in the format of a URL.
|
|
25
|
+
extensions: Specification extensions (x-* fields)
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
root_node: yaml.Node
|
|
29
|
+
description: FieldSource[str] | None = fixed_field()
|
|
30
|
+
url: FieldSource[str] | None = fixed_field()
|
|
31
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def build(
|
|
35
|
+
root: yaml.Node, context: Context | None = None
|
|
36
|
+
) -> ExternalDocumentation | ValueSource[YAMLInvalidValue]:
|
|
37
|
+
"""
|
|
38
|
+
Build an ExternalDocumentation object from a YAML node.
|
|
39
|
+
|
|
40
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
41
|
+
model that provides complete source fidelity for inspection and validation.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
45
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
An ExternalDocumentation object if the node is valid, or a ValueSource containing
|
|
49
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
50
|
+
and its source location for validation).
|
|
51
|
+
|
|
52
|
+
Example:
|
|
53
|
+
from ruamel.yaml import YAML
|
|
54
|
+
yaml = YAML()
|
|
55
|
+
root = yaml.compose("url: https://example.com\\ndescription: Find more info here")
|
|
56
|
+
external_docs = build(root)
|
|
57
|
+
assert external_docs.url.value == 'https://example.com'
|
|
58
|
+
"""
|
|
59
|
+
return build_model(root, ExternalDocumentation, context=context)
|