jentic-openapi-datamodels 1.0.0a18__py3-none-any.whl → 1.0.0a20__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.0a20.dist-info/METADATA +379 -0
- jentic_openapi_datamodels-1.0.0a20.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.0a20.dist-info}/WHEEL +0 -0
- {jentic_openapi_datamodels-1.0.0a18.dist-info → jentic_openapi_datamodels-1.0.0a20.dist-info}/licenses/LICENSE +0 -0
- {jentic_openapi_datamodels-1.0.0a18.dist-info → jentic_openapi_datamodels-1.0.0a20.dist-info}/licenses/NOTICE +0 -0
|
@@ -0,0 +1,123 @@
|
|
|
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 .example import Example
|
|
10
|
+
from .media_type import MediaType
|
|
11
|
+
from .reference import Reference
|
|
12
|
+
from .reference import build as build_reference
|
|
13
|
+
from .schema import Schema
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = ["Parameter", "build", "build_parameter_or_reference"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True, slots=True)
|
|
20
|
+
class Parameter:
|
|
21
|
+
"""
|
|
22
|
+
Parameter Object representation for OpenAPI 3.0.
|
|
23
|
+
|
|
24
|
+
Describes a single operation parameter. A unique parameter is defined by a combination
|
|
25
|
+
of a name and location (in).
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
root_node: The top-level node representing the entire Parameter object in the original source file
|
|
29
|
+
name: The name of the parameter (case-sensitive)
|
|
30
|
+
in_: The location of the parameter. Possible values are "query", "header", "path", or "cookie"
|
|
31
|
+
description: A brief description of the parameter (may contain CommonMark syntax)
|
|
32
|
+
required: Determines whether this parameter is mandatory. For path parameters, must be true.
|
|
33
|
+
Default is false for other parameter types.
|
|
34
|
+
deprecated: Specifies that a parameter is deprecated and should be transitioned out of usage
|
|
35
|
+
allow_empty_value: Sets the ability to pass empty-valued parameters (valid only for query parameters)
|
|
36
|
+
style: Describes how the parameter value will be serialized (default depends on 'in' value)
|
|
37
|
+
explode: When true, parameter values of type array or object generate separate parameters
|
|
38
|
+
allow_reserved: Determines whether reserved characters are allowed without percent-encoding
|
|
39
|
+
schema: The schema defining the type used for the parameter
|
|
40
|
+
example: Example of the parameter's potential value
|
|
41
|
+
examples: Examples of the parameter's potential value (map of Example objects or References)
|
|
42
|
+
content: A map containing the representations for the parameter (must contain only one entry)
|
|
43
|
+
extensions: Specification extensions (x-* fields)
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
root_node: yaml.Node
|
|
47
|
+
name: FieldSource[str] | None = fixed_field()
|
|
48
|
+
in_: FieldSource[str] | None = fixed_field(metadata={"yaml_name": "in"})
|
|
49
|
+
description: FieldSource[str] | None = fixed_field()
|
|
50
|
+
required: FieldSource[bool] | None = fixed_field()
|
|
51
|
+
deprecated: FieldSource[bool] | None = fixed_field()
|
|
52
|
+
allow_empty_value: FieldSource[bool] | None = fixed_field(
|
|
53
|
+
metadata={"yaml_name": "allowEmptyValue"}
|
|
54
|
+
)
|
|
55
|
+
style: FieldSource[str] | None = fixed_field()
|
|
56
|
+
explode: FieldSource[bool] | None = fixed_field()
|
|
57
|
+
allow_reserved: FieldSource[bool] | None = fixed_field(metadata={"yaml_name": "allowReserved"})
|
|
58
|
+
schema: FieldSource["Schema | Reference"] | None = fixed_field()
|
|
59
|
+
example: FieldSource[YAMLValue] | None = fixed_field()
|
|
60
|
+
examples: FieldSource[dict[KeySource[str], "Example | Reference"]] | None = fixed_field()
|
|
61
|
+
content: FieldSource[dict[KeySource[str], "MediaType"]] | None = fixed_field()
|
|
62
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def build(
|
|
66
|
+
root: yaml.Node, context: Context | None = None
|
|
67
|
+
) -> Parameter | ValueSource[YAMLInvalidValue]:
|
|
68
|
+
"""
|
|
69
|
+
Build a Parameter object from a YAML node.
|
|
70
|
+
|
|
71
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
72
|
+
model that provides complete source fidelity for inspection and validation.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
76
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
A Parameter object if the node is valid, or a ValueSource containing
|
|
80
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
81
|
+
and its source location for validation).
|
|
82
|
+
|
|
83
|
+
Example:
|
|
84
|
+
from ruamel.yaml import YAML
|
|
85
|
+
yaml = YAML()
|
|
86
|
+
root = yaml.compose('''
|
|
87
|
+
name: userId
|
|
88
|
+
in: path
|
|
89
|
+
required: true
|
|
90
|
+
schema:
|
|
91
|
+
type: integer
|
|
92
|
+
''')
|
|
93
|
+
parameter = build(root)
|
|
94
|
+
assert parameter.name.value == 'userId'
|
|
95
|
+
"""
|
|
96
|
+
return build_model(root, Parameter, context=context)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def build_parameter_or_reference(
|
|
100
|
+
node: yaml.Node, context: Context
|
|
101
|
+
) -> Parameter | Reference | ValueSource[YAMLInvalidValue]:
|
|
102
|
+
"""
|
|
103
|
+
Build either a Parameter or Reference from a YAML node.
|
|
104
|
+
|
|
105
|
+
This helper handles the polymorphic nature of OpenAPI where many fields
|
|
106
|
+
can contain either a Parameter object or a Reference object ($ref).
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
node: The YAML node to parse
|
|
110
|
+
context: Parsing context
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
A Parameter, Reference, or ValueSource if the node is invalid
|
|
114
|
+
"""
|
|
115
|
+
# Check if it's a reference (has $ref key)
|
|
116
|
+
if isinstance(node, yaml.MappingNode):
|
|
117
|
+
for key_node, _ in node.value:
|
|
118
|
+
key = context.yaml_constructor.construct_yaml_str(key_node)
|
|
119
|
+
if key == "$ref":
|
|
120
|
+
return build_reference(node, context)
|
|
121
|
+
|
|
122
|
+
# Otherwise, try to build as Parameter
|
|
123
|
+
return build(node, context)
|
|
@@ -0,0 +1,125 @@
|
|
|
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_model
|
|
9
|
+
from .operation import Operation
|
|
10
|
+
from .operation import build as build_operation
|
|
11
|
+
from .parameter import Parameter
|
|
12
|
+
from .reference import Reference
|
|
13
|
+
from .server import Server
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = ["PathItem", "build"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True, slots=True)
|
|
20
|
+
class PathItem:
|
|
21
|
+
"""
|
|
22
|
+
Path Item Object representation for OpenAPI 3.0.
|
|
23
|
+
|
|
24
|
+
Describes the operations available on a single path. A Path Item may be empty,
|
|
25
|
+
due to ACL constraints.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
root_node: The top-level node representing the entire Path Item object in the original source file
|
|
29
|
+
ref: Allows referencing an external definition of this path item
|
|
30
|
+
summary: Optional string summary intended to apply to all operations in this path
|
|
31
|
+
description: Optional string description (may contain CommonMark syntax)
|
|
32
|
+
get: Definition of a GET operation on this path
|
|
33
|
+
put: Definition of a PUT operation on this path
|
|
34
|
+
post: Definition of a POST operation on this path
|
|
35
|
+
delete: Definition of a DELETE operation on this path
|
|
36
|
+
options: Definition of an OPTIONS operation on this path
|
|
37
|
+
head: Definition of a HEAD operation on this path
|
|
38
|
+
patch: Definition of a PATCH operation on this path
|
|
39
|
+
trace: Definition of a TRACE operation on this path
|
|
40
|
+
servers: Alternative server array to service all operations in this path
|
|
41
|
+
parameters: List of parameters that are applicable for all operations in this path
|
|
42
|
+
extensions: Specification extensions (x-* fields)
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
root_node: yaml.Node
|
|
46
|
+
ref: FieldSource[str] | None = fixed_field(metadata={"yaml_name": "$ref"})
|
|
47
|
+
summary: FieldSource[str] | None = fixed_field()
|
|
48
|
+
description: FieldSource[str] | None = fixed_field()
|
|
49
|
+
get: FieldSource[Operation] | None = fixed_field()
|
|
50
|
+
put: FieldSource[Operation] | None = fixed_field()
|
|
51
|
+
post: FieldSource[Operation] | None = fixed_field()
|
|
52
|
+
delete: FieldSource[Operation] | None = fixed_field()
|
|
53
|
+
options: FieldSource[Operation] | None = fixed_field()
|
|
54
|
+
head: FieldSource[Operation] | None = fixed_field()
|
|
55
|
+
patch: FieldSource[Operation] | None = fixed_field()
|
|
56
|
+
trace: FieldSource[Operation] | None = fixed_field()
|
|
57
|
+
servers: FieldSource[list["Server"]] | None = fixed_field()
|
|
58
|
+
parameters: FieldSource[list["Parameter | Reference"]] | None = fixed_field()
|
|
59
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def build(
|
|
63
|
+
root: yaml.Node, context: Context | None = None
|
|
64
|
+
) -> PathItem | ValueSource[YAMLInvalidValue]:
|
|
65
|
+
"""
|
|
66
|
+
Build a PathItem object from a YAML node.
|
|
67
|
+
|
|
68
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
69
|
+
model that provides complete source fidelity for inspection and validation.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
73
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
A PathItem object if the node is valid, or a ValueSource containing
|
|
77
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
78
|
+
and its source location for validation).
|
|
79
|
+
|
|
80
|
+
Example:
|
|
81
|
+
from ruamel.yaml import YAML
|
|
82
|
+
yaml = YAML()
|
|
83
|
+
root = yaml.compose('''
|
|
84
|
+
summary: User operations
|
|
85
|
+
get:
|
|
86
|
+
summary: List users
|
|
87
|
+
responses:
|
|
88
|
+
'200':
|
|
89
|
+
description: successful operation
|
|
90
|
+
post:
|
|
91
|
+
summary: Create user
|
|
92
|
+
responses:
|
|
93
|
+
'201':
|
|
94
|
+
description: user created
|
|
95
|
+
''')
|
|
96
|
+
path_item = build(root)
|
|
97
|
+
assert path_item.get is not None
|
|
98
|
+
assert path_item.post is not None
|
|
99
|
+
"""
|
|
100
|
+
context = context or Context()
|
|
101
|
+
|
|
102
|
+
# Use build_model for initial construction
|
|
103
|
+
path_item = build_model(root, PathItem, context=context)
|
|
104
|
+
|
|
105
|
+
# If build_model returned ValueSource (invalid node), return it immediately
|
|
106
|
+
if not isinstance(path_item, PathItem):
|
|
107
|
+
return path_item
|
|
108
|
+
|
|
109
|
+
# Manually handle nested complex fields
|
|
110
|
+
replacements = {}
|
|
111
|
+
for key_node, value_node in root.value:
|
|
112
|
+
key = context.yaml_constructor.construct_yaml_str(key_node)
|
|
113
|
+
|
|
114
|
+
# Handle HTTP method operation fields
|
|
115
|
+
if key in ("get", "put", "post", "delete", "options", "head", "patch", "trace"):
|
|
116
|
+
operation_obj = build_operation(value_node, context)
|
|
117
|
+
replacements[key] = FieldSource(
|
|
118
|
+
value=operation_obj, key_node=key_node, value_node=value_node
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Apply all replacements at once
|
|
122
|
+
if replacements:
|
|
123
|
+
path_item = replace(path_item, **replacements)
|
|
124
|
+
|
|
125
|
+
return path_item
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
from ruamel import yaml
|
|
4
|
+
|
|
5
|
+
from ..context import Context
|
|
6
|
+
from ..extractors import extract_extension_fields
|
|
7
|
+
from ..sources import KeySource, ValueSource, YAMLInvalidValue, YAMLValue
|
|
8
|
+
from .path_item import PathItem
|
|
9
|
+
from .path_item import build as build_path_item
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__all__ = ["Paths", "build"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True, slots=True)
|
|
16
|
+
class Paths:
|
|
17
|
+
"""
|
|
18
|
+
Paths Object representation for OpenAPI 3.0.
|
|
19
|
+
|
|
20
|
+
Holds the relative paths to the individual endpoints and their operations.
|
|
21
|
+
The paths are appended to the server URL to construct the full URL.
|
|
22
|
+
|
|
23
|
+
Path field names MUST begin with a forward slash (/). Path templating is supported
|
|
24
|
+
(e.g., /users/{id}). When matching URLs, concrete (non-templated) paths are matched
|
|
25
|
+
before templated paths. Templated paths with the same hierarchy but different templated
|
|
26
|
+
names are not allowed.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
root_node: The top-level node representing the entire Paths object in the original source file
|
|
30
|
+
paths: Map of path strings to Path Item Objects. Each key is a relative path that MUST begin
|
|
31
|
+
with a forward slash (/). Supports path templating with curly braces.
|
|
32
|
+
extensions: Specification extensions (x-* fields)
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
root_node: yaml.Node
|
|
36
|
+
paths: dict[KeySource[str], PathItem] = field(default_factory=dict)
|
|
37
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def build(root: yaml.Node, context: Context | None = None) -> Paths | ValueSource[YAMLInvalidValue]:
|
|
41
|
+
"""
|
|
42
|
+
Build a Paths object from a YAML node.
|
|
43
|
+
|
|
44
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
45
|
+
model that provides complete source fidelity for inspection and validation.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
49
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
A Paths object if the node is valid, or a ValueSource containing
|
|
53
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
54
|
+
and its source location for validation).
|
|
55
|
+
|
|
56
|
+
Example:
|
|
57
|
+
from ruamel.yaml import YAML
|
|
58
|
+
yaml = YAML()
|
|
59
|
+
root = yaml.compose('''
|
|
60
|
+
/users:
|
|
61
|
+
get:
|
|
62
|
+
summary: Get all users
|
|
63
|
+
responses:
|
|
64
|
+
'200':
|
|
65
|
+
description: Success
|
|
66
|
+
/users/{id}:
|
|
67
|
+
get:
|
|
68
|
+
summary: Get user by ID
|
|
69
|
+
parameters:
|
|
70
|
+
- name: id
|
|
71
|
+
in: path
|
|
72
|
+
required: true
|
|
73
|
+
schema:
|
|
74
|
+
type: integer
|
|
75
|
+
responses:
|
|
76
|
+
'200':
|
|
77
|
+
description: Success
|
|
78
|
+
''')
|
|
79
|
+
paths = build(root)
|
|
80
|
+
assert '/users' in {k.value for k in paths.paths.keys()}
|
|
81
|
+
"""
|
|
82
|
+
context = context or Context()
|
|
83
|
+
|
|
84
|
+
# Check if root is a MappingNode, if not return ValueSource with invalid data
|
|
85
|
+
if not isinstance(root, yaml.MappingNode):
|
|
86
|
+
value = context.yaml_constructor.construct_object(root, deep=True)
|
|
87
|
+
return ValueSource(value=value, value_node=root)
|
|
88
|
+
|
|
89
|
+
# Extract extensions first
|
|
90
|
+
extensions = extract_extension_fields(root, context)
|
|
91
|
+
extension_properties = {k.value for k in extensions.keys()}
|
|
92
|
+
|
|
93
|
+
# Process each field to determine if it's a path (not an extension)
|
|
94
|
+
paths = {}
|
|
95
|
+
|
|
96
|
+
for key_node, value_node in root.value:
|
|
97
|
+
key = context.yaml_constructor.construct_yaml_str(key_node)
|
|
98
|
+
|
|
99
|
+
if key not in extension_properties and key.startswith("/"):
|
|
100
|
+
# Path field (starts with / and not an extension) - build as Path Item
|
|
101
|
+
paths[KeySource(value=key, key_node=key_node)] = build_path_item(value_node, context)
|
|
102
|
+
|
|
103
|
+
# Create and return the Paths object with collected data
|
|
104
|
+
return Paths(
|
|
105
|
+
root_node=root,
|
|
106
|
+
paths=paths,
|
|
107
|
+
extensions=extensions,
|
|
108
|
+
)
|
|
@@ -2,14 +2,10 @@ from dataclasses import dataclass
|
|
|
2
2
|
|
|
3
3
|
from ruamel import yaml
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
from
|
|
7
|
-
from
|
|
8
|
-
from
|
|
9
|
-
FieldSource,
|
|
10
|
-
ValueSource,
|
|
11
|
-
YAMLInvalidValue,
|
|
12
|
-
)
|
|
5
|
+
from ..context import Context
|
|
6
|
+
from ..fields import fixed_field
|
|
7
|
+
from ..sources import FieldSource, ValueSource, YAMLInvalidValue
|
|
8
|
+
from .builders import build_model
|
|
13
9
|
|
|
14
10
|
|
|
15
11
|
__all__ = ["Reference", "build"]
|
|
@@ -20,7 +16,7 @@ class Reference:
|
|
|
20
16
|
"""
|
|
21
17
|
Reference Object representation for OpenAPI 3.0.
|
|
22
18
|
|
|
23
|
-
A simple object to allow referencing other components in the OpenAPI
|
|
19
|
+
A simple object to allow referencing other components in the OpenAPI Description,
|
|
24
20
|
internally and externally.
|
|
25
21
|
|
|
26
22
|
Note: In OpenAPI 3.0, Reference Objects only have the $ref field.
|
|
@@ -0,0 +1,108 @@
|
|
|
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 .media_type import MediaType
|
|
10
|
+
from .reference import Reference
|
|
11
|
+
from .reference import build as build_reference
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
__all__ = ["RequestBody", "build", "build_request_body_or_reference"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True, slots=True)
|
|
18
|
+
class RequestBody:
|
|
19
|
+
"""
|
|
20
|
+
Request Body Object representation for OpenAPI 3.0.
|
|
21
|
+
|
|
22
|
+
Describes a single request body.
|
|
23
|
+
|
|
24
|
+
Attributes:
|
|
25
|
+
root_node: The top-level node representing the entire Request Body object in the original source file
|
|
26
|
+
description: A brief description of the request body. CommonMark syntax MAY be used for rich text representation.
|
|
27
|
+
content: The content of the request body. The key is a media type or media type range and the value describes it.
|
|
28
|
+
For requests that match multiple keys, only the most specific key is applicable.
|
|
29
|
+
required: Determines if the request body is required in the request. Defaults to false.
|
|
30
|
+
extensions: Specification extensions (x-* fields)
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
root_node: yaml.Node
|
|
34
|
+
description: FieldSource[str] | None = fixed_field()
|
|
35
|
+
content: FieldSource[dict[KeySource[str], "MediaType"]] | None = fixed_field()
|
|
36
|
+
required: FieldSource[bool] | None = fixed_field()
|
|
37
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def build(
|
|
41
|
+
root: yaml.Node, context: Context | None = None
|
|
42
|
+
) -> RequestBody | ValueSource[YAMLInvalidValue]:
|
|
43
|
+
"""
|
|
44
|
+
Build a RequestBody object from a YAML node.
|
|
45
|
+
|
|
46
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
47
|
+
model that provides complete source fidelity for inspection and validation.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
51
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
A RequestBody object if the node is valid, or a ValueSource containing
|
|
55
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
56
|
+
and its source location for validation).
|
|
57
|
+
|
|
58
|
+
Example:
|
|
59
|
+
from ruamel.yaml import YAML
|
|
60
|
+
yaml = YAML()
|
|
61
|
+
root = yaml.compose('''
|
|
62
|
+
description: user to add to the system
|
|
63
|
+
required: true
|
|
64
|
+
content:
|
|
65
|
+
application/json:
|
|
66
|
+
schema:
|
|
67
|
+
type: object
|
|
68
|
+
''')
|
|
69
|
+
request_body = build(root)
|
|
70
|
+
assert request_body.description.value == 'user to add to the system'
|
|
71
|
+
"""
|
|
72
|
+
context = context or Context()
|
|
73
|
+
|
|
74
|
+
# Use build_model for initial construction
|
|
75
|
+
request_body = build_model(root, RequestBody, context=context)
|
|
76
|
+
|
|
77
|
+
# If build_model returned ValueSource (invalid node), return it immediately
|
|
78
|
+
if not isinstance(request_body, RequestBody):
|
|
79
|
+
return request_body
|
|
80
|
+
|
|
81
|
+
return request_body
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def build_request_body_or_reference(
|
|
85
|
+
node: yaml.Node, context: Context
|
|
86
|
+
) -> RequestBody | Reference | ValueSource[YAMLInvalidValue]:
|
|
87
|
+
"""
|
|
88
|
+
Build either a RequestBody or Reference from a YAML node.
|
|
89
|
+
|
|
90
|
+
This helper handles the polymorphic nature of OpenAPI where many fields
|
|
91
|
+
can contain either a RequestBody object or a Reference object ($ref).
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
node: The YAML node to parse
|
|
95
|
+
context: Parsing context
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
A RequestBody, Reference, or ValueSource if the node is invalid
|
|
99
|
+
"""
|
|
100
|
+
# Check if it's a reference (has $ref key)
|
|
101
|
+
if isinstance(node, yaml.MappingNode):
|
|
102
|
+
for key_node, _ in node.value:
|
|
103
|
+
key = context.yaml_constructor.construct_yaml_str(key_node)
|
|
104
|
+
if key == "$ref":
|
|
105
|
+
return build_reference(node, context)
|
|
106
|
+
|
|
107
|
+
# Otherwise, try to build as RequestBody
|
|
108
|
+
return build(node, context)
|
|
@@ -0,0 +1,104 @@
|
|
|
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 .link import Link
|
|
11
|
+
from .media_type import MediaType
|
|
12
|
+
from .reference import Reference
|
|
13
|
+
from .reference import build as build_reference
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = ["Response", "build", "build_response_or_reference"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True, slots=True)
|
|
20
|
+
class Response:
|
|
21
|
+
"""
|
|
22
|
+
Response Object representation for OpenAPI 3.0.
|
|
23
|
+
|
|
24
|
+
Describes a single response from an API Operation, including design-time, static links
|
|
25
|
+
to operations based on the response.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
root_node: The top-level node representing the entire Response object in the original source file
|
|
29
|
+
description: A description of the response. CommonMark syntax MAY be used for rich text representation.
|
|
30
|
+
headers: Maps a header name to its definition.
|
|
31
|
+
content: A map containing descriptions of potential response payloads. The key is a media type or media type range
|
|
32
|
+
and the value describes it. For responses that match multiple keys, only the most specific key is applicable.
|
|
33
|
+
links: A map of operations links that can be followed from the response. The key is a short name for the link,
|
|
34
|
+
following the naming constraints of the Components Object.
|
|
35
|
+
extensions: Specification extensions (x-* fields)
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
root_node: yaml.Node
|
|
39
|
+
description: FieldSource[str] | None = fixed_field()
|
|
40
|
+
headers: FieldSource[dict[KeySource[str], "Header | Reference"]] | None = fixed_field()
|
|
41
|
+
content: FieldSource[dict[KeySource[str], "MediaType"]] | None = fixed_field()
|
|
42
|
+
links: FieldSource[dict[KeySource[str], "Link | Reference"]] | None = fixed_field()
|
|
43
|
+
extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def build(
|
|
47
|
+
root: yaml.Node, context: Context | None = None
|
|
48
|
+
) -> Response | ValueSource[YAMLInvalidValue]:
|
|
49
|
+
"""
|
|
50
|
+
Build a Response object from a YAML node.
|
|
51
|
+
|
|
52
|
+
Preserves all source data as-is, regardless of type. This is a low-level/plumbing
|
|
53
|
+
model that provides complete source fidelity for inspection and validation.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
root: The YAML node to parse (should be a MappingNode)
|
|
57
|
+
context: Optional parsing context. If None, a default context will be created.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
A Response object if the node is valid, or a ValueSource containing
|
|
61
|
+
the invalid data if the root is not a MappingNode (preserving the invalid data
|
|
62
|
+
and its source location for validation).
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
from ruamel.yaml import YAML
|
|
66
|
+
yaml = YAML()
|
|
67
|
+
root = yaml.compose('''
|
|
68
|
+
description: successful operation
|
|
69
|
+
content:
|
|
70
|
+
application/json:
|
|
71
|
+
schema:
|
|
72
|
+
type: object
|
|
73
|
+
''')
|
|
74
|
+
response = build(root)
|
|
75
|
+
assert response.description.value == 'successful operation'
|
|
76
|
+
"""
|
|
77
|
+
return build_model(root, Response, context=context)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def build_response_or_reference(
|
|
81
|
+
node: yaml.Node, context: Context
|
|
82
|
+
) -> Response | Reference | ValueSource[YAMLInvalidValue]:
|
|
83
|
+
"""
|
|
84
|
+
Build either a Response or Reference from a YAML node.
|
|
85
|
+
|
|
86
|
+
This helper handles the polymorphic nature of OpenAPI where many fields
|
|
87
|
+
can contain either a Response object or a Reference object ($ref).
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
node: The YAML node to parse
|
|
91
|
+
context: Parsing context
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
A Response, Reference, or ValueSource if the node is invalid
|
|
95
|
+
"""
|
|
96
|
+
# Check if it's a reference (has $ref key)
|
|
97
|
+
if isinstance(node, yaml.MappingNode):
|
|
98
|
+
for key_node, _ in node.value:
|
|
99
|
+
key = context.yaml_constructor.construct_yaml_str(key_node)
|
|
100
|
+
if key == "$ref":
|
|
101
|
+
return build_reference(node, context)
|
|
102
|
+
|
|
103
|
+
# Otherwise, try to build as Response
|
|
104
|
+
return build(node, context)
|