Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/schema_salad/main.py @ 2:6af9afd405e9 draft
"planemo upload commit 0a63dd5f4d38a1f6944587f52a8cd79874177fc1"
author | shellac |
---|---|
date | Thu, 14 May 2020 14:56:58 -0400 |
parents | 26e78fe6e8c4 |
children |
comparison
equal
deleted
inserted
replaced
1:75ca89e9b81c | 2:6af9afd405e9 |
---|---|
1 """Command line interface to schema-salad.""" | |
2 from __future__ import absolute_import, print_function | |
3 | |
4 import argparse | |
5 import logging | |
6 import os | |
7 import sys | |
8 from typing import Any, Dict, List, Mapping, MutableSequence, Optional, Union, cast | |
9 | |
10 import pkg_resources # part of setuptools | |
11 import six | |
12 from rdflib.parser import Parser | |
13 from rdflib.plugin import register | |
14 from six.moves import urllib | |
15 from typing_extensions import Text # pylint: disable=unused-import | |
16 | |
17 from ruamel.yaml.comments import CommentedSeq | |
18 | |
19 from . import codegen, jsonld_context, schema | |
20 from .avro.schema import SchemaParseException | |
21 from .exceptions import ValidationException, to_one_line_messages | |
22 from .makedoc import makedoc | |
23 from .ref_resolver import Loader, file_uri | |
24 from .utils import json_dumps | |
25 | |
26 # move to a regular typing import when Python 3.3-3.6 is no longer supported | |
27 | |
28 | |
29 register("json-ld", Parser, "rdflib_jsonld.parser", "JsonLDParser") | |
30 _logger = logging.getLogger("salad") | |
31 | |
32 | |
33 def printrdf( | |
34 workflow, # type: str | |
35 wf, # type: Union[List[Dict[Text, Any]], Dict[Text, Any]] | |
36 ctx, # type: Dict[Text, Any] | |
37 sr, # type: str | |
38 ): | |
39 # type: (...) -> None | |
40 g = jsonld_context.makerdf(workflow, wf, ctx) | |
41 print(g.serialize(format=sr, encoding="utf-8").decode("utf-8")) | |
42 | |
43 | |
44 def main(argsl=None): # type: (Optional[List[str]]) -> int | |
45 if argsl is None: | |
46 argsl = sys.argv[1:] | |
47 | |
48 parser = argparse.ArgumentParser() | |
49 parser.add_argument( | |
50 "--rdf-serializer", | |
51 help="Output RDF serialization format used by --print-rdf" | |
52 "(one of turtle (default), n3, nt, xml)", | |
53 default="turtle", | |
54 ) | |
55 | |
56 parser.add_argument( | |
57 "--skip-schemas", | |
58 action="store_true", | |
59 default=False, | |
60 help="If specified, ignore $schemas sections.", | |
61 ) | |
62 parser.add_argument( | |
63 "--strict-foreign-properties", | |
64 action="store_true", | |
65 help="Strict checking of foreign properties", | |
66 default=False, | |
67 ) | |
68 | |
69 exgroup = parser.add_mutually_exclusive_group() | |
70 exgroup.add_argument( | |
71 "--print-jsonld-context", | |
72 action="store_true", | |
73 help="Print JSON-LD context for schema", | |
74 ) | |
75 exgroup.add_argument("--print-rdfs", action="store_true", help="Print RDF schema") | |
76 exgroup.add_argument("--print-avro", action="store_true", help="Print Avro schema") | |
77 | |
78 exgroup.add_argument( | |
79 "--print-rdf", | |
80 action="store_true", | |
81 help="Print corresponding RDF graph for document", | |
82 ) | |
83 exgroup.add_argument( | |
84 "--print-pre", action="store_true", help="Print document after preprocessing" | |
85 ) | |
86 exgroup.add_argument("--print-index", action="store_true", help="Print node index") | |
87 exgroup.add_argument( | |
88 "--print-metadata", action="store_true", help="Print document metadata" | |
89 ) | |
90 exgroup.add_argument( | |
91 "--print-inheritance-dot", | |
92 action="store_true", | |
93 help="Print graphviz file of inheritance", | |
94 ) | |
95 exgroup.add_argument( | |
96 "--print-fieldrefs-dot", | |
97 action="store_true", | |
98 help="Print graphviz file of field refs", | |
99 ) | |
100 | |
101 exgroup.add_argument( | |
102 "--codegen", | |
103 type=str, | |
104 metavar="language", | |
105 help="Generate classes in target language, currently supported: python, java", | |
106 ) | |
107 | |
108 parser.add_argument( | |
109 "--codegen-target", | |
110 type=str, | |
111 default=None, | |
112 help="Defaults to sys.stdout for python and ./ for Java", | |
113 ) | |
114 | |
115 parser.add_argument( | |
116 "--codegen-examples", | |
117 type=str, | |
118 metavar="directory", | |
119 default=None, | |
120 help="Directory of example documents for test case generation (Java only).", | |
121 ) | |
122 | |
123 exgroup.add_argument( | |
124 "--print-oneline", | |
125 action="store_true", | |
126 help="Print each error message in oneline", | |
127 ) | |
128 | |
129 exgroup.add_argument( | |
130 "--print-doc", action="store_true", help="Print HTML schema documentation page" | |
131 ) | |
132 | |
133 exgroup = parser.add_mutually_exclusive_group() | |
134 exgroup.add_argument( | |
135 "--strict", | |
136 action="store_true", | |
137 help="Strict validation (unrecognized or out of place fields are error)", | |
138 default=True, | |
139 dest="strict", | |
140 ) | |
141 exgroup.add_argument( | |
142 "--non-strict", | |
143 action="store_false", | |
144 help="Lenient validation (ignore unrecognized fields)", | |
145 default=True, | |
146 dest="strict", | |
147 ) | |
148 | |
149 exgroup = parser.add_mutually_exclusive_group() | |
150 exgroup.add_argument("--verbose", action="store_true", help="Default logging") | |
151 exgroup.add_argument( | |
152 "--quiet", action="store_true", help="Only print warnings and errors." | |
153 ) | |
154 exgroup.add_argument("--debug", action="store_true", help="Print even more logging") | |
155 | |
156 parser.add_argument( | |
157 "--only", | |
158 action="append", | |
159 help="Use with --print-doc, document only listed types", | |
160 ) | |
161 parser.add_argument( | |
162 "--redirect", | |
163 action="append", | |
164 help="Use with --print-doc, override default link for type", | |
165 ) | |
166 parser.add_argument( | |
167 "--brand", help="Use with --print-doc, set the 'brand' text in nav bar" | |
168 ) | |
169 parser.add_argument( | |
170 "--brandlink", help="Use with --print-doc, set the link for 'brand' in nav bar" | |
171 ) | |
172 parser.add_argument( | |
173 "--primtype", | |
174 default="#PrimitiveType", | |
175 help="Use with --print-doc, link to use for primitive types (string, int etc)", | |
176 ) | |
177 | |
178 parser.add_argument("schema", type=str, nargs="?", default=None) | |
179 parser.add_argument("document", type=str, nargs="?", default=None) | |
180 parser.add_argument( | |
181 "--version", "-v", action="store_true", help="Print version", default=None | |
182 ) | |
183 | |
184 args = parser.parse_args(argsl) | |
185 | |
186 if args.version is None and args.schema is None: | |
187 print("{}: error: too few arguments".format(sys.argv[0])) | |
188 return 1 | |
189 | |
190 if args.quiet: | |
191 _logger.setLevel(logging.WARN) | |
192 if args.debug: | |
193 _logger.setLevel(logging.DEBUG) | |
194 | |
195 pkg = pkg_resources.require("schema_salad") | |
196 if pkg: | |
197 if args.version: | |
198 print("{} Current version: {}".format(sys.argv[0], pkg[0].version)) | |
199 return 0 | |
200 else: | |
201 _logger.info("%s Current version: %s", sys.argv[0], pkg[0].version) | |
202 | |
203 # Get the metaschema to validate the schema | |
204 metaschema_names, metaschema_doc, metaschema_loader = schema.get_metaschema() | |
205 | |
206 # Load schema document and resolve refs | |
207 | |
208 schema_uri = args.schema | |
209 if not ( | |
210 urllib.parse.urlparse(schema_uri)[0] | |
211 and urllib.parse.urlparse(schema_uri)[0] in [u"http", u"https", u"file"] | |
212 ): | |
213 schema_uri = file_uri(os.path.abspath(schema_uri)) | |
214 schema_raw_doc = metaschema_loader.fetch(schema_uri) | |
215 | |
216 try: | |
217 schema_doc, schema_metadata = metaschema_loader.resolve_all( | |
218 schema_raw_doc, schema_uri | |
219 ) | |
220 except ValidationException as e: | |
221 _logger.error( | |
222 "Schema `%s` failed link checking:\n%s", | |
223 args.schema, | |
224 Text(e), | |
225 exc_info=(True if args.debug else False), | |
226 ) | |
227 _logger.debug("Index is %s", list(metaschema_loader.idx.keys())) | |
228 _logger.debug("Vocabulary is %s", list(metaschema_loader.vocab.keys())) | |
229 return 1 | |
230 except (RuntimeError) as e: | |
231 _logger.error( | |
232 "Schema `%s` read error:\n%s", | |
233 args.schema, | |
234 Text(e), | |
235 exc_info=(True if args.debug else False), | |
236 ) | |
237 return 1 | |
238 | |
239 if args.print_doc: | |
240 makedoc(args) | |
241 return 0 | |
242 | |
243 # Optionally print the schema after ref resolution | |
244 if not args.document and args.print_pre: | |
245 print(json_dumps(schema_doc, indent=4)) | |
246 return 0 | |
247 | |
248 if not args.document and args.print_index: | |
249 print(json_dumps(list(metaschema_loader.idx.keys()), indent=4)) | |
250 return 0 | |
251 | |
252 # Validate the schema document against the metaschema | |
253 try: | |
254 schema.validate_doc( | |
255 metaschema_names, schema_doc, metaschema_loader, args.strict | |
256 ) | |
257 except ValidationException as e: | |
258 _logger.error("While validating schema `%s`:\n%s", args.schema, Text(e)) | |
259 return 1 | |
260 | |
261 # Get the json-ld context and RDFS representation from the schema | |
262 metactx = schema.collect_namespaces(schema_metadata) | |
263 if "$base" in schema_metadata: | |
264 metactx["@base"] = schema_metadata["$base"] | |
265 if isinstance(schema_doc, CommentedSeq): | |
266 (schema_ctx, rdfs) = jsonld_context.salad_to_jsonld_context(schema_doc, metactx) | |
267 else: | |
268 raise ValidationException( | |
269 "Expected a CommentedSeq, got {}: {}.".format(type(schema_doc), schema_doc) | |
270 ) | |
271 | |
272 # Create the loader that will be used to load the target document. | |
273 document_loader = Loader(schema_ctx, skip_schemas=args.skip_schemas) | |
274 | |
275 if args.codegen: | |
276 codegen.codegen( | |
277 args.codegen, | |
278 cast(List[Dict[Text, Any]], schema_doc), | |
279 schema_metadata, | |
280 document_loader, | |
281 target=args.codegen_target, | |
282 examples=args.codegen_examples, | |
283 ) | |
284 return 0 | |
285 | |
286 # Make the Avro validation that will be used to validate the target | |
287 # document | |
288 if isinstance(schema_doc, MutableSequence): | |
289 avsc_obj = schema.make_avro(schema_doc, document_loader) | |
290 try: | |
291 avsc_names = schema.make_avro_schema_from_avro(avsc_obj) | |
292 except SchemaParseException as err: | |
293 _logger.error( | |
294 "Schema `%s` error:\n%s", | |
295 args.schema, | |
296 Text(err), | |
297 exc_info=((type(err), err, None) if args.debug else None), | |
298 ) | |
299 if args.print_avro: | |
300 print(json_dumps(avsc_obj, indent=4)) | |
301 return 1 | |
302 else: | |
303 _logger.error("Schema `%s` must be a list.", args.schema) | |
304 return 1 | |
305 | |
306 # Optionally print Avro-compatible schema from schema | |
307 if args.print_avro: | |
308 print(json_dumps(avsc_obj, indent=4)) | |
309 return 0 | |
310 | |
311 # Optionally print the json-ld context from the schema | |
312 if args.print_jsonld_context: | |
313 j = {"@context": schema_ctx} | |
314 print(json_dumps(j, indent=4, sort_keys=True)) | |
315 return 0 | |
316 | |
317 # Optionally print the RDFS graph from the schema | |
318 if args.print_rdfs: | |
319 print(rdfs.serialize(format=args.rdf_serializer).decode("utf-8")) | |
320 return 0 | |
321 | |
322 if args.print_metadata and not args.document: | |
323 print(json_dumps(schema_metadata, indent=4)) | |
324 return 0 | |
325 | |
326 if args.print_inheritance_dot: | |
327 schema.print_inheritance(schema_doc, sys.stdout) | |
328 return 0 | |
329 | |
330 if args.print_fieldrefs_dot: | |
331 schema.print_fieldrefs(schema_doc, document_loader, sys.stdout) | |
332 return 0 | |
333 | |
334 # If no document specified, all done. | |
335 if not args.document: | |
336 print("Schema `{}` is valid".format(args.schema)) | |
337 return 0 | |
338 | |
339 # Load target document and resolve refs | |
340 try: | |
341 uri = args.document | |
342 document, doc_metadata = document_loader.resolve_ref( | |
343 uri, strict_foreign_properties=args.strict_foreign_properties | |
344 ) | |
345 except ValidationException as e: | |
346 msg = to_one_line_messages(e) if args.print_oneline else six.text_type(e) | |
347 _logger.error( | |
348 "Document `%s` failed validation:\n%s", | |
349 args.document, | |
350 msg, | |
351 exc_info=args.debug, | |
352 ) | |
353 return 1 | |
354 | |
355 # Optionally print the document after ref resolution | |
356 if args.print_pre: | |
357 print(json_dumps(document, indent=4)) | |
358 return 0 | |
359 | |
360 if args.print_index: | |
361 print(json_dumps(list(document_loader.idx.keys()), indent=4)) | |
362 return 0 | |
363 | |
364 # Validate the user document against the schema | |
365 try: | |
366 schema.validate_doc( | |
367 avsc_names, | |
368 document, | |
369 document_loader, | |
370 args.strict, | |
371 strict_foreign_properties=args.strict_foreign_properties, | |
372 ) | |
373 except ValidationException as e: | |
374 msg = to_one_line_messages(e) if args.print_oneline else six.text_type(e) | |
375 _logger.error("While validating document `%s`:\n%s" % (args.document, msg)) | |
376 return 1 | |
377 | |
378 # Optionally convert the document to RDF | |
379 if args.print_rdf: | |
380 if isinstance(document, (Mapping, MutableSequence)): | |
381 printrdf(args.document, document, schema_ctx, args.rdf_serializer) | |
382 return 0 | |
383 else: | |
384 print("Document must be a dictionary or list.") | |
385 return 1 | |
386 | |
387 if args.print_metadata: | |
388 print(json_dumps(doc_metadata, indent=4)) | |
389 return 0 | |
390 | |
391 print("Document `{}` is valid".format(args.document)) | |
392 | |
393 return 0 | |
394 | |
395 | |
396 if __name__ == "__main__": | |
397 sys.exit(main(sys.argv[1:])) |