Skip to content

Commit 803cea8

Browse files
committed
More docs, options, output, and error improvements
Use an alternate TOML formatter that handles arrays of long strings much better. Support @ as a command-line argument prefix indicating a file from whic to read options
1 parent 5e1de1c commit 803cea8

8 files changed

+172
-21
lines changed

README.md

+62-18
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
This repository contains the OpenAPI Compliance Project, the first
44
piece of which is the OpenAPI Specification Compliance Parser.
55

6+
The `oascomply` command-line tool takes an API description, as a single document or as several documents linked by JSON References (`$ref`) and indicates whether or not it is syntactically and semantically valid. It can optionally serialize an RDF graph of the parsed API description to `stdout` in any format supported by `rdflib`, as well as a custom format intended to be more human-readable.
7+
8+
The `oas30-schema` command-line tool is an OAS 3.0-specific JSON Schema implementation, based on the `jschon` implementation.
9+
10+
## Status
11+
612
The OAS Compliance Parser is expected to reach 1.0 status by
713
late 2023. The current status of the project is
814
[pre-Milestone 1](https://tinyurl.com/4kth84k8).
@@ -187,13 +193,20 @@ line-oriented format known as
187193
most RDF-based tools, but is also simple enough to be parsed directly
188194
by a regular expression, which can be found in the `oascomply.reparse` module.
189195

190-
To print the graph to stdout, use the `-o` option without an argument
191-
(diagnostic messages such as "Your API description is valid!" are printed
192-
to stderr). We'll set a short HTTPS URI as it's less noisy than full
193-
filesystem paths.
196+
To print the graph to stdout, use the `-o` option without an argument.
197+
Here, we redirect it to a `.nt` file, which is the standard N-Triples
198+
file extension (diagnostic messages such as
199+
"Your API description is valid!" are printed to stderr). We'll set a short
200+
HTTPS URI as it's less noisy than full filesystem paths:
194201

195202
```
196-
~/src/oascomply % oascomply -f tutorial/minimal.json https://example.com/minimal -o
203+
~/src/oascomply % oascomply -f tutorial/minimal.json https://example.com/minimal -o > minimal.nt
204+
Your API description is valid!
205+
```
206+
207+
Let's take a look at that output file:
208+
209+
```TTL
197210
<https://example.com/minimal#> <https://spec.openapis.org/compliance/ontology#paths> <https://example.com/minimal#/paths> .
198211
<https://example.com/minimal#/info> <http://www.w3.org/2000/01/rdf-schema#label> "Info" .
199212
<https://example.com/minimal> <http://www.w3.org/2000/01/rdf-schema#label> "minimal.json" .
@@ -214,7 +227,6 @@ filesystem paths.
214227
<https://example.com/minimal#> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://spec.openapis.org/compliance/ontology#3.0-OpenAPI> .
215228
<https://example.com/minimal#/paths> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <https://spec.openapis.org/compliance/ontology#3.0-Paths> .
216229
<https://example.com/minimal#> <https://spec.openapis.org/compliance/ontology#oasVersion> "3.0.3" .
217-
Your API description is valid!
218230
```
219231

220232
That's easy for machines to parse but a bit hard for people to read.
@@ -225,7 +237,7 @@ JSON-LD) for any format supported by
225237
[`rdflib`](https://rdflib.readthedocs.io/en/stable/). But it also offers
226238
a custom TOML format (`-o toml`) meant for human-friendly output:
227239

228-
```toml
240+
```TOML
229241
[namespaces]
230242
rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
231243
rdfs = "http://www.w3.org/2000/01/rdf-schema#"
@@ -266,12 +278,14 @@ oas = "https://spec.openapis.org/compliance/ontology#"
266278
Keep in mind that for programmatic use, libraries like Python's
267279
[`rdflib`](https://rdflib.readthedocs.io/en/stable/) can parse N-Triples
268280
directly and offer far more powerful features for working with the data.
269-
This TOML format is intended purely for human convenience.
281+
282+
This TOML format is intended purely for human convenience, and is somewhat
283+
experimental. Feedback is encouraged!
270284

271285
We'll talk more about namespaces and how this condensed format works further
272286
down, but lets dig into the N-Triples format first.
273287

274-
## Reading the output
288+
## Reading the N-Triples output
275289

276290
N-Triples may look like a bit of a mess with all of the URIs, but it's
277291
really pretty straightforward. Each line represents an RDF triple, which
@@ -298,10 +312,10 @@ generate it shows them in a side panel when you click on a node).
298312

299313
Every N-Triples line looks like one of the following three structures:[^lang]
300314

301-
```
302-
<subject concept> <relationship> <object concept> .
303-
<subject concept> <relationship> "string literal value" .
304-
<subject concept> <relationship> "literal value"^^<data type> .
315+
```TTL
316+
<subject_concept> <relationship> <object_concept> .
317+
<subject_concept> <relationship> "string literal value" .
318+
<subject_concept> <relationship> "literal value"^^<datatype> .
305319
```
306320

307321
The `.` terminates the line, and is mostly there to make this format
@@ -311,10 +325,10 @@ Since the same node can appear in either the subject or object position in
311325
many triples, these lines in the output connect through shared nodes to form
312326
a graph:
313327

314-
```
315-
<a> <x> <b>
316-
<b> <y> <c>
317-
<a> <z> "d"
328+
```TTL
329+
<a> <x> <b> .
330+
<b> <y> <c> .
331+
<a> <z> "d" .
318332
```
319333

320334
This is a graph with three nodes, `<a>`, `<b>`, and `<c>`, with edges
@@ -348,7 +362,37 @@ OpenAPI concepts use the following namespace:
348362

349363
For OpenAPI object types, a version prefix, e.g. `3.0-Schema`, is part of the fragment. For relationships, including object fields with string, number, or boolean values, there is no version prefix. _(This may not remain the case, it will depend on feedback).
350364

351-
_**TODO:** Document human-friendly TOML format properly._
365+
## Reading the experimental TOML output
366+
367+
The TOML output format is an experiment in providing something a little
368+
more intuitive. Here's a portion of the earlier example for reference:
369+
370+
```TOML
371+
[namespaces]
372+
rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
373+
rdfs = "http://www.w3.org/2000/01/rdf-schema#"
374+
xsd = "http://www.w3.org/2001/XMLSchema#"
375+
schema = "https://schema.org/"
376+
oas = "https://spec.openapis.org/compliance/ontology#"
377+
"oas3.0" = "https://spec.openapis.org/compliance/ontology#3.0-"
378+
379+
["https://example.com/minimal"]
380+
"rdf:type" = "schema:DigitalDocument"
381+
"rdfs:label" = [ "minimal.json",]
382+
"oas:locatedAt" = [ "file:///Users/handrews/src/oascomply/tutorial/minimal.json", "xsd:anyURI",]
383+
"oas:root" = "https://example.com/minimal#"
384+
```
385+
386+
Currently the format is as follows:
387+
388+
* The first section, `[namespaces]`, defines the short names for each namespace, and the URI prefix the short name represents
389+
* The remaining section headings are subjects in the RDF triples
390+
* Under each heading, the keys are predicates (relationships) and the values are objects, forming a triple with the subject in the heading
391+
* String literal object values are one-element arrays
392+
* Typed literal object values are two-element arrays, with the datatype as the second element
393+
* Multiple objects for the same subject and predicate appear as arrays
394+
395+
While the two different uses of arrays is somewhat ambiguous for the two-element array case, in practice datatypes tend to be very recognizable. However, feedback on this is encouraged.
352396

353397
## Understanding error messages
354398

oascomply/.oasgraph.py.swp

44 KB
Binary file not shown.

oascomply/apidescription.py

+1
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ def format_help(self):
521521
parser = CustomArgumentParser(
522522
formatter_class=argparse.RawDescriptionHelpFormatter,
523523
epilog=HELP_EPILOG,
524+
fromfile_prefix_chars='@',
524525
)
525526
parser.add_argument(
526527
'-f',

oascomply/oas30dialect.py

+1
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ def validate_with_oas30():
594594
epilog=f'Note that the schema "{OAS30_DIALECT_METASCHEMA}" is '
595595
'*NOT* provided by the OpenAPI Initiative, but is part of the '
596596
'oascomply package (oascomply.schemas/oas/v3.0/base.json)',
597+
fromfile_prefix_chars='@',
597598
)
598599
parser.add_argument(
599600
'instance',

oascomply/oasgraph.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import rdflib
1313
from rdflib.namespace import RDF, RDFS, XSD
1414
import toml
15+
import dom_toml
1516
import yaml
1617

1718
import oascomply.resourceid as rid
@@ -142,7 +143,7 @@ def to_toml(self, *args, destination, order, **kwargs):
142143
data.setdefault(s_name, {})[p_name] = \
143144
self._objects_to_toml(s, p)
144145

145-
toml.dump(data, destination)
146+
toml.dump(data, destination, dom_toml.TomlEncoder())
146147

147148
def _pseudo_qname(self, term): #, namespaces):
148149
try:
@@ -396,7 +397,11 @@ def add_oasliterals(self, annotation, document, data, sourcemap):
396397
):
397398
literal = result.data
398399
literal_path = rid.JsonPtr(literal.path)
399-
literal_node = rdflib.Literal(literal.value)
400+
literal_node = (
401+
rdflib.Literal(literal.value, datatype=RDF.JSON)
402+
if literal.type in ('object', 'array')
403+
else rdflib.Literal(literal.value)
404+
)
400405
self._g.add((
401406
parent_uri,
402407
self.oas[relname],

poetry.lock

+90-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ regex = "^2023.5.5"
3333
idna = "^3.4"
3434
tonyg-rfc3339 = "^0.1"
3535
toml = "^0.10.2"
36+
dom-toml = "^0.6.1"
3637

3738
[build-system]
3839
requires = ["poetry-core"]

tutorial/references.args

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-d
2+
tutorial/references
3+
https://example.com/
4+
-f
5+
tutorial/references/openapi.json
6+
-f
7+
tutorial/references/pathitems/foo.json
8+
-f
9+
tutorial/references/schemas/bar.json
10+
Schema

0 commit comments

Comments
 (0)