amati 0.1.0__py3-none-any.whl → 0.1.1__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/__init__.py CHANGED
@@ -3,7 +3,9 @@ Amati is a specification validator, built to put a specification into
3
3
  a single datatype and validate on instantiation.
4
4
  """
5
5
 
6
- __version__ = "0.1.0"
6
+ import importlib.metadata
7
+
8
+ __version__ = importlib.metadata.version("amati")
7
9
 
8
10
  # Imports are here for convenience, they're not going to be used here
9
11
  # pylint: disable=unused-import
amati/amati.py CHANGED
@@ -37,10 +37,10 @@ def dispatch(data: JSONObject) -> tuple[BaseModel | None, list[ErrorDetails] | N
37
37
  version: JSONValue = data.get("openapi")
38
38
 
39
39
  if not isinstance(version, str):
40
- raise ValueError("A OpenAPI specification version must be a string.")
40
+ raise TypeError("A OpenAPI specification version must be a string.")
41
41
 
42
42
  if not version:
43
- raise ValueError("An OpenAPI Specfication must contain a version.")
43
+ raise TypeError("An OpenAPI Specfication must contain a version.")
44
44
 
45
45
  version_map: dict[str, str] = {
46
46
  "3.1.1": "311",
@@ -86,9 +86,19 @@ def check(original: JSONObject, validated: BaseModel) -> bool:
86
86
  return original_ == new_
87
87
 
88
88
 
89
- def run(file_path: str, consistency_check: bool = False, store_errors: bool = False):
89
+ def run(file_path: str | Path, consistency_check: bool = False):
90
90
  """
91
- Runs the full amati process
91
+ Runs the full amati process on a specific specification file.
92
+
93
+ * Parses the YAML or JSON specification, gunzipping if necessary.
94
+ * Validates the specification.
95
+ * Runs a consistency check on the ouput of the validation to verify
96
+ that the output is identical to the input.
97
+ * Stores any errors found during validation.
98
+
99
+ Args:
100
+ file_path: The specification to be validated
101
+ consistency_check: Whether or not to verify the output against the input
92
102
  """
93
103
 
94
104
  data = load_file(file_path)
@@ -101,25 +111,73 @@ def run(file_path: str, consistency_check: bool = False, store_errors: bool = Fa
101
111
  else:
102
112
  print("Consistency check failed")
103
113
 
104
- if errors and store_errors:
114
+ if errors:
105
115
  if not Path(".amati").exists():
106
116
  Path(".amati").mkdir()
107
117
 
108
- with open(".amati/pydantic.json", "w", encoding="utf-8") as f:
118
+ error_file = Path(file_path).parts[-1]
119
+
120
+ with open(f".amati/{error_file}.json", "w", encoding="utf-8") as f:
109
121
  f.write(jsonpickle.encode(errors, unpicklable=False)) # type: ignore
110
122
 
111
123
 
124
+ def discover(discover_dir: str = ".") -> list[Path]:
125
+ """
126
+ Finds OpenAPI Specification files to validate
127
+
128
+ Args:
129
+ discover_dir: The directory to search through.
130
+ Returns:
131
+ A list of paths to validate.
132
+ """
133
+
134
+ specs: list[Path] = []
135
+
136
+ if Path("openapi.json").exists():
137
+ specs.append(Path("openapi.json"))
138
+
139
+ if Path("openapi.yaml").exists():
140
+ specs.append(Path("openapi.yaml"))
141
+
142
+ if specs:
143
+ return specs
144
+
145
+ if discover_dir == ".":
146
+ raise FileNotFoundError(
147
+ "openapi.json or openapi.yaml can't be found, use --discover or --spec."
148
+ )
149
+
150
+ specs = specs + list(Path(discover_dir).glob("**/openapi.json"))
151
+ specs = specs + list(Path(discover_dir).glob("**/openapi.yaml"))
152
+
153
+ if not specs:
154
+ raise FileNotFoundError(
155
+ "openapi.json or openapi.yaml can't be found, use --spec."
156
+ )
157
+
158
+ return specs
159
+
160
+
112
161
  if __name__ == "__main__":
113
162
 
114
163
  import argparse
115
164
 
116
165
  parser = argparse.ArgumentParser(
117
166
  prog="amati",
118
- description="Test whether a OpenAPI specification is valid.",
167
+ description="""
168
+ Tests whether a OpenAPI specification is valid. Will look an openapi.json
169
+ or openapi.yaml file in the directory that amati is called from. If
170
+ --discover is set will search the directory tree. If the specification
171
+ does not follow the naming recommendation the --spec switch should be
172
+ used.
173
+ """,
119
174
  )
120
175
 
121
176
  parser.add_argument(
122
- "-s", "--spec", required=True, help="The specification to be parsed"
177
+ "-s",
178
+ "--spec",
179
+ required=False,
180
+ help="The specification to be parsed",
123
181
  )
124
182
 
125
183
  parser.add_argument(
@@ -131,13 +189,19 @@ if __name__ == "__main__":
131
189
  )
132
190
 
133
191
  parser.add_argument(
134
- "-se",
135
- "--store-errors",
192
+ "-d",
193
+ "--discover",
136
194
  required=False,
137
- action="store_true",
138
- help="Stores and errors in a file for visibility.",
195
+ default=".",
196
+ help="Searches the specified directory tree for openapi.yaml or openapi.json.",
139
197
  )
140
198
 
141
199
  args = parser.parse_args()
142
200
 
143
- run(args.spec, args.consistency_check, args.store_errors)
201
+ if args.spec:
202
+ specifications: list[Path] = [Path(args.spec)]
203
+ else:
204
+ specifications = discover(args.discover)
205
+
206
+ for specification in specifications:
207
+ run(specification, args.consistency_check)
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amati
3
- Version: 0.1.0
4
- Summary: Validates that a .yaml or .json file conforms to the OpenAPI Specifications 3.x. This is an ALPHA build.
3
+ Version: 0.1.1
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
7
7
  Author-email: Ben <2551337+ben-alexander@users.noreply.github.com>
@@ -1,6 +1,6 @@
1
- amati/__init__.py,sha256=C-4SGpCtZFCxS_PEPaGNFiKJu-gW5YxMSauYA-LxmzQ,449
1
+ amati/__init__.py,sha256=suTY0Rf540LRPtdkOJi9OolXlUlv-uPNDvem_2o5eVs,504
2
2
  amati/_resolve_forward_references.py,sha256=iOibCv_XuIUpe7qbRBtPzd7H5rvL-aldUzlXV_9FJaw,6511
3
- amati/amati.py,sha256=fl6RL5_RWtoSpxTkEcDsgeejSh8HynxPuKvU4F5EwXY,3775
3
+ amati/amati.py,sha256=L-kdIrXR_RTkShAKl4E2C4brHeDadbEBeNzRBGWaJjo,5661
4
4
  amati/exceptions.py,sha256=Rm0njRFjyYTa6KcrbfwDXOz8IqZraCoXo82sDKseQMY,645
5
5
  amati/file_handler.py,sha256=h95t7TDxDA_qr4rIe2bddCjh2Xw5Ht27yLK7zCQzT68,5085
6
6
  amati/logging.py,sha256=AZXQv4jXKy6NAxths7DbpUlOWAhkh3XZ6imBtYjkHxc,1323
@@ -30,8 +30,8 @@ amati/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
30
30
  amati/validators/generic.py,sha256=NehHehVimlsVHDgStRWYgn0MZyR-i78yIPP_lw6L1bU,3736
31
31
  amati/validators/oas304.py,sha256=5QrfvBRKNZnqGZZgG7VbdIkbvklW_1M9qHeBh55D-d4,33885
32
32
  amati/validators/oas311.py,sha256=F6ejYYtSrSPFQm2MneuzbtTtlw7hv7AkfrYHDOlpWDs,20776
33
- amati-0.1.0.dist-info/METADATA,sha256=5Up6rsMw3Vev44sHuGovORpjYrpKKZ0-fn3Fx0WTRbE,3695
34
- amati-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
- amati-0.1.0.dist-info/entry_points.txt,sha256=sacBb6g0f0ZJtNjNYx93_Xe4y5xzawvklCFVXup9ru0,37
36
- amati-0.1.0.dist-info/licenses/LICENSE,sha256=WAA01ZXeNs1bwpNWKR6aVucjtYjYm_iQIUYkCAENjqM,1070
37
- amati-0.1.0.dist-info/RECORD,,
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