amati 0.1.1__py3-none-any.whl → 0.2__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.
@@ -23,23 +23,21 @@ from pydantic import (
23
23
  ConfigDict,
24
24
  Field,
25
25
  RootModel,
26
- ValidationError,
27
26
  model_validator,
28
27
  )
29
28
 
30
- from amati import AmatiValueError, Reference
29
+ from amati import AmatiValueError
31
30
  from amati import model_validators as mv
32
31
  from amati.fields import (
33
32
  SPDXURL,
34
33
  URI,
35
- HTTPStatusCode,
36
34
  SPDXIdentifier,
37
35
  )
38
36
  from amati.fields.commonmark import CommonMark
39
37
  from amati.fields.json import JSON
40
38
  from amati.fields.oas import OpenAPI
41
39
  from amati.fields.spdx_licences import VALID_LICENCES
42
- from amati.logging import Log, LogMixin
40
+ from amati.logging import LogMixin
43
41
  from amati.validators.generic import GenericObject, allow_extra_fields
44
42
  from amati.validators.oas304 import (
45
43
  CallbackObject,
@@ -53,6 +51,7 @@ from amati.validators.oas304 import (
53
51
  PathsObject,
54
52
  RequestBodyObject,
55
53
  ResponseObject,
54
+ ResponsesObject,
56
55
  )
57
56
  from amati.validators.oas304 import SecuritySchemeObject as OAS30SecuritySchemeObject
58
57
  from amati.validators.oas304 import (
@@ -84,10 +83,8 @@ class LicenceObject(GenericObject):
84
83
  # What difference does Optional make here?
85
84
  identifier: Optional[SPDXIdentifier] = None
86
85
  url: Optional[URI] = None
87
- _reference: ClassVar[Reference] = Reference(
88
- title=TITLE,
89
- url="https://spec.openapis.org/oas/v3.1.1.html#license-object",
90
- section="License Object",
86
+ _reference_uri: ClassVar[str] = URI(
87
+ "https://spec.openapis.org/oas/v3.1.1.html#license-object"
91
88
  )
92
89
 
93
90
  _not_url_and_identifier = mv.only_one_of(["url", "identifier"])
@@ -109,11 +106,13 @@ class LicenceObject(GenericObject):
109
106
  SPDXURL(self.url)
110
107
  except AmatiValueError:
111
108
  LogMixin.log(
112
- Log(
113
- message=f"{self.url} is not a valid SPDX URL",
114
- type=Warning,
115
- reference=self._reference,
116
- )
109
+ {
110
+ "msg": f"{str(self.url)} is not a valid SPDX URL",
111
+ "type": "warning",
112
+ "loc": (self.__class__.__name__,),
113
+ "input": self.url,
114
+ "url": self._reference_uri,
115
+ }
117
116
  )
118
117
 
119
118
  # Both Identifier and URI, technically invalid, but should check if
@@ -124,11 +123,13 @@ class LicenceObject(GenericObject):
124
123
  and str(self.url) not in VALID_LICENCES[self.identifier]
125
124
  ):
126
125
  LogMixin.log(
127
- Log(
128
- message=f"{self.url} is not associated with the identifier {self.identifier}", # pylint: disable=line-too-long
129
- type=Warning,
130
- reference=self._reference,
131
- )
126
+ {
127
+ "msg": f"{self.url} is not associated with the identifier {self.identifier}", # pylint: disable=line-too-long
128
+ "type": "warning",
129
+ "loc": (self.__class__.__name__,),
130
+ "input": self.model_dump_json(),
131
+ "url": self._reference_uri,
132
+ }
132
133
  )
133
134
 
134
135
  return self
@@ -149,10 +150,8 @@ class ReferenceObject(GenericObject):
149
150
  ref: URI = Field(alias="$ref")
150
151
  summary: Optional[str]
151
152
  description: Optional[CommonMark]
152
- _reference: ClassVar[Reference] = Reference(
153
- title=TITLE,
154
- url="https://spec.openapis.org/oas/v3.1.1.html#reference-object",
155
- section="Reference Object",
153
+ _reference_uri: ClassVar[str] = (
154
+ "https://spec.openapis.org/oas/v3.1.1.html#reference-object"
156
155
  )
157
156
 
158
157
 
@@ -169,10 +168,8 @@ class InfoObject(GenericObject):
169
168
  contact: Optional[ContactObject] = None
170
169
  license: Optional[LicenceObject] = None
171
170
  version: str
172
- _reference: ClassVar[Reference] = Reference(
173
- title=TITLE,
174
- url="https://spec.openapis.org/oas/3.1.1.html#info-object",
175
- section="Info Object",
171
+ _reference_uri: ClassVar[str] = (
172
+ "https://spec.openapis.org/oas/3.1.1.html#info-object"
176
173
  )
177
174
 
178
175
 
@@ -187,10 +184,8 @@ class DiscriminatorObject(GenericObject):
187
184
  # properly.
188
185
  propertyName: str
189
186
  mapping: Optional[dict[str, str | URI]] = None
190
- _reference: ClassVar[Reference] = Reference(
191
- title=TITLE,
192
- url="https://spec.openapis.org/oas/v3.1.1.html#discriminator-object",
193
- section="Discriminator Object",
187
+ _reference_uri: ClassVar[str] = (
188
+ "https://spec.openapis.org/oas/v3.1.1.html#discriminator-object"
194
189
  )
195
190
 
196
191
 
@@ -203,10 +198,8 @@ class ServerVariableObject(GenericObject):
203
198
  enum: Optional[list[str]] = Field(None, min_length=1)
204
199
  default: str = Field(min_length=1)
205
200
  description: Optional[str | CommonMark] = None
206
- _reference: ClassVar[Reference] = Reference(
207
- title=TITLE,
208
- url="https://spec.openapis.org/oas/v3.1.1.html#server-variable-object",
209
- section="Server Variable Object",
201
+ _reference_uri: ClassVar[str] = (
202
+ "https://spec.openapis.org/oas/v3.1.1.html#server-variable-object"
210
203
  )
211
204
 
212
205
  @model_validator(mode="after")
@@ -222,11 +215,13 @@ class ServerVariableObject(GenericObject):
222
215
 
223
216
  if self.default not in self.enum:
224
217
  LogMixin.log(
225
- Log(
226
- message=f"The default value {self.default} is not in the enum list {self.enum}", # pylint: disable=line-too-long
227
- type=ValueError,
228
- reference=self._reference,
229
- )
218
+ {
219
+ "msg": f"The default value {self.default} is not in the enum list {self.enum}", # pylint: disable=line-too-long
220
+ "type": "value_error",
221
+ "loc": (self.__class__.__name__,),
222
+ "input": {"default": self.default, "enum": self.enum},
223
+ "url": self._reference_uri,
224
+ }
230
225
  )
231
226
 
232
227
  return self
@@ -249,10 +244,8 @@ class OperationObject(GenericObject):
249
244
  security: Optional[list["SecurityRequirementObject"]] = None
250
245
  servers: Optional[list[ServerObject]] = None
251
246
 
252
- _reference: ClassVar[Reference] = Reference(
253
- title=TITLE,
254
- url="https://spec.openapis.org/oas/v3.1.1.html#operation-object",
255
- section="Operation Object",
247
+ _reference_uri: ClassVar[str] = (
248
+ "https://spec.openapis.org/oas/v3.1.1.html#operation-object"
256
249
  )
257
250
 
258
251
 
@@ -267,6 +260,7 @@ PARAMETER_STYLES: set[str] = {
267
260
  }
268
261
 
269
262
 
263
+ @specification_extensions("x-")
270
264
  class ParameterObject(GenericObject):
271
265
  """Validates the OpenAPI Specification parameter object - §4.8.11"""
272
266
 
@@ -283,6 +277,9 @@ class ParameterObject(GenericObject):
283
277
  example: Optional[Any] = None
284
278
  examples: Optional[dict[str, "ExampleObject | ReferenceObject"]] = None
285
279
  content: Optional[dict[str, "MediaTypeObject"]] = None
280
+ _reference_uri: ClassVar[str] = (
281
+ "https://spec.openapis.org/oas/v3.1.1.html#parameter-object"
282
+ )
286
283
 
287
284
  _in_valid = mv.if_then(
288
285
  conditions={"in_": mv.UNKNOWN},
@@ -328,99 +325,10 @@ class MediaTypeObject(GenericObject):
328
325
  example: Optional[Any] = None
329
326
  examples: Optional[dict[str, ExampleObject | ReferenceObject]] = None
330
327
  encoding: Optional["EncodingObject"] = None
331
- _reference: ClassVar[Reference] = Reference(
332
- title=TITLE,
333
- url="https://spec.openapis.org/oas/v3.1.1.html#media-type-object",
334
- section="Tag Object",
335
- )
336
-
337
-
338
- type _ResponsesObjectReturnType = dict[str, "ReferenceObject | ResponseObject"]
339
-
340
-
341
- @specification_extensions("x-")
342
- class ResponsesObject(GenericObject):
343
- """
344
- Validates the OpenAPI Specification responses object - §4.8.16
345
- """
346
-
347
- model_config = ConfigDict(
348
- extra="allow",
349
- )
350
-
351
- default: Optional["ResponseObject | ReferenceObject"] = None
352
- _reference: ClassVar[Reference] = Reference(
353
- title=TITLE,
354
- url="https://spec.openapis.org/oas/v3.1.1.html#responses-object",
355
- section="Responses Object",
328
+ _reference_uri: ClassVar[str] = (
329
+ "https://spec.openapis.org/oas/v3.1.1.html#media-type-object"
356
330
  )
357
331
 
358
- @classmethod
359
- def _choose_model(
360
- cls, value: Any, field_name: str
361
- ) -> "ReferenceObject | ResponseObject":
362
- """
363
- Choose the model to use for validation based on the type of value.
364
-
365
- Args:
366
- value: The value to validate.
367
-
368
- Returns:
369
- The model class to use for validation.
370
- """
371
-
372
- message = f"{field_name} must be a ResponseObject or ReferenceObject, got {type(value)}" # pylint: disable=line-too-long
373
-
374
- try:
375
- return ResponseObject.model_validate(value)
376
- except ValidationError:
377
- try:
378
- return ReferenceObject.model_validate(value)
379
- except ValidationError as e:
380
- raise ValueError(message, ResponsesObject._reference) from e
381
-
382
- @model_validator(mode="before")
383
- @classmethod
384
- def validate_all_fields(cls, data: dict[str, Any]) -> _ResponsesObjectReturnType:
385
- """
386
- Validates the responses object.
387
- """
388
-
389
- validated_data: _ResponsesObjectReturnType = {}
390
-
391
- for field_name, value in data.items():
392
-
393
- # If the value is a specification extension, allow it
394
- if field_name.startswith("x-"):
395
- validated_data[field_name] = value
396
- continue
397
-
398
- # If the value is the fixed field, "default", allow it
399
- if field_name == "default":
400
- if isinstance(value, dict):
401
- validated_data[field_name] = ResponsesObject._choose_model(
402
- value, field_name
403
- )
404
- continue
405
-
406
- # Otherwise, if the field appears like a valid HTTP status code or a range
407
- if re.match(r"^[1-5]([0-9]{2}|XX)+$", str(field_name)):
408
-
409
- # Double check and raise a value error if not
410
- HTTPStatusCode(field_name)
411
-
412
- # and validate as a ResponseObject or ReferenceObject
413
- validated_data[field_name] = ResponsesObject._choose_model(
414
- value, field_name
415
- )
416
-
417
- continue
418
-
419
- # If the field is not a valid HTTP status code or "default"
420
- raise ValueError(f"Invalid type for numeric field '{field_name}'")
421
-
422
- return validated_data
423
-
424
332
 
425
333
  class SchemaObject(GenericObject):
426
334
  """
@@ -452,10 +360,8 @@ class SchemaObject(GenericObject):
452
360
  default=None, alias="$ref"
453
361
  ) # Reference to another schema
454
362
 
455
- _reference: ClassVar[Reference] = Reference(
456
- title=TITLE,
457
- url="https://spec.openapis.org/oas/v3.1.1.html#schema-object",
458
- section="Link Object",
363
+ _reference_uri: ClassVar[str] = (
364
+ "https://spec.openapis.org/oas/v3.1.1.html#schema-object"
459
365
  )
460
366
 
461
367
  @model_validator(mode="after")
@@ -491,11 +397,13 @@ class SchemaObject(GenericObject):
491
397
  validator_cls(meta_schema).validate(schema_dict) # type: ignore
492
398
  except JSONVSchemeValidationError as e:
493
399
  LogMixin.log(
494
- Log(
495
- message=f"Invalid JSON Schema: {e.message}",
496
- type=ValueError,
497
- reference=self._reference,
498
- )
400
+ {
401
+ "msg": f"Invalid JSON Schema: {e.message}",
402
+ "type": "value_error",
403
+ "loc": (self.__class__.__name__,),
404
+ "input": schema_dict,
405
+ "url": self._reference_uri,
406
+ }
499
407
  )
500
408
 
501
409
  return self
@@ -527,10 +435,8 @@ class SecurityRequirementObject(RootModel[list[_Requirement] | _Requirement]):
527
435
  # FIXME: The name must be a valid Security Scheme - need to use post-processing
528
436
  # FIXME If the security scheme is of type "oauth2" or "openIdConnect", then the
529
437
  # value must be a list
530
- _reference: ClassVar[Reference] = Reference(
531
- title=TITLE,
532
- url="https://spec.openapis.org/oas/3.1.1.html#security-requirement-object",
533
- section="Security Requirement Object",
438
+ _reference_uri: ClassVar[str] = (
439
+ "https://spec.openapis.org/oas/3.1.1.html#security-requirement-object"
534
440
  )
535
441
 
536
442
 
@@ -542,7 +448,7 @@ class ComponentsObject(GenericObject):
542
448
 
543
449
  schemas: Optional[dict[str, SchemaObject | ReferenceObject]] = None
544
450
  responses: Optional[dict[str, ResponseObject | ReferenceObject]] = None
545
- paremeters: Optional[dict[str, ParameterObject | ReferenceObject]] = None
451
+ parameters: Optional[dict[str, ParameterObject | ReferenceObject]] = None
546
452
  examples: Optional[dict[str, ExampleObject | ReferenceObject]] = None
547
453
  requestBodies: Optional[dict[str, RequestBodyObject | ReferenceObject]] = None
548
454
  headers: Optional[dict[str, HeaderObject | ReferenceObject]] = None
@@ -550,10 +456,8 @@ class ComponentsObject(GenericObject):
550
456
  links: Optional[dict[str, LinkObject | ReferenceObject]] = None
551
457
  callbacks: Optional[dict[str, CallbackObject | ReferenceObject]] = None
552
458
  pathItems: Optional[dict[str, PathItemObject]] = None
553
- _reference: ClassVar[Reference] = Reference(
554
- title=TITLE,
555
- url="https://spec.openapis.org/oas/v3.1.1.html#components-object",
556
- section="Components Object",
459
+ _reference_uri: ClassVar[str] = (
460
+ "https://spec.openapis.org/oas/v3.1.1.html#components-object"
557
461
  )
558
462
 
559
463
  @model_validator(mode="before")
@@ -608,8 +512,6 @@ class OpenAPIObject(GenericObject):
608
512
  security: Optional[list[SecurityRequirementObject]] = None
609
513
  tags: Optional[list[TagObject]] = None
610
514
  externalDocs: Optional[ExternalDocumentationObject] = None
611
- _reference: ClassVar[Reference] = Reference(
612
- title=TITLE,
613
- url="https://spec.openapis.org/oas/3.1.1.html#openapi-object",
614
- section="OpenAPI Object",
515
+ _reference_uri: ClassVar[str] = (
516
+ "https://spec.openapis.org/oas/3.1.1.html#openapi-object"
615
517
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amati
3
- Version: 0.1.1
3
+ Version: 0.2
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/ben-alexander/amati
6
6
  Project-URL: Issues, https://github.com/ben-alexander/amati/issues
@@ -15,6 +15,7 @@ Classifier: Topic :: Software Development :: Testing :: Acceptance
15
15
  Requires-Python: >=3.13
16
16
  Requires-Dist: abnf>=2.3.1
17
17
  Requires-Dist: idna>=3.10
18
+ Requires-Dist: jinja2>=3.1.6
18
19
  Requires-Dist: jsonpickle>=4.1.1
19
20
  Requires-Dist: jsonschema>=4.24.0
20
21
  Requires-Dist: pydantic>=2.11.5
@@ -23,26 +24,64 @@ Description-Content-Type: text/markdown
23
24
 
24
25
  # amati
25
26
 
26
- A programme designed to validate that a file conforms to [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.1.html) (OAS).
27
-
28
- Currently a proof of concept.
27
+ amati is designed to validate that a file conforms to the [OpenAPI Specification v3.x](https://spec.openapis.org/) (OAS).
29
28
 
30
29
  ## Name
31
30
 
32
31
  amati means to observe in Malay, especially with attention to detail. It's also one of the plurals of beloved or favourite in Italian.
33
32
 
33
+ ## Usage
34
+
35
+ ```sh
36
+ python amati/amati.py --help
37
+ usage: amati [-h] [-s SPEC] [-cc] [-d DISCOVER] [-l] [-hr]
38
+
39
+ Tests whether a OpenAPI specification is valid. Will look an openapi.json or openapi.yaml file in the directory that
40
+ amati is called from. If --discover is set will search the directory tree. If the specification does not follow the
41
+ naming recommendation the --spec switch should be used. Creates a file <filename>.errors.json alongside the original
42
+ specification containing a JSON representation of all the errors.
43
+
44
+ options:
45
+ -h, --help show this help message and exit
46
+ -s, --spec SPEC The specification to be parsed
47
+ -cc, --consistency-check
48
+ Runs a consistency check between the input specification and the parsed specification
49
+ -d, --discover DISCOVER
50
+ Searches the specified directory tree for openapi.yaml or openapi.json.
51
+ -l, --local Store errors local to the caller in a file called <file-name>.errors.json; a .amati/ directory
52
+ will be created.
53
+ -hr, --html-report Creates an HTML report of the errors, called <file-name>.errors.html, alongside the original
54
+ file or in a .amati/ directory if the --local switch is used
55
+ ```
56
+
57
+ A Dockerfile is available on [DockerHub](https://hub.docker.com/r/benale/amati/tags)
58
+
59
+ To run against a specific specification the location of the specification needs to be mounted in the container.
60
+
61
+ ```sh
62
+ docker run -v "<path-to-mount>:/<mount-name> amati <options>
63
+ ```
64
+
65
+ e.g.
66
+
67
+ ```sh
68
+ docker run -v /Users/myuser/myrepo:/data amati --spec data/myspec.yaml --hr
69
+ ```
70
+
34
71
  ## Architecture
35
72
 
36
73
  This uses Pydantic, especially the validation, and Typing to construct the entire OAS as a single data type. Passing a dictionary to the top-level data type runs all the validation in the Pydantic models constructing a single set of inherited classes and datatypes that validate that the API specification is accurate.
37
74
 
38
75
  Where the specification conforms, but relies on implementation-defined behavior (e.g. [data type formats](https://spec.openapis.org/oas/v3.1.1.html#data-type-format)), a warning will be raised.
39
76
 
40
- ## Requirements
77
+ ## Contributing
78
+
79
+ ### Requirements
41
80
 
42
81
  * The latest version of [uv](https://docs.astral.sh/uv/)
43
82
  * [git 2.49+](https://git-scm.com/downloads/linux)
44
83
 
45
- ## Testing and formatting
84
+ ### Testing and formatting
46
85
 
47
86
  This project uses:
48
87
 
@@ -54,7 +93,7 @@ This project uses:
54
93
  * [Black](https://black.readthedocs.io/en/stable/index.html) for automated formatting
55
94
  * [isort](https://pycqa.github.io/isort/) for import sorting
56
95
 
57
- It's expected that there are no errors, no surviving mutants and 100% of the code is reached and executed.
96
+ It's expected that there are no errors and 100% of the code is reached and executed. The strategy for test coverage is based on parsing test specifications and not unit tests.
58
97
 
59
98
  amati runs tests on external specifications, detailed in `tests/data/.amati.tests.yaml`. To be able to run these tests the appropriate GitHub repos need to be local. Specific revisions of the repos can be downloaded by running
60
99
 
@@ -62,13 +101,15 @@ amati runs tests on external specifications, detailed in `tests/data/.amati.test
62
101
  python scripts/tests/setup_test_specs.py
63
102
  ```
64
103
 
65
- To run everything, from linting, type checking to downloading test specs run:
104
+ To run everything, from linting, type checking to downloading test specs and building and testing the Docker image run:
66
105
 
67
106
  ```sh
68
107
  sh bin/checks.sh
69
108
  ```
70
109
 
71
- ## Building
110
+ You will need to have Docker installed.
111
+
112
+ ### Building
72
113
 
73
114
  The project uses a [`pyproject.toml` file](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#writing-pyproject-toml) to determine what to build.
74
115
 
@@ -80,6 +121,27 @@ uv venv
80
121
  uv sync
81
122
  ```
82
123
 
124
+ ### Docker
125
+
126
+ A development Docker image is provided, `Dockerfile.dev`, to build:
127
+
128
+ ```sh
129
+ docker build -t amati -f Dockerfile .
130
+ ```
131
+
132
+ and to run against a specific specification the location of the specification needs to be mounted in the container.
133
+
134
+ ```sh
135
+ docker run -v "<path-to-mount>:/<mount-name> amati <options>
136
+ ```
137
+
138
+ This can be tested against a provided specification, from the root directory
139
+
140
+ ```sh
141
+ docker run --detach -v "$(pwd):/data" amati
142
+ ```
143
+
144
+
83
145
  ### Data
84
146
 
85
147
  There are some scripts to create the data needed by the project, for example, all the possible licences. If the data needs to be refreshed this can be done by running the contents of `/scripts/data`.
@@ -0,0 +1,37 @@
1
+ amati/__init__.py,sha256=bsPoaYcFmejsqQN6eDxcuGKXg8ZXgk1NoD6Hujwhkkw,428
2
+ amati/_error_handler.py,sha256=s_Nhnq8hz7xQP_yeCCJ8Hwzs5xyrxlisd1XFYYECtSY,1244
3
+ amati/_resolve_forward_references.py,sha256=iOibCv_XuIUpe7qbRBtPzd7H5rvL-aldUzlXV_9FJaw,6511
4
+ amati/amati.py,sha256=sgWQrlvvusK8EgdcsYkCZWUNiv0TAHV8jRivUCBByQA,7698
5
+ amati/exceptions.py,sha256=X_RDBVjcFn_gXPFkhKuREmm5nDCdGs4rBy6sZsXBJDo,609
6
+ amati/file_handler.py,sha256=h95t7TDxDA_qr4rIe2bddCjh2Xw5Ht27yLK7zCQzT68,5085
7
+ amati/logging.py,sha256=X37gLui5Y94X1mlJIzkt3fQDwPcHlZiP3QBnM5Ipric,1339
8
+ amati/model_validators.py,sha256=zKK9G-xaERc-e9AmWBLzCIGKkmpi0nMMx94N_nd8fs8,14979
9
+ amati/data/http-status-codes.json,sha256=xEGBlE7eCXaQFG2gNSeK1aCs7A8XxOe6JcXwAKxwWBU,10903
10
+ amati/data/iso9110.json,sha256=YLv6V8dPrgagjAnHUWKMmade5xboV_eJB9smnUfwgDY,1692
11
+ amati/data/media-types.json,sha256=tSRZTUqIQeiW5cmw5aDAWNqXLGcvX4gwwEkDL5H6lDg,47108
12
+ amati/data/schemes.json,sha256=47a16eEatxahMMAgSQXRiFF7FotiETKTkQcleqF5m6w,10252
13
+ amati/data/spdx-licences.json,sha256=s9DHaYn4PSLVAEKE6wHEu_Rs-VI73WmsvcEgXSU6TTk,255373
14
+ amati/data/tlds.json,sha256=wDio6l8toi54-cano3EUuH3zGEoBvivagKjgbpsCdYo,19235
15
+ amati/fields/__init__.py,sha256=YPFOs0RZu7JlVuMEAkp6w9mNa1zgIZ6-0Mh-2v2tm6g,565
16
+ amati/fields/_custom_types.py,sha256=zHQdzyntVEGbLSblOOdKNzpZTCkmpUZ4Ji6WS6TkcPc,2513
17
+ amati/fields/commonmark.py,sha256=ssRc_338xd76y0MXR9U5OMkFE1ARCy-CWVOMY7AB8SU,220
18
+ amati/fields/email.py,sha256=1jkRVT_uUrDS9Y_AilvWMm776rMYDPiqXM3nq8VZqGY,559
19
+ amati/fields/http_status_codes.py,sha256=PaoebUSul9ZPwmyM0XIrrQ_4dxV4U0NURzXtbQlQVMg,3370
20
+ amati/fields/iso9110.py,sha256=MCfPOC0vmRI0VhM2WmzQyFurHA9kpKR4_fBL2rzYqvw,1855
21
+ amati/fields/json.py,sha256=TsNMW5gcCc3tpjDd0Sew_8okzDQu6S_FLKjGGvoRVos,304
22
+ amati/fields/media.py,sha256=ZFgNHDr-kGzGToOH0RkV4xhuMW-KrVdYlU6_8-G1EHk,3132
23
+ amati/fields/oas.py,sha256=oRvruhRmY9VQtlqiPaRvGKeeOgjYE-JG5aUZYZay6Kg,1733
24
+ amati/fields/spdx_licences.py,sha256=0iXZYzdzElvYmnTrtJM07IODENMP7qd21knZ5eH-7ws,2794
25
+ amati/fields/uri.py,sha256=iLAStugKYt1md4vP9oYrrsmME2d7XF9vSnLb6q_D5EA,11967
26
+ amati/grammars/oas.py,sha256=vTMnJIxeiTC3gJATOo0RRZDlRsQOWkY6jG1VRzazLjM,1666
27
+ amati/grammars/rfc6901.py,sha256=ChpKnoPDTsaNMvJT_UCpY8xwbl9zWZcD36MjRsD8IpQ,656
28
+ amati/grammars/rfc7159.py,sha256=eksX1m7WRzQ9iGeANG1BgmsXbAhV6gQVRkPpLqPjq6U,2218
29
+ amati/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ amati/validators/generic.py,sha256=AYIHIuEHpf1p-lCynBp-YGaayIZOylzNgGi533ykVbc,3983
31
+ amati/validators/oas304.py,sha256=84sAc37azkgrOt29scjRtYtJGypnFZd5UkV9VGLsX8c,32472
32
+ amati/validators/oas311.py,sha256=FVMOjNXWlZhq6fgah0NGGPlgdcSZFgVxVbEwWnk4Sn4,17712
33
+ amati-0.2.dist-info/METADATA,sha256=pDJg9ueeR6-_otHva88kNPxiEy3e-AAMIRvxsc4RFhg,5916
34
+ amati-0.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
+ amati-0.2.dist-info/entry_points.txt,sha256=sacBb6g0f0ZJtNjNYx93_Xe4y5xzawvklCFVXup9ru0,37
36
+ amati-0.2.dist-info/licenses/LICENSE,sha256=WAA01ZXeNs1bwpNWKR6aVucjtYjYm_iQIUYkCAENjqM,1070
37
+ amati-0.2.dist-info/RECORD,,
amati/references.py DELETED
@@ -1,33 +0,0 @@
1
- """
2
- Represents a reference, declared here to not put in __init__.
3
- """
4
-
5
- from dataclasses import dataclass
6
- from typing import Optional, Sequence
7
-
8
-
9
- class AmatiReferenceException(Exception):
10
- message: str = "Cannot construct empty references"
11
-
12
-
13
- @dataclass
14
- class Reference:
15
- """
16
- Attributes:
17
- title : Title of the referenced content
18
- section : Section of the referenced content
19
- url : URL where the referenced content can be found
20
- """
21
-
22
- title: Optional[str] = None
23
- section: Optional[str] = None
24
- url: Optional[str] = None
25
-
26
- def __post_init__(self):
27
-
28
- if not self.title and not self.section and not self.url:
29
- raise AmatiReferenceException
30
-
31
-
32
- type ReferenceArray = Sequence[Reference]
33
- type References = Reference | ReferenceArray
@@ -1,37 +0,0 @@
1
- amati/__init__.py,sha256=suTY0Rf540LRPtdkOJi9OolXlUlv-uPNDvem_2o5eVs,504
2
- amati/_resolve_forward_references.py,sha256=iOibCv_XuIUpe7qbRBtPzd7H5rvL-aldUzlXV_9FJaw,6511
3
- amati/amati.py,sha256=L-kdIrXR_RTkShAKl4E2C4brHeDadbEBeNzRBGWaJjo,5661
4
- amati/exceptions.py,sha256=Rm0njRFjyYTa6KcrbfwDXOz8IqZraCoXo82sDKseQMY,645
5
- amati/file_handler.py,sha256=h95t7TDxDA_qr4rIe2bddCjh2Xw5Ht27yLK7zCQzT68,5085
6
- amati/logging.py,sha256=AZXQv4jXKy6NAxths7DbpUlOWAhkh3XZ6imBtYjkHxc,1323
7
- amati/model_validators.py,sha256=omKagnWKQkhMc7AF5JWYZaLGNwYe38jVlCGgTO71zsY,14645
8
- amati/references.py,sha256=nGMUKIMGqZMpZcdQ7r_gxkcGARh9RULNhVBMej-ZiJE,788
9
- amati/data/http-status-codes.json,sha256=xEGBlE7eCXaQFG2gNSeK1aCs7A8XxOe6JcXwAKxwWBU,10903
10
- amati/data/iso9110.json,sha256=YLv6V8dPrgagjAnHUWKMmade5xboV_eJB9smnUfwgDY,1692
11
- amati/data/media-types.json,sha256=tSRZTUqIQeiW5cmw5aDAWNqXLGcvX4gwwEkDL5H6lDg,47108
12
- amati/data/schemes.json,sha256=47a16eEatxahMMAgSQXRiFF7FotiETKTkQcleqF5m6w,10252
13
- amati/data/spdx-licences.json,sha256=s9DHaYn4PSLVAEKE6wHEu_Rs-VI73WmsvcEgXSU6TTk,255373
14
- amati/data/tlds.json,sha256=wDio6l8toi54-cano3EUuH3zGEoBvivagKjgbpsCdYo,19235
15
- amati/fields/__init__.py,sha256=YPFOs0RZu7JlVuMEAkp6w9mNa1zgIZ6-0Mh-2v2tm6g,565
16
- amati/fields/_custom_types.py,sha256=zHQdzyntVEGbLSblOOdKNzpZTCkmpUZ4Ji6WS6TkcPc,2513
17
- amati/fields/commonmark.py,sha256=ssRc_338xd76y0MXR9U5OMkFE1ARCy-CWVOMY7AB8SU,220
18
- amati/fields/email.py,sha256=335vaJJmpASmScYCliCyxGElPvLt3bflNuAL6p-KGCg,661
19
- amati/fields/http_status_codes.py,sha256=bxhZIAlHyf7gYHIhxub-u2xb8VbXsqk96Oe3SnZ8RPM,3466
20
- amati/fields/iso9110.py,sha256=0nCJqJ3KXRnyUvJGyiMZfLd5ngixZlZpcYqsORAPhjc,1971
21
- amati/fields/json.py,sha256=TsNMW5gcCc3tpjDd0Sew_8okzDQu6S_FLKjGGvoRVos,304
22
- amati/fields/media.py,sha256=rst8okknJCQiQlDYYR_DIckd65VYHAK4A98Fl8C26z0,3268
23
- amati/fields/oas.py,sha256=J8QegOIiGcqGziJEaYxalsGZAMjWOt85R30k4oQ7h6w,1980
24
- amati/fields/spdx_licences.py,sha256=vPBkQsxC2z4uyeS2iGrgMTXJKHSn3VLBo9LR1uIyyh0,2866
25
- amati/fields/uri.py,sha256=FryHcn3D74-wA0GK9qATMju1KtWmfFb6K-Cy6jfXDL4,12390
26
- amati/grammars/oas.py,sha256=vTMnJIxeiTC3gJATOo0RRZDlRsQOWkY6jG1VRzazLjM,1666
27
- amati/grammars/rfc6901.py,sha256=ChpKnoPDTsaNMvJT_UCpY8xwbl9zWZcD36MjRsD8IpQ,656
28
- amati/grammars/rfc7159.py,sha256=eksX1m7WRzQ9iGeANG1BgmsXbAhV6gQVRkPpLqPjq6U,2218
29
- amati/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- amati/validators/generic.py,sha256=NehHehVimlsVHDgStRWYgn0MZyR-i78yIPP_lw6L1bU,3736
31
- amati/validators/oas304.py,sha256=5QrfvBRKNZnqGZZgG7VbdIkbvklW_1M9qHeBh55D-d4,33885
32
- amati/validators/oas311.py,sha256=F6ejYYtSrSPFQm2MneuzbtTtlw7hv7AkfrYHDOlpWDs,20776
33
- amati-0.1.1.dist-info/METADATA,sha256=5vYhn9HWXqKAuVMrWW7MitP5tQaBxEQqdQCc6KGyeQk,3671
34
- amati-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
- amati-0.1.1.dist-info/entry_points.txt,sha256=sacBb6g0f0ZJtNjNYx93_Xe4y5xzawvklCFVXup9ru0,37
36
- amati-0.1.1.dist-info/licenses/LICENSE,sha256=WAA01ZXeNs1bwpNWKR6aVucjtYjYm_iQIUYkCAENjqM,1070
37
- amati-0.1.1.dist-info/RECORD,,
File without changes