|
6 | 6 | """ |
7 | 7 |
|
8 | 8 | import argparse |
| 9 | +import json |
9 | 10 | import sys |
10 | 11 | from contextlib import redirect_stdout |
11 | 12 |
|
| 13 | +import jsonschema |
| 14 | + |
12 | 15 | import app |
13 | 16 |
|
14 | 17 | import clams.app |
15 | 18 | from clams import AppMetadata |
| 19 | +from clams.envelop import EnvelopeError |
16 | 20 |
|
17 | 21 |
|
18 | 22 | def metadata_to_argparser(app_metadata: AppMetadata) -> argparse.ArgumentParser: |
@@ -81,11 +85,24 @@ def metadata_to_argparser(app_metadata: AppMetadata) -> argparse.ArgumentParser: |
81 | 85 | params[pname] = pvalue |
82 | 86 | else: |
83 | 87 | params[pname] = [pvalue] |
84 | | - if args.OUT_MMIF_FILE.name == '<stdout>': |
85 | | - with redirect_stdout(sys.stderr): |
| 88 | + # Mirror the HTTP server's error handling (see clams.restify): an invalid |
| 89 | + # input is reported and exits non-zero, while an app-level failure is |
| 90 | + # recorded as an error view instead of crashing with a raw traceback. |
| 91 | + try: |
| 92 | + if args.OUT_MMIF_FILE.name == '<stdout>': |
| 93 | + with redirect_stdout(sys.stderr): |
| 94 | + out_mmif = clamsapp.annotate(in_data, **params) |
| 95 | + else: |
86 | 96 | out_mmif = clamsapp.annotate(in_data, **params) |
87 | | - else: |
88 | | - out_mmif = clamsapp.annotate(in_data, **params) |
| 97 | + except (jsonschema.exceptions.ValidationError, json.JSONDecodeError, EnvelopeError) as e: |
| 98 | + detail = e.message if isinstance(e, jsonschema.exceptions.ValidationError) else str(e) |
| 99 | + print(f"Invalid input data. See below for validation error.\n\n{detail}", file=sys.stderr) |
| 100 | + sys.exit(1) |
| 101 | + except Exception: |
| 102 | + clamsapp.logger.exception("Error in annotation") |
| 103 | + out_mmif = clamsapp.record_error(in_data, **params).serialize(pretty=True) |
| 104 | + args.OUT_MMIF_FILE.write(out_mmif) |
| 105 | + sys.exit(1) |
89 | 106 | args.OUT_MMIF_FILE.write(out_mmif) |
90 | 107 | else: |
91 | 108 | arg_parser.print_help() |
|
0 commit comments