amati 0.3.14__py3-none-any.whl → 0.3.16__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.
amati/fields/media.py CHANGED
@@ -8,7 +8,8 @@ from typing import cast
8
8
  from abnf import ParseError
9
9
  from abnf.grammars import rfc7231
10
10
 
11
- from amati import AmatiValueError, get
11
+ from amati import get
12
+ from amati.exceptions import AmatiValueError
12
13
  from amati.fields import Str as _Str
13
14
 
14
15
  reference_uri = "https://datatracker.ietf.org/doc/html/rfc7231#appendix-D"
amati/fields/oas.py CHANGED
@@ -6,7 +6,7 @@ from typing import ClassVar
6
6
 
7
7
  from abnf import ParseError
8
8
 
9
- from amati import AmatiValueError
9
+ from amati.exceptions import AmatiValueError
10
10
  from amati.fields import Str as _Str
11
11
  from amati.grammars import oas
12
12
 
@@ -5,7 +5,8 @@ Exchange (SPDX) licence list.
5
5
 
6
6
  from typing import Any, cast
7
7
 
8
- from amati import AmatiValueError, get
8
+ from amati import get
9
+ from amati.exceptions import AmatiValueError
9
10
  from amati.fields import Str as _Str
10
11
  from amati.fields.uri import URI
11
12
 
amati/fields/uri.py CHANGED
@@ -9,7 +9,8 @@ import idna
9
9
  from abnf import Node, ParseError, Rule
10
10
  from abnf.grammars import rfc3986, rfc3987
11
11
 
12
- from amati import AmatiValueError, get
12
+ from amati import get
13
+ from amati.exceptions import AmatiValueError
13
14
  from amati.fields import Str as _Str
14
15
  from amati.grammars import rfc6901
15
16
 
@@ -0,0 +1,8 @@
1
+ from typing import Any
2
+
3
+
4
+ def reference_object_disciminator(data: Any) -> str:
5
+ if isinstance(data, dict) and "$ref" in data:
6
+ return "ref"
7
+
8
+ return "other"
@@ -13,13 +13,14 @@ from typing import (
13
13
  cast,
14
14
  )
15
15
 
16
- from pydantic import BaseModel, ConfigDict, PrivateAttr
16
+ from pydantic import BaseModel, ConfigDict, PrivateAttr, ValidationInfo, model_validator
17
17
  from pydantic_core._pydantic_core import PydanticUndefined
18
18
 
19
19
  from amati._logging import Logger
20
+ from amati._references import URICollectorMixin
20
21
 
21
22
 
22
- class GenericObject(BaseModel):
23
+ class GenericObject(URICollectorMixin, BaseModel):
23
24
  """A generic model extending Pydantic BaseModel with enhanced validation.
24
25
 
25
26
  Provides additional functionality for handling extra fields, including pattern
@@ -35,35 +36,41 @@ class GenericObject(BaseModel):
35
36
  _reference_uri: ClassVar[str] = PrivateAttr()
36
37
  _extra_field_pattern: re.Pattern[str] | None = PrivateAttr()
37
38
 
38
- def __init__(self, **data: Any) -> None:
39
- """Initialize the model and validate extra fields.
40
-
41
- Logs any fields that are not recognized as valid model fields or aliases
39
+ @model_validator(mode="before")
40
+ @classmethod
41
+ def _validate_extra_fields(cls, data: Any, info: ValidationInfo) -> Any:
42
+ """Logs any fields that are not recognized as valid model fields or aliases
42
43
  when extra fields are not allowed by the model configuration.
43
44
 
44
45
  Args:
45
- **data: Arbitrary keyword arguments representing model data.
46
+ data: dict representing model data.
46
47
  """
47
- super().__init__(**data)
48
-
49
- if self.model_config.get("extra") == "allow":
50
- return
48
+ if cls.model_config.get("extra") == "allow":
49
+ return data
51
50
 
52
51
  # If extra fields aren't allowed log those that aren't going to be added
53
52
  # to the model.
53
+
54
+ aliases = [field_info.alias for _, field_info in cls.model_fields.items()]
54
55
  for field in data:
55
- if field not in self.model_dump() and field not in self.get_field_aliases():
56
- message = f"{field} is not a valid field for {self.__repr_name__()}."
56
+ if field not in cls.model_fields and field not in aliases:
57
+ message = f"{field} is not a valid field for {cls.__name__}."
57
58
  Logger.log(
58
59
  {
59
60
  "msg": message,
60
61
  "type": "value_error",
61
- "loc": (self.__repr_name__(),),
62
- "input": field,
63
- "url": self._reference_uri,
62
+ "loc": (
63
+ info.context.get("current_document")
64
+ if info.context
65
+ else cls.__name__,
66
+ ),
67
+ "input": {field: data[field]},
68
+ "url": cls._reference_uri,
64
69
  }
65
70
  )
66
71
 
72
+ return data
73
+
67
74
  def model_post_init(self, __context: Any) -> None:
68
75
  """Validate extra fields against the configured pattern after initialization.
69
76
 
@@ -148,6 +155,7 @@ def allow_extra_fields(pattern: str | None = None) -> Callable[[type[T]], type[T
148
155
  "model_config": ConfigDict(extra="allow"),
149
156
  "_extra_field_pattern": pattern,
150
157
  }
158
+
151
159
  # Create a new class with the updated configuration
152
160
  return cast(type[T], type(cls.__name__, (cls,), namespace))
153
161
 
@@ -13,17 +13,21 @@ Note that per https://spec.openapis.org/oas/v3.0.4.html#relative-references-in-a
13
13
  """
14
14
 
15
15
  import re
16
- from typing import Any, ClassVar, Self
16
+ from typing import Annotated, Any, ClassVar, Self
17
17
 
18
18
  from jsonschema.exceptions import ValidationError as JSONVSchemeValidationError
19
19
  from jsonschema.protocols import Validator as JSONSchemaValidator
20
20
  from jsonschema.validators import validator_for # type: ignore
21
21
  from pydantic import (
22
22
  ConfigDict,
23
+ Discriminator,
23
24
  Field,
24
25
  RootModel,
26
+ SerializerFunctionWrapHandler,
27
+ Tag,
25
28
  ValidationError,
26
29
  field_validator,
30
+ model_serializer,
27
31
  model_validator,
28
32
  )
29
33
 
@@ -42,6 +46,7 @@ from amati.fields import (
42
46
  from amati.fields.commonmark import CommonMark
43
47
  from amati.fields.json import JSON
44
48
  from amati.fields.oas import OpenAPI, RuntimeExpression
49
+ from amati.validators._discriminators import reference_object_disciminator
45
50
  from amati.validators.generic import GenericObject, allow_extra_fields
46
51
 
47
52
  type JSONPrimitive = str | int | float | bool | None
@@ -57,6 +62,58 @@ TITLE = "OpenAPI Specification v3.0.4"
57
62
  specification_extensions = allow_extra_fields
58
63
 
59
64
 
65
+ CallbackReferenceType = Annotated[
66
+ Annotated["CallbackObject", Tag("other")]
67
+ | Annotated["ReferenceObject", Tag("ref")],
68
+ Discriminator(reference_object_disciminator),
69
+ ]
70
+
71
+ ExampleReferenceType = Annotated[
72
+ Annotated["ExampleObject", Tag("other")] | Annotated["ReferenceObject", Tag("ref")],
73
+ Discriminator(reference_object_disciminator),
74
+ ]
75
+
76
+ HeaderReferenceType = Annotated[
77
+ Annotated["HeaderObject", Tag("other")] | Annotated["ReferenceObject", Tag("ref")],
78
+ Discriminator(reference_object_disciminator),
79
+ ]
80
+
81
+ LinkReferenceType = Annotated[
82
+ Annotated["LinkObject", Tag("other")] | Annotated["ReferenceObject", Tag("ref")],
83
+ Discriminator(reference_object_disciminator),
84
+ ]
85
+
86
+
87
+ ParameterReferenceType = Annotated[
88
+ Annotated["ParameterObject", Tag("other")]
89
+ | Annotated["ReferenceObject", Tag("ref")],
90
+ Discriminator(reference_object_disciminator),
91
+ ]
92
+
93
+ ResponseReferenceType = Annotated[
94
+ Annotated["ResponseObject", Tag("other")]
95
+ | Annotated["ReferenceObject", Tag("ref")],
96
+ Discriminator(reference_object_disciminator),
97
+ ]
98
+
99
+ RequestBodyReferenceType = Annotated[
100
+ Annotated["RequestBodyObject", Tag("other")]
101
+ | Annotated["ReferenceObject", Tag("ref")],
102
+ Discriminator(reference_object_disciminator),
103
+ ]
104
+
105
+ SchemaReferenceType = Annotated[
106
+ Annotated["SchemaObject", Tag("other")] | Annotated["ReferenceObject", Tag("ref")],
107
+ Discriminator(reference_object_disciminator),
108
+ ]
109
+
110
+ SecuritySchemeReferenceType = Annotated[
111
+ Annotated["SecuritySchemeObject", Tag("other")]
112
+ | Annotated["ReferenceObject", Tag("ref")],
113
+ Discriminator(reference_object_disciminator),
114
+ ]
115
+
116
+
60
117
  @specification_extensions("x-")
61
118
  class ContactObject(GenericObject):
62
119
  """
@@ -150,6 +207,9 @@ class ExampleObject(GenericObject):
150
207
  "https://spec.openapis.org/oas/v3.0.4.html#example-object"
151
208
  )
152
209
 
210
+ # Note https://spec.openapis.org/oas/v3.1.1.html#example-object doesn't
211
+ # state that one of value and externalValue is required, however,
212
+ # there's very little point to an example object without either.
153
213
  _not_value_and_external_value = mv.only_one_of(
154
214
  ["value", "externalValue"], "warning"
155
215
  )
@@ -249,28 +309,6 @@ class PathsObject(GenericObject):
249
309
  return data
250
310
 
251
311
 
252
- @specification_extensions("x-")
253
- class OperationObject(GenericObject):
254
- """Validates the OpenAPI Specification operation object - §4.8.10"""
255
-
256
- tags: list[str] | None = None
257
- summary: str | None = None
258
- description: str | CommonMark | None = None
259
- externalDocs: ExternalDocumentationObject | None = None
260
- operationId: str | None = None
261
- parameters: list[ParameterObject | ReferenceObject] | None = None
262
- requestBody: RequestBodyObject | ReferenceObject | None = None
263
- responses: ResponsesObject
264
- callbacks: dict[str, CallbackObject | ReferenceObject] | None = None
265
- deprecated: bool | None = False
266
- security: list[SecurityRequirementObject] | None = None
267
- servers: list[ServerObject] | None = None
268
-
269
- _reference_uri: ClassVar[str] = (
270
- "https://spec.openapis.org/oas/v3.0.4.html#operation-object"
271
- )
272
-
273
-
274
312
  PARAMETER_STYLES: set[str] = {
275
313
  "matrix",
276
314
  "label",
@@ -295,10 +333,10 @@ class ParameterObject(GenericObject):
295
333
  style: str | None = None
296
334
  explode: bool | None = None
297
335
  allowReserved: bool | None = None
298
- schema_: SchemaObject | ReferenceObject | None = Field(alias="schema")
336
+ schema_: SchemaReferenceType | None = Field(alias="schema")
299
337
  example: Any | None = None
300
- examples: dict[str, ExampleObject | ReferenceObject] | None = None
301
- content: dict[str, MediaTypeObject] | None = None
338
+ examples: dict[str, ExampleReferenceType] | None = None
339
+ content: dict[str, "MediaTypeObject"] | None = None # noqa: UP037
302
340
  _reference_uri: ClassVar[str] = (
303
341
  "https://spec.openapis.org/oas/v3.0.4.html#parameter-object"
304
342
  )
@@ -356,10 +394,10 @@ class MediaTypeObject(GenericObject):
356
394
  Validates the OpenAPI Specification media type object - §4.8.14
357
395
  """
358
396
 
359
- schema_: SchemaObject | ReferenceObject | None = Field(alias="schema", default=None)
397
+ schema_: SchemaReferenceType | None = Field(alias="schema", default=None)
360
398
  # FIXME: Define example
361
399
  example: Any | None = None
362
- examples: dict[str, ExampleObject | ReferenceObject] | None = None
400
+ examples: dict[str, ExampleReferenceType] | None = None
363
401
  encoding: EncodingObject | None = None
364
402
  _reference_uri: ClassVar[str] = (
365
403
  "https://spec.openapis.org/oas/v3.0.4.html#media-type-object"
@@ -373,7 +411,7 @@ class EncodingObject(GenericObject):
373
411
  """
374
412
 
375
413
  contentType: str | None = None
376
- headers: dict[str, HeaderObject | ReferenceObject] | None = None
414
+ headers: dict[str, HeaderReferenceType] | None = None
377
415
  _reference_uri: ClassVar[str] = (
378
416
  "https://spec.openapis.org/oas/v3.0.4.html#encoding object-object"
379
417
  )
@@ -394,7 +432,7 @@ class EncodingObject(GenericObject):
394
432
  return value
395
433
 
396
434
 
397
- type _ResponsesObjectReturnType = dict[str, "ReferenceObject | ResponseObject"]
435
+ type _ResponsesObjectReturnType = dict[str, ResponseReferenceType]
398
436
 
399
437
 
400
438
  @specification_extensions(".*")
@@ -407,7 +445,7 @@ class ResponsesObject(GenericObject):
407
445
  extra="allow",
408
446
  )
409
447
 
410
- default: ResponseObject | ReferenceObject | None = None
448
+ default: ResponseReferenceType | None = None
411
449
  _reference_uri: ClassVar[str] = (
412
450
  "https://spec.openapis.org/oas/v3.0.4.html#responses-object"
413
451
  )
@@ -484,9 +522,9 @@ class ResponseObject(GenericObject):
484
522
  """
485
523
 
486
524
  description: str | CommonMark
487
- headers: dict[str, HeaderObject | ReferenceObject] | None = None
525
+ headers: dict[str, HeaderReferenceType] | None = None
488
526
  content: dict[str, MediaTypeObject] | None = None
489
- links: dict[str, LinkObject | ReferenceObject] | None = None
527
+ links: dict[str, LinkReferenceType] | None = None
490
528
  _reference_uri: ClassVar[str] = (
491
529
  "https://spec.openapis.org/oas/v3.0.4.html#response-object"
492
530
  )
@@ -603,9 +641,9 @@ class HeaderObject(GenericObject):
603
641
  # Schema fields
604
642
  style: str | None = Field(default="simple")
605
643
  explode: bool | None = Field(default=False)
606
- schema_: SchemaObject | ReferenceObject | None = Field(alias="schema", default=None)
644
+ schema_: SchemaReferenceType | None = Field(alias="schema", default=None)
607
645
  example: JSONValue | None = None
608
- examples: dict[str, ExampleObject | ReferenceObject] | None = None
646
+ examples: dict[str, ExampleReferenceType] | None = None
609
647
 
610
648
  # Content fields
611
649
  content: dict[str, MediaTypeObject] | None = None
@@ -781,6 +819,20 @@ class OAuthFlowObject(GenericObject):
781
819
  conditions={"type": "password"}, consequences={"tokenUrl": mv.UNKNOWN}
782
820
  )
783
821
 
822
+ @model_serializer(mode="wrap", when_used="json")
823
+ def serialize_model(
824
+ self, handler: SerializerFunctionWrapHandler
825
+ ) -> dict[str, object]:
826
+ """
827
+ Serializes the type field for JSON output only.
828
+ The Python output is used inside model_validators, so
829
+ a standard Field(exclude=True) cannot be used.
830
+ """
831
+
832
+ serialized = handler(self)
833
+ serialized.pop("type", None)
834
+ return serialized
835
+
784
836
 
785
837
  @specification_extensions("-x")
786
838
  class OAuthFlowsObject(GenericObject):
@@ -803,16 +855,14 @@ class OAuthFlowsObject(GenericObject):
803
855
  @classmethod
804
856
  def _push_down_type(cls, data: Any) -> Any:
805
857
  """
806
- Adds the type of OAuth2 flow, e.g. implicit, password to the child
858
+ Adds the type of OAuth2 flow, e.g. implicit, password, to the child
807
859
  OAuthFlowObject so that additional validation can be done on this object.
808
860
  """
809
861
 
810
- for k, v in data.items():
811
- if isinstance(v, OAuthFlowObject):
862
+ for field, value in data.items():
863
+ if isinstance(value, OAuthFlowObject):
812
864
  raise NotImplementedError("Must pass a dict")
813
-
814
- if v:
815
- data[k]["type"] = k
865
+ data[field]["type"] = field
816
866
 
817
867
  return data
818
868
 
@@ -888,6 +938,28 @@ class SecurityRequirementObject(RootModel[list[_Requirement] | _Requirement]):
888
938
  )
889
939
 
890
940
 
941
+ @specification_extensions("x-")
942
+ class OperationObject(GenericObject):
943
+ """Validates the OpenAPI Specification operation object - §4.8.10"""
944
+
945
+ tags: list[str] | None = None
946
+ summary: str | None = None
947
+ description: str | CommonMark | None = None
948
+ externalDocs: ExternalDocumentationObject | None = None
949
+ operationId: str | None = None
950
+ parameters: list[ParameterReferenceType] | None = None
951
+ requestBody: RequestBodyReferenceType | None = None
952
+ responses: ResponsesObject
953
+ callbacks: dict[str, CallbackReferenceType] | None = None
954
+ deprecated: bool | None = False
955
+ security: list[SecurityRequirementObject] | None = None
956
+ servers: list[ServerObject] | None = None
957
+
958
+ _reference_uri: ClassVar[str] = (
959
+ "https://spec.openapis.org/oas/v3.0.4.html#operation-object"
960
+ )
961
+
962
+
891
963
  @specification_extensions("x-")
892
964
  class PathItemObject(GenericObject):
893
965
  """Validates the OpenAPI Specification path item object - §4.8.9"""
@@ -904,7 +976,7 @@ class PathItemObject(GenericObject):
904
976
  patch: OperationObject | None = None
905
977
  trace: OperationObject | None = None
906
978
  servers: list[ServerObject] | None = None
907
- parameters: list[ParameterObject | ReferenceObject] | None = None
979
+ parameters: list[ParameterReferenceType] | None = None
908
980
  _reference_uri: ClassVar[str] = (
909
981
  "https://spec.openapis.org/oas/v3.0.4.html#path-item-object"
910
982
  )
@@ -917,14 +989,14 @@ class ComponentsObject(GenericObject):
917
989
  """
918
990
 
919
991
  schemas: dict[str, SchemaObject] | None = None
920
- responses: dict[str, ResponseObject | ReferenceObject] | None = None
921
- parameters: dict[str, ParameterObject | ReferenceObject] | None = None
922
- examples: dict[str, ExampleObject | ReferenceObject] | None = None
923
- requestBodies: dict[str, RequestBodyObject | ReferenceObject] | None = None
924
- headers: dict[str, HeaderObject | ReferenceObject] | None = None
925
- securitySchemes: dict[str, SecuritySchemeObject | ReferenceObject] | None = None
926
- links: dict[str, LinkObject | ReferenceObject] | None = None
927
- callbacks: dict[str, CallbackObject | ReferenceObject] | None = None
992
+ responses: dict[str, ResponseReferenceType] | None = None
993
+ parameters: dict[str, ParameterReferenceType] | None = None
994
+ examples: dict[str, ExampleReferenceType] | None = None
995
+ requestBodies: dict[str, RequestBodyReferenceType] | None = None
996
+ headers: dict[str, HeaderReferenceType] | None = None
997
+ securitySchemes: dict[str, SecuritySchemeReferenceType] | None = None
998
+ links: dict[str, LinkReferenceType] | None = None
999
+ callbacks: dict[str, CallbackReferenceType] | None = None
928
1000
  _reference_uri: ClassVar[str] = (
929
1001
  "https://spec.openapis.org/oas/v3.0.4.html#components-object"
930
1002
  )
@@ -13,15 +13,17 @@ Note that per https://spec.openapis.org/oas/v3.1.1.html#relative-references-in-a
13
13
  """
14
14
 
15
15
  import re
16
- from typing import Any, ClassVar, Self
16
+ from typing import Annotated, Any, ClassVar, Self
17
17
 
18
18
  from jsonschema.exceptions import ValidationError as JSONVSchemeValidationError
19
19
  from jsonschema.protocols import Validator as JSONSchemaValidator
20
20
  from jsonschema.validators import validator_for # type: ignore
21
21
  from pydantic import (
22
22
  ConfigDict,
23
+ Discriminator,
23
24
  Field,
24
25
  RootModel,
26
+ Tag,
25
27
  model_validator,
26
28
  )
27
29
 
@@ -37,6 +39,7 @@ from amati.fields.commonmark import CommonMark
37
39
  from amati.fields.json import JSON
38
40
  from amati.fields.oas import OpenAPI
39
41
  from amati.fields.spdx_licences import VALID_LICENCES
42
+ from amati.validators._discriminators import reference_object_disciminator
40
43
  from amati.validators.generic import GenericObject, allow_extra_fields
41
44
  from amati.validators.oas304 import (
42
45
  CallbackObject,
@@ -64,6 +67,58 @@ TITLE = "OpenAPI Specification v3.1.1"
64
67
  specification_extensions = allow_extra_fields
65
68
 
66
69
 
70
+ CallbackReferenceType = Annotated[
71
+ Annotated["CallbackObject", Tag("other")]
72
+ | Annotated["ReferenceObject", Tag("ref")],
73
+ Discriminator(reference_object_disciminator),
74
+ ]
75
+
76
+ ExampleReferenceType = Annotated[
77
+ Annotated["ExampleObject", Tag("other")] | Annotated["ReferenceObject", Tag("ref")],
78
+ Discriminator(reference_object_disciminator),
79
+ ]
80
+
81
+ HeaderReferenceType = Annotated[
82
+ Annotated["HeaderObject", Tag("other")] | Annotated["ReferenceObject", Tag("ref")],
83
+ Discriminator(reference_object_disciminator),
84
+ ]
85
+
86
+ LinkReferenceType = Annotated[
87
+ Annotated["LinkObject", Tag("other")] | Annotated["ReferenceObject", Tag("ref")],
88
+ Discriminator(reference_object_disciminator),
89
+ ]
90
+
91
+
92
+ ParameterReferenceType = Annotated[
93
+ Annotated["ParameterObject", Tag("other")]
94
+ | Annotated["ReferenceObject", Tag("ref")],
95
+ Discriminator(reference_object_disciminator),
96
+ ]
97
+
98
+ ResponseReferenceType = Annotated[
99
+ Annotated["ResponseObject", Tag("other")]
100
+ | Annotated["ReferenceObject", Tag("ref")],
101
+ Discriminator(reference_object_disciminator),
102
+ ]
103
+
104
+ RequestBodyReferenceType = Annotated[
105
+ Annotated["RequestBodyObject", Tag("other")]
106
+ | Annotated["ReferenceObject", Tag("ref")],
107
+ Discriminator(reference_object_disciminator),
108
+ ]
109
+
110
+ SchemaReferenceType = Annotated[
111
+ Annotated["SchemaObject", Tag("other")] | Annotated["ReferenceObject", Tag("ref")],
112
+ Discriminator(reference_object_disciminator),
113
+ ]
114
+
115
+ SecuritySchemeReferenceType = Annotated[
116
+ Annotated["SecuritySchemeObject", Tag("other")]
117
+ | Annotated["ReferenceObject", Tag("ref")],
118
+ Discriminator(reference_object_disciminator),
119
+ ]
120
+
121
+
67
122
  @specification_extensions("x-")
68
123
  class LicenceObject(GenericObject):
69
124
  """
@@ -226,28 +281,6 @@ class ServerVariableObject(GenericObject):
226
281
  return self
227
282
 
228
283
 
229
- @specification_extensions("x-")
230
- class OperationObject(GenericObject):
231
- """Validates the OpenAPI Specification operation object - §4.8.10"""
232
-
233
- tags: list[str] | None = None
234
- summary: str | None = None
235
- description: str | CommonMark | None = None
236
- externalDocs: ExternalDocumentationObject | None = None
237
- operationId: str | None = None
238
- parameters: list[ParameterObject | ReferenceObject] | None = None
239
- requestBody: RequestBodyObject | ReferenceObject | None = None
240
- responses: ResponsesObject | None = None
241
- callbacks: dict[str, CallbackObject | ReferenceObject] | None = None
242
- deprecated: bool | None = False
243
- security: list[SecurityRequirementObject] | None = None
244
- servers: list[ServerObject] | None = None
245
-
246
- _reference_uri: ClassVar[str] = (
247
- "https://spec.openapis.org/oas/v3.1.1.html#operation-object"
248
- )
249
-
250
-
251
284
  PARAMETER_STYLES: set[str] = {
252
285
  "matrix",
253
286
  "label",
@@ -272,10 +305,10 @@ class ParameterObject(GenericObject):
272
305
  style: str | None = None
273
306
  explode: bool | None = None
274
307
  allowReserved: bool | None = None
275
- schema_: SchemaObject | None = Field(alias="schema")
308
+ schema_: "SchemaObject | None" = Field(alias="schema") # noqa: UP037
276
309
  example: Any | None = None
277
- examples: dict[str, ExampleObject | ReferenceObject] | None = None
278
- content: dict[str, MediaTypeObject] | None = None
310
+ examples: dict[str, ExampleReferenceType] | None = None
311
+ content: dict[str, "MediaTypeObject"] | None = None # noqa: UP037
279
312
  _reference_uri: ClassVar[str] = (
280
313
  "https://spec.openapis.org/oas/v3.1.1.html#parameter-object"
281
314
  )
@@ -319,10 +352,10 @@ class MediaTypeObject(GenericObject):
319
352
  Validates the OpenAPI Specification media type object - §4.8.14
320
353
  """
321
354
 
322
- schema_: SchemaObject | None = Field(alias="schema", default=None)
355
+ schema_: "SchemaObject | None" = Field(alias="schema", default=None) # noqa: UP037
323
356
  # FIXME: Define example
324
357
  example: Any | None = None
325
- examples: dict[str, ExampleObject | ReferenceObject] | None = None
358
+ examples: dict[str, ExampleReferenceType] | None = None
326
359
  encoding: EncodingObject | None = None
327
360
  _reference_uri: ClassVar[str] = (
328
361
  "https://spec.openapis.org/oas/v3.1.1.html#media-type-object"
@@ -437,21 +470,43 @@ class SecurityRequirementObject(RootModel[list[_Requirement] | _Requirement]):
437
470
  )
438
471
 
439
472
 
473
+ @specification_extensions("x-")
474
+ class OperationObject(GenericObject):
475
+ """Validates the OpenAPI Specification operation object - §4.8.10"""
476
+
477
+ tags: list[str] | None = None
478
+ summary: str | None = None
479
+ description: str | CommonMark | None = None
480
+ externalDocs: ExternalDocumentationObject | None = None
481
+ operationId: str | None = None
482
+ parameters: list[ParameterReferenceType] | None = None
483
+ requestBody: RequestBodyReferenceType | None = None
484
+ responses: ResponsesObject | None = None
485
+ callbacks: dict[str, CallbackReferenceType] | None = None
486
+ deprecated: bool | None = False
487
+ security: list[SecurityRequirementObject] | None = None
488
+ servers: list[ServerObject] | None = None
489
+
490
+ _reference_uri: ClassVar[str] = (
491
+ "https://spec.openapis.org/oas/v3.1.1.html#operation-object"
492
+ )
493
+
494
+
440
495
  @specification_extensions("x-")
441
496
  class ComponentsObject(GenericObject):
442
497
  """
443
498
  Validates the OpenAPI Specification components object - §4.8.7
444
499
  """
445
500
 
446
- schemas: dict[str, SchemaObject | ReferenceObject] | None = None
447
- responses: dict[str, ResponseObject | ReferenceObject] | None = None
448
- parameters: dict[str, ParameterObject | ReferenceObject] | None = None
449
- examples: dict[str, ExampleObject | ReferenceObject] | None = None
450
- requestBodies: dict[str, RequestBodyObject | ReferenceObject] | None = None
451
- headers: dict[str, HeaderObject | ReferenceObject] | None = None
452
- securitySchemes: dict[str, SecuritySchemeObject | ReferenceObject] | None = None
453
- links: dict[str, LinkObject | ReferenceObject] | None = None
454
- callbacks: dict[str, CallbackObject | ReferenceObject] | None = None
501
+ schemas: dict[str, SchemaReferenceType] | None = None
502
+ responses: dict[str, ResponseReferenceType] | None = None
503
+ parameters: dict[str, ParameterReferenceType] | None = None
504
+ examples: dict[str, ExampleReferenceType] | None = None
505
+ requestBodies: dict[str, RequestBodyReferenceType] | None = None
506
+ headers: dict[str, HeaderReferenceType] | None = None
507
+ securitySchemes: dict[str, SecuritySchemeReferenceType] | None = None
508
+ links: dict[str, LinkReferenceType] | None = None
509
+ callbacks: dict[str, CallbackReferenceType] | None = None
455
510
  pathItems: dict[str, PathItemObject] | None = None
456
511
  _reference_uri: ClassVar[str] = (
457
512
  "https://spec.openapis.org/oas/v3.1.1.html#components-object"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amati
3
- Version: 0.3.14
3
+ Version: 0.3.16
4
4
  Summary: Validates that a .yaml or .json file conforms to the OpenAPI Specifications 3.x.
5
5
  Project-URL: Homepage, https://github.com/gwyli/amati
6
6
  Project-URL: Issues, https://github.com/gwyli/amati/issues