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.
Files changed (73) hide show
  1. jentic/apitools/openapi/datamodels/low/extractors.py +3 -3
  2. jentic/apitools/openapi/datamodels/low/v30/__init__.py +76 -0
  3. jentic/apitools/openapi/datamodels/low/v30/builders/__init__.py +312 -0
  4. jentic/apitools/openapi/datamodels/low/v30/callback.py +131 -0
  5. jentic/apitools/openapi/datamodels/low/v30/components.py +236 -0
  6. jentic/apitools/openapi/datamodels/low/v30/contact.py +4 -10
  7. jentic/apitools/openapi/datamodels/low/v30/discriminator.py +4 -9
  8. jentic/apitools/openapi/datamodels/low/v30/encoding.py +81 -0
  9. jentic/apitools/openapi/datamodels/low/v30/example.py +91 -0
  10. jentic/apitools/openapi/datamodels/low/v30/external_documentation.py +4 -10
  11. jentic/apitools/openapi/datamodels/low/v30/header.py +120 -0
  12. jentic/apitools/openapi/datamodels/low/v30/info.py +14 -23
  13. jentic/apitools/openapi/datamodels/low/v30/license.py +4 -10
  14. jentic/apitools/openapi/datamodels/low/v30/link.py +141 -0
  15. jentic/apitools/openapi/datamodels/low/v30/media_type.py +110 -0
  16. jentic/apitools/openapi/datamodels/low/v30/oauth_flow.py +4 -10
  17. jentic/apitools/openapi/datamodels/low/v30/oauth_flows.py +7 -15
  18. jentic/apitools/openapi/datamodels/low/v30/openapi.py +149 -0
  19. jentic/apitools/openapi/datamodels/low/v30/operation.py +134 -0
  20. jentic/apitools/openapi/datamodels/low/v30/parameter.py +123 -0
  21. jentic/apitools/openapi/datamodels/low/v30/path_item.py +125 -0
  22. jentic/apitools/openapi/datamodels/low/v30/paths.py +108 -0
  23. jentic/apitools/openapi/datamodels/low/v30/reference.py +5 -9
  24. jentic/apitools/openapi/datamodels/low/v30/request_body.py +108 -0
  25. jentic/apitools/openapi/datamodels/low/v30/response.py +104 -0
  26. jentic/apitools/openapi/datamodels/low/v30/responses.py +109 -0
  27. jentic/apitools/openapi/datamodels/low/v30/schema.py +81 -97
  28. jentic/apitools/openapi/datamodels/low/v30/security_requirement.py +14 -9
  29. jentic/apitools/openapi/datamodels/low/v30/security_scheme.py +42 -22
  30. jentic/apitools/openapi/datamodels/low/v30/server.py +111 -0
  31. jentic/apitools/openapi/datamodels/low/v30/server_variable.py +4 -10
  32. jentic/apitools/openapi/datamodels/low/v30/tag.py +8 -46
  33. jentic/apitools/openapi/datamodels/low/v30/xml.py +4 -10
  34. jentic/apitools/openapi/datamodels/low/v31/__init__.py +77 -0
  35. jentic/apitools/openapi/datamodels/low/v31/builders/__init__.py +347 -0
  36. jentic/apitools/openapi/datamodels/low/v31/callback.py +131 -0
  37. jentic/apitools/openapi/datamodels/low/v31/components.py +240 -0
  38. jentic/apitools/openapi/datamodels/low/v31/contact.py +61 -0
  39. jentic/apitools/openapi/datamodels/low/v31/discriminator.py +62 -0
  40. jentic/apitools/openapi/datamodels/low/v31/encoding.py +81 -0
  41. jentic/apitools/openapi/datamodels/low/v31/example.py +91 -0
  42. jentic/apitools/openapi/datamodels/low/v31/external_documentation.py +59 -0
  43. jentic/apitools/openapi/datamodels/low/v31/header.py +120 -0
  44. jentic/apitools/openapi/datamodels/low/v31/info.py +116 -0
  45. jentic/apitools/openapi/datamodels/low/v31/license.py +61 -0
  46. jentic/apitools/openapi/datamodels/low/v31/link.py +141 -0
  47. jentic/apitools/openapi/datamodels/low/v31/media_type.py +110 -0
  48. jentic/apitools/openapi/datamodels/low/v31/oauth_flow.py +65 -0
  49. jentic/apitools/openapi/datamodels/low/v31/oauth_flows.py +108 -0
  50. jentic/apitools/openapi/datamodels/low/v31/openapi.py +168 -0
  51. jentic/apitools/openapi/datamodels/low/v31/operation.py +133 -0
  52. jentic/apitools/openapi/datamodels/low/v31/parameter.py +123 -0
  53. jentic/apitools/openapi/datamodels/low/v31/path_item.py +125 -0
  54. jentic/apitools/openapi/datamodels/low/v31/paths.py +108 -0
  55. jentic/apitools/openapi/datamodels/low/v31/reference.py +65 -0
  56. jentic/apitools/openapi/datamodels/low/v31/request_body.py +108 -0
  57. jentic/apitools/openapi/datamodels/low/v31/response.py +104 -0
  58. jentic/apitools/openapi/datamodels/low/v31/responses.py +109 -0
  59. jentic/apitools/openapi/datamodels/low/v31/schema.py +498 -0
  60. jentic/apitools/openapi/datamodels/low/v31/security_requirement.py +106 -0
  61. jentic/apitools/openapi/datamodels/low/v31/security_scheme.py +129 -0
  62. jentic/apitools/openapi/datamodels/low/v31/server.py +111 -0
  63. jentic/apitools/openapi/datamodels/low/v31/server_variable.py +70 -0
  64. jentic/apitools/openapi/datamodels/low/v31/tag.py +63 -0
  65. jentic/apitools/openapi/datamodels/low/v31/xml.py +54 -0
  66. jentic_openapi_datamodels-1.0.0a20.dist-info/METADATA +379 -0
  67. jentic_openapi_datamodels-1.0.0a20.dist-info/RECORD +75 -0
  68. jentic/apitools/openapi/datamodels/low/model_builder.py +0 -129
  69. jentic_openapi_datamodels-1.0.0a18.dist-info/METADATA +0 -211
  70. jentic_openapi_datamodels-1.0.0a18.dist-info/RECORD +0 -27
  71. {jentic_openapi_datamodels-1.0.0a18.dist-info → jentic_openapi_datamodels-1.0.0a20.dist-info}/WHEEL +0 -0
  72. {jentic_openapi_datamodels-1.0.0a18.dist-info → jentic_openapi_datamodels-1.0.0a20.dist-info}/licenses/LICENSE +0 -0
  73. {jentic_openapi_datamodels-1.0.0a18.dist-info → jentic_openapi_datamodels-1.0.0a20.dist-info}/licenses/NOTICE +0 -0
@@ -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.1.
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
+ )
@@ -0,0 +1,65 @@
1
+ from dataclasses import dataclass
2
+
3
+ from ruamel import yaml
4
+
5
+ from ..context import Context
6
+ from ..fields import fixed_field
7
+ from ..sources import FieldSource, ValueSource, YAMLInvalidValue
8
+ from .builders import build_model
9
+
10
+
11
+ __all__ = ["Reference", "build"]
12
+
13
+
14
+ @dataclass(frozen=True, slots=True)
15
+ class Reference:
16
+ """
17
+ Reference Object representation for OpenAPI 3.1.
18
+
19
+ Allows for a reference to another document.
20
+
21
+ Attributes:
22
+ root_node: The top-level node representing the entire Reference object in the original source file
23
+ ref: REQUIRED. The reference identifier. This MUST be in the form of a URI.
24
+ summary: A short summary which by default SHOULD override that of the referenced component. If the referenced object-type does not allow a summary field, then this field has no effect.
25
+ description: A description which by default SHOULD override that of the referenced component. CommonMark syntax MAY be used for rich text representation. If the referenced object-type does not allow a description field, then this field has no effect.
26
+ """
27
+
28
+ root_node: yaml.Node
29
+ ref: FieldSource[str] | None = fixed_field(metadata={"yaml_name": "$ref"})
30
+ summary: FieldSource[str] | None = fixed_field()
31
+ description: FieldSource[str] | None = fixed_field()
32
+
33
+
34
+ def build(
35
+ root: yaml.Node, context: Context | None = None
36
+ ) -> Reference | ValueSource[YAMLInvalidValue]:
37
+ """
38
+ Build a Reference 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
+ A Reference 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('''
56
+ $ref: '#/components/schemas/Pet'
57
+ summary: A Pet reference
58
+ description: Reference to the Pet schema in components
59
+ ''')
60
+ reference = build(root)
61
+ assert reference.ref.value == '#/components/schemas/Pet'
62
+ assert reference.summary.value == 'A Pet reference'
63
+ assert reference.description.value == 'Reference to the Pet schema in components'
64
+ """
65
+ return build_model(root, Reference, context=context)
@@ -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.1.
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.1.
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)
@@ -0,0 +1,109 @@
1
+ import re
2
+ from dataclasses import dataclass, field
3
+ from typing import cast
4
+
5
+ from ruamel import yaml
6
+
7
+ from ..context import Context
8
+ from ..extractors import extract_extension_fields
9
+ from ..fields import fixed_field
10
+ from ..sources import FieldSource, KeySource, ValueSource, YAMLInvalidValue, YAMLValue
11
+ from .reference import Reference
12
+ from .response import Response, build_response_or_reference
13
+
14
+
15
+ __all__ = ["Responses", "build"]
16
+
17
+
18
+ @dataclass(frozen=True, slots=True)
19
+ class Responses:
20
+ """
21
+ Responses Object representation for OpenAPI 3.1.
22
+
23
+ A container for the expected responses of an operation. The container maps a HTTP response code
24
+ to the expected response.
25
+
26
+ Attributes:
27
+ root_node: The top-level node representing the entire Responses object in the original source file
28
+ default: The documentation of responses other than the ones declared for specific HTTP response codes.
29
+ Use this field to cover undeclared responses.
30
+ responses: Maps HTTP status codes to their Response objects. The key is the HTTP status code
31
+ (e.g., "200", "404", "4XX") and the value is a Response object or Reference.
32
+ extensions: Specification extensions (x-* fields)
33
+ """
34
+
35
+ root_node: yaml.Node
36
+ default: FieldSource[Response | Reference] | None = fixed_field()
37
+ responses: dict[KeySource[str], Response | Reference] = field(default_factory=dict)
38
+ extensions: dict[KeySource[str], ValueSource[YAMLValue]] = field(default_factory=dict)
39
+
40
+
41
+ def build(
42
+ root: yaml.Node, context: Context | None = None
43
+ ) -> Responses | ValueSource[YAMLInvalidValue]:
44
+ """
45
+ Build a Responses object from a YAML node.
46
+
47
+ Preserves all source data as-is, regardless of type. This is a low-level/plumbing
48
+ model that provides complete source fidelity for inspection and validation.
49
+
50
+ Args:
51
+ root: The YAML node to parse (should be a MappingNode)
52
+ context: Optional parsing context. If None, a default context will be created.
53
+
54
+ Returns:
55
+ A Responses object if the node is valid, or a ValueSource containing
56
+ the invalid data if the root is not a MappingNode (preserving the invalid data
57
+ and its source location for validation).
58
+
59
+ Example:
60
+ from ruamel.yaml import YAML
61
+ yaml = YAML()
62
+ root = yaml.compose('''
63
+ '200':
64
+ description: successful operation
65
+ '404':
66
+ description: not found
67
+ default:
68
+ description: unexpected error
69
+ ''')
70
+ responses = build(root)
71
+ assert '200' in {k.value for k in responses.responses.keys()}
72
+ """
73
+ context = context or Context()
74
+
75
+ # Check if root is a MappingNode, if not return ValueSource with invalid data
76
+ if not isinstance(root, yaml.MappingNode):
77
+ value = context.yaml_constructor.construct_object(root, deep=True)
78
+ return ValueSource(value=value, value_node=root)
79
+
80
+ # Process each field to determine if it's default or a status code response
81
+ responses = {}
82
+ default: FieldSource[Response | Reference] | None = None
83
+
84
+ for key_node, value_node in root.value:
85
+ key = context.yaml_constructor.construct_yaml_str(key_node)
86
+
87
+ if key == "default":
88
+ # Handle default response - can be Response or Reference
89
+ response_or_reference = build_response_or_reference(value_node, context)
90
+ default = cast(
91
+ FieldSource[Response | Reference],
92
+ FieldSource(value=response_or_reference, key_node=key_node, value_node=value_node),
93
+ )
94
+ elif _HTTP_STATUS_CODE_PATTERN.match(key):
95
+ # Valid HTTP status code (100-599) or pattern (1XX-5XX)
96
+ response_or_reference = build_response_or_reference(value_node, context)
97
+ responses[KeySource(value=key, key_node=key_node)] = response_or_reference
98
+
99
+ # Create and return the Responses object with collected data
100
+ return Responses(
101
+ root_node=root,
102
+ default=default,
103
+ responses=responses,
104
+ extensions=extract_extension_fields(root, context),
105
+ )
106
+
107
+
108
+ # Pattern for valid HTTP status codes: 100-599 or wildcard patterns (1XX-5XX)
109
+ _HTTP_STATUS_CODE_PATTERN = re.compile(r"^([1-5]XX|[1-5][0-9]{2})$")