Skip to content

Commit

Permalink
Validation mode warn no longer exits code 2
Browse files Browse the repository at this point in the history
The help message for `--validation-mode` is very specific:

> 'error' mode causes a non-zero exit status if any validation checks
> failed, while 'warn' does not.

In the actual implementation however we would print an error and exit
with code 2 for any validation check _except_ the augur version check.
Now, for `ValidationMode.WARN` we catch these errors and turn them into
warnings such that augur can exit code 0 as specified.

Note that during validation, any non-ValidationError exception will be
be fatal even in `WARN`. An example of this would be errors loading the
schema itself. See the following review comment for more:
<#1440 (comment)>
  • Loading branch information
jameshadfield committed Mar 19, 2024
1 parent af2abfe commit a43536c
Showing 1 changed file with 47 additions and 41 deletions.
88 changes: 47 additions & 41 deletions augur/util_support/node_data_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,49 +63,55 @@ def validate(self):
if self.validation_mode is ValidationMode.SKIP:
return # don't perform validation (i.e. skip it)

if self.annotations:
try:
validate_json(
self.annotations,
load_json_schema("schema-annotations.json"),
self.fname,
try:
if self.annotations:
try:
# validate_json will print any errors to STDERR
validate_json(
self.annotations,
load_json_schema("schema-annotations.json"),
self.fname,
)
except ValidateError as err:
raise ValidateError(
f"{self.fname} contains an `annotations` attribute of an invalid JSON format. Was it "
"produced by different version of augur the one you are currently using "
f" ({__version__})? Please check the program that produced that JSON file."
) from err

if not isinstance(self.nodes, dict):
raise ValidateError(
f"`nodes` value in {self.fname} is not a dictionary. Please check the formatting of this JSON!"
)

if not isinstance(self.branches, dict):
raise ValidateError(
f"`branches` value in {self.fname} is not a dictionary. Please check the formatting of this JSON!"
)
except ValidateError as err:
raise AugurError(
f"{self.fname} contains an `annotations` attribute of an invalid JSON format. Was it "
"produced by different version of augur the one you are currently using "
f" ({__version__})? Please check the program that produced that JSON file."
) from err

if not isinstance(self.nodes, dict):
raise AugurError(
f"`nodes` value in {self.fname} is not a dictionary. Please check the formatting of this JSON!"
)

if not isinstance(self.branches, dict):
raise AugurError(
f"`branches` value in {self.fname} is not a dictionary. Please check the formatting of this JSON!"
)

if not self.nodes and not self.branches:
print_err(
f"WARNING: {self.fname} has empty or nonexistent `nodes` and `branches`. Please check the formatting of this JSON!"
)

if self.is_generated_by_incompatible_augur:
msg = (
f"Augur version incompatibility detected: the JSON {self.fname} was generated by "
f"{self.generated_by}, which is incompatible with the current augur version "
f"({__version__}). We suggest you rerun the pipeline using the current version of "
"augur."
)
if self.validation_mode is ValidationMode.ERROR:
raise AugurError(msg)
elif self.validation_mode is ValidationMode.WARN:
print_err(f"WARNING: {msg}")
else:
raise ValueError(f"unknown validation mode: {self.validation_mode!r}")

if not self.nodes and not self.branches:
print_err(
f"WARNING: {self.fname} has empty or nonexistent `nodes` and `branches`. Please check the formatting of this JSON!"
)

if self.is_generated_by_incompatible_augur:
msg = (
f"Augur version incompatibility detected: the JSON {self.fname} was generated by "
f"{self.generated_by}, which is incompatible with the current augur version "
f"({__version__}). We suggest you rerun the pipeline using the current version of "
"augur."
)
raise ValidateError(msg)
except ValidateError as e:
if self.validation_mode is ValidationMode.WARN:
# string-representation of error mirrors how augur ultimately handles AugurError
print_err(f"WARNING: {e}")
else:
# Re-raising within an except block will use implicit chaining (via __context__)
# however since we ultimately catch AugurError and use a string representation
# this isn't particularly helpful. One day we may add a dev-flag to allow printing
# the traceback or similar
raise AugurError(*e.args)


class NodeDataObject(NodeDataFile):
Expand Down

0 comments on commit a43536c

Please sign in to comment.