def main():
    # Load all available checker classes
    check_suite = CheckSuite()
    check_suite.load_all_available_checkers()

    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--test",
        "-t",
        "--test=",
        "-t=",
        default=[],
        action="append",
        help=("Select the Checks you want to perform. Defaults to 'acdd'"
              " if unspecified.  Versions of standards can be specified via "
              "`-t <test_standard>:<version>`.  If `<version>` is omitted, or "
              'is "latest", the latest version of the test standard is used.'),
    )

    parser.add_argument(
        "--criteria",
        "-c",
        help=("Define the criteria for the checks. "
              "Either Strict, Normal, or Lenient.  Defaults to Normal."),
        nargs="?",
        default="normal",
        choices=["lenient", "normal", "strict"],
    )

    parser.add_argument(
        "--verbose",
        "-v",
        help="Increase output. May be specified up to three times.",
        action="count",
        default=0,
    )

    parser.add_argument(
        "--describe-checks",
        "-D",
        help=("Describes checks for checkers specified using "
              "`-t`. If `-t` is not specified, lists checks "
              "from all available checkers."),
        action="store_true",
    )

    parser.add_argument(
        "--skip-checks",
        "-s",
        help=dedent("""
                                    Specifies tests to skip. Can take the form
                                    of either `<check_name>` or
                                    `<check_name>:<skip_level>`.  The first
                                    form skips any checks matching the name.
                                    In the second form <skip_level> may be
                                    specified as "A", "M", or "L".  "A" skips
                                    all checks and is equivalent to calling
                                    the first form. "M" will only show high
                                    priority output from the given check and
                                    will skip medium and low.  "L" will show
                                    both high and medium priority issues, while
                                    skipping low priority issues.
                                    """),
        action="append",
    )

    parser.add_argument(
        "-f",
        "--format",
        default=[],
        action="append",
        help=(
            "Output format(s). Options are 'text', 'html', 'json', 'json_new'."
            " The difference between the 'json' and the 'json_new'"
            " formats is that the 'json' format has the check as the top level"
            " key, whereas the 'json_new' format has the dataset name(s) as the"
            " main key in the output follow by any checks as subkeys.  Also, "
            "'json' format can be only be run against one input file, whereas "
            "'json_new' can be run against multiple files."),
        choices=["text", "html", "json", "json_new"],
    )

    parser.add_argument(
        "-o",
        "--output",
        default=[],
        action="append",
        help=("Output filename(s).  If '-' is supplied, output to stdout."
              " Can either be one or many files.  If one file is supplied,"
              " but the checker is run against many files, all the output"
              " from the checks goes to that file (does not presently work "
              "with 'json' format).  If more than one output file is "
              "supplied, the number of input datasets supplied must match "
              "the number of output files."),
    )

    parser.add_argument(
        "-O",
        "--option",
        default=[],
        action="append",
        help=dedent("""
                                    Additional options to be passed to the
                                    checkers.  Multiple options can be specified
                                    via multiple invocations of this switch.
                                    Options should be prefixed with a the
                                    checker name followed by the option, e.g.
                                    '<checker>:<option_name>'

                                    Available options:
                                    'cf:enable_appendix_a_checks' - Allow check
                                    results against CF Appendix A for attribute
                                    location and data types.
                                    """),
    )

    parser.add_argument(
        "-V",
        "--version",
        action="store_true",
        help="Display the IOOS Compliance Checker version information.",
    )

    parser.add_argument(
        "dataset_location",
        nargs="*",
        help=(
            "Defines the location of the dataset to be checked. The location "
            "can be a local netCDF file, a remote OPeNDAP endpoint, a remote "
            "netCDF file which returns content-type header of "
            "'application/x-netcdf', or an ERDDAP TableDAP endpoint. "
            "Note that the ERDDAP TableDAP endpoint will currently attempt "
            "to fetch the entire TableDAP dataset."))

    parser.add_argument("-l",
                        "--list-tests",
                        action="store_true",
                        help="List the available tests")

    parser.add_argument(
        "-d",
        "--download-standard-names",
        help=("Specify a version of the cf standard name table"
              " to download as packaged version. Either specify"
              ' a version number (e.g. "72") to fetch a '
              'specific version or "latest" to get the '
              "latest CF standard name table."),
    )

    # Add command line args from generator plugins
    check_suite.add_plugin_args(parser)

    args = parser.parse_args()

    check_suite.load_generated_checkers(args)

    if args.version:
        print("IOOS compliance checker version %s" % __version__)
        sys.exit(0)

    options_dict = parse_options(
        args.option) if args.option else defaultdict(set)

    if args.describe_checks:
        error_stat = 0
        if args.test:
            checker_names = set(args.test)
        else:
            # skip "latest" meta-versions (":latest" or no explicit version
            # specifier)
            checker_names = [
                c for c in check_suite.checkers
                if ":" in c and not c.endswith(":latest")
            ]

        for checker_name in sorted(checker_names):
            if checker_name not in check_suite.checkers:
                print(
                    "Cannot find checker '{}' with which to "
                    "describe checks".format(checker_name),
                    file=sys.stderr,
                )
                error_stat = 1
            else:
                _print_checker_name_header(checker_name)
                check_suite._print_checker(check_suite.checkers[checker_name])
        sys.exit(error_stat)

    if args.list_tests:
        print("IOOS compliance checker available checker suites:")
        check_suite._print_suites(args.verbose)
        return 0

    if args.download_standard_names:
        download_cf_standard_name_table(args.download_standard_names)

    if len(args.dataset_location) == 0:
        parser.print_help()
        sys.exit(1)

    # Check the number of output files
    if not args.output:
        args.output = "-"
    output_len = len(args.output)
    if not (output_len == 1 or output_len == len(args.dataset_location)):
        print(
            "The number of output files must either be one or the same as the number of datasets",
            file=sys.stderr,
        )
        sys.exit(2)

    # Run the compliance checker
    # 2 modes, concatenated output file or multiple output files
    return_values = []
    had_errors = []
    if output_len == 1:
        if args.format != "json":
            print(
                "Running Compliance Checker on the datasets from: {}".format(
                    args.dataset_location),
                file=sys.stderr,
            )
        return_value, errors = ComplianceChecker.run_checker(
            args.dataset_location,
            args.test or ["acdd"],
            args.verbose,
            args.criteria,
            args.skip_checks,
            args.output[0],
            args.format or ["text"],
            options=options_dict,
        )
        return_values.append(return_value)
        had_errors.append(errors)
    else:
        for output, dataset in zip(args.output, args.dataset_location):
            if args.format != "json":
                print(
                    "Running Compliance Checker on the dataset from: {}".
                    format(dataset),
                    file=sys.stderr,
                )
            return_value, errors = ComplianceChecker.run_checker(
                [dataset],
                args.test or ["acdd"],
                args.verbose,
                args.criteria,
                args.skip_checks,
                output,
                args.format or ["text"],
                options=options_dict,
            )
            return_values.append(return_value)
            had_errors.append(errors)

    if any(had_errors):
        sys.exit(2)
    if all(return_values):
        sys.exit(0)
    sys.exit(1)
Example #2
0
def main():
    # Load all available checker classes
    check_suite = CheckSuite()
    check_suite.load_all_available_checkers()

    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--test',
        '-t',
        '--test=',
        '-t=',
        default=[],
        action='append',
        help=(
            "Select the Checks you want to perform. Defaults to 'acdd'"
            " if unspecified.  Versions of standards can be specified via "
            "`-t <test_standard>:<version>`.  If `<version>` is omitted, or "
            "is \"latest\", the latest version of the test standard is used."))

    parser.add_argument(
        '--criteria',
        '-c',
        help=("Define the criteria for the checks. "
              "Either Strict, Normal, or Lenient.  Defaults to Normal."),
        nargs='?',
        default='normal',
        choices=['lenient', 'normal', 'strict'])

    parser.add_argument(
        '--verbose',
        '-v',
        help="Increase output. May be specified up to three times.",
        action="count",
        default=0)

    parser.add_argument('--skip-checks',
                        '-s',
                        help="Specifies tests to skip",
                        action='append')

    parser.add_argument(
        '-f',
        '--format',
        default=[],
        action='append',
        help=(
            "Output format(s). Options are 'text', 'html', 'json', 'json_new'."
            " The difference between the 'json' and the 'json_new'"
            " formats is that the 'json' format has the check as the top level"
            " key, whereas the 'json_new' format has the dataset name(s) as the"
            " main key in the output follow by any checks as subkeys.  Also, "
            "'json' format can be only be run against one input file, whereas "
            "'json_new' can be run against multiple files."),
        choices=['text', 'html', 'json', 'json_new'])

    parser.add_argument(
        '-o',
        '--output',
        default=[],
        action='append',
        help=("Output filename(s).  If '-' is supplied, output to stdout."
              " Can either be one or many files.  If one file is supplied,"
              " but the checker is run against many files, all the output"
              " from the checks goes to that file (does not presently work "
              "with 'json' format).  If more than one output file is "
              "supplied, the number of input datasets supplied must match "
              "the number of output files."))

    parser.add_argument(
        '-V',
        '--version',
        action='store_true',
        help='Display the IOOS Compliance Checker version information.')

    parser.add_argument(
        'dataset_location',
        nargs='*',
        help="Defines the location of the dataset to be checked.")

    parser.add_argument('-l',
                        '--list-tests',
                        action='store_true',
                        help='List the available tests')

    parser.add_argument('-d',
                        '--download-standard-names',
                        help=("Specify a version of the cf standard name table"
                              " to download as packaged version"))

    # Add command line args from generator plugins
    check_suite.add_plugin_args(parser)

    args = parser.parse_args()

    check_suite.load_generated_checkers(args)

    if args.version:
        print("IOOS compliance checker version %s" % __version__)
        return 0

    if args.list_tests:
        print("IOOS compliance checker available checker suites:")
        for checker in sorted(check_suite.checkers.keys()):
            version = getattr(check_suite.checkers[checker],
                              '_cc_checker_version', "???")
            if args.verbose:
                print(" - {} (v{})".format(checker, version))
            elif ':' in checker and not checker.endswith(
                    ':latest'):  # Skip the "latest" output
                print(" - {}".format(checker))
        return 0

    if args.download_standard_names:
        download_cf_standard_name_table(args.download_standard_names)

    if len(args.dataset_location) == 0:
        parser.print_help()
        return 1

    # Check the number of output files
    if not args.output:
        args.output = '-'
    output_len = len(args.output)
    if not (output_len == 1 or output_len == len(args.dataset_location)):
        print(
            'The number of output files must either be one or the same as the number of datasets',
            file=sys.stderr)
        sys.exit(2)

    # Run the compliance checker
    # 2 modes, concatenated output file or multiple output files
    return_values = []
    had_errors = []
    if output_len == 1:
        if args.format != 'json':
            print("Running Compliance Checker on the datasets from: {}".format(
                args.dataset_location),
                  file=sys.stderr)
        return_value, errors = ComplianceChecker.run_checker(
            args.dataset_location, args.test or ['acdd'], args.verbose,
            args.criteria, args.skip_checks, args.output[0], args.format
            or ['text'])
        return_values.append(return_value)
        had_errors.append(errors)
    else:
        for output, dataset in zip(args.output, args.dataset_location):
            if args.format != 'json':
                print("Running Compliance Checker on the dataset from: {}".
                      format(dataset),
                      file=sys.stderr)
            return_value, errors = ComplianceChecker.run_checker(
                [dataset], args.test or ['acdd'], args.verbose, args.criteria,
                args.skip_checks, output, args.format or ['text'])
            return_values.append(return_value)
            had_errors.append(errors)

    if any(had_errors):
        return 2
    if all(return_values):
        return 0
    return 1
Example #3
0
def main():
    # Load all available checker classes
    check_suite = CheckSuite()
    check_suite.load_all_available_checkers()

    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--test',
        '-t',
        '--test=',
        '-t=',
        default=[],
        action='append',
        help=(
            "Select the Checks you want to perform. Defaults to 'acdd'"
            " if unspecified.  Versions of standards can be specified via "
            "`-t <test_standard>:<version>`.  If `<version>` is omitted, or "
            "is \"latest\", the latest version of the test standard is used."))

    parser.add_argument(
        '--criteria',
        '-c',
        help=("Define the criteria for the checks. "
              "Either Strict, Normal, or Lenient.  Defaults to Normal."),
        nargs='?',
        default='normal',
        choices=['lenient', 'normal', 'strict'])

    parser.add_argument(
        '--verbose',
        '-v',
        help="Increase output. May be specified up to three times.",
        action="count",
        default=0)

    parser.add_argument('--describe-checks',
                        '-D',
                        help=("Describes checks for checkers specified using "
                              "`-t`. If `-t` is not specified, lists checks "
                              "from all available checkers."),
                        action='store_true')

    parser.add_argument('--skip-checks',
                        '-s',
                        help=dedent("""
                                    Specifies tests to skip. Can take the form
                                    of either `<check_name>` or
                                    `<check_name>:<skip_level>`.  The first
                                    form skips any checks matching the name.
                                    In the second form <skip_level> may be
                                    specified as "A", "M", or "L".  "A" skips
                                    all checks and is equivalent to calling
                                    the first form. "M" will only show high
                                    priority output from the given check and
                                    will skip medium and low.  "L" will show
                                    both high and medium priority issues, while
                                    skipping low priority issues.
                                    """),
                        action='append')

    parser.add_argument(
        '-f',
        '--format',
        default=[],
        action='append',
        help=(
            "Output format(s). Options are 'text', 'html', 'json', 'json_new'."
            " The difference between the 'json' and the 'json_new'"
            " formats is that the 'json' format has the check as the top level"
            " key, whereas the 'json_new' format has the dataset name(s) as the"
            " main key in the output follow by any checks as subkeys.  Also, "
            "'json' format can be only be run against one input file, whereas "
            "'json_new' can be run against multiple files."),
        choices=['text', 'html', 'json', 'json_new'])

    parser.add_argument(
        '-o',
        '--output',
        default=[],
        action='append',
        help=("Output filename(s).  If '-' is supplied, output to stdout."
              " Can either be one or many files.  If one file is supplied,"
              " but the checker is run against many files, all the output"
              " from the checks goes to that file (does not presently work "
              "with 'json' format).  If more than one output file is "
              "supplied, the number of input datasets supplied must match "
              "the number of output files."))

    parser.add_argument(
        '-V',
        '--version',
        action='store_true',
        help='Display the IOOS Compliance Checker version information.')

    parser.add_argument(
        'dataset_location',
        nargs='*',
        help="Defines the location of the dataset to be checked.")

    parser.add_argument('-l',
                        '--list-tests',
                        action='store_true',
                        help='List the available tests')

    parser.add_argument('-d',
                        '--download-standard-names',
                        help=("Specify a version of the cf standard name table"
                              " to download as packaged version"))

    # Add command line args from generator plugins
    check_suite.add_plugin_args(parser)

    args = parser.parse_args()

    check_suite.load_generated_checkers(args)

    if args.version:
        print("IOOS compliance checker version %s" % __version__)
        sys.exit(0)

    if args.describe_checks:
        error_stat = 0
        if args.test:
            checker_names = set(args.test)
        else:
            # skip "latest" meta-versions (":latest" or no explicit version
            # specifier)
            checker_names = [
                c for c in check_suite.checkers
                if ':' in c and not c.endswith(':latest')
            ]

        for checker_name in sorted(checker_names):
            if checker_name not in check_suite.checkers:
                print("Cannot find checker '{}' with which to "
                      "describe checks".format(checker_name),
                      file=sys.stderr)
                error_stat = 1
            else:
                _print_checker_name_header(checker_name)
                check_suite._print_checker(check_suite.checkers[checker_name])
        sys.exit(error_stat)

    if args.list_tests:
        print("IOOS compliance checker available checker suites:")
        check_suite._print_suites(args.verbose)
        return 0

    if args.download_standard_names:
        download_cf_standard_name_table(args.download_standard_names)

    if len(args.dataset_location) == 0:
        parser.print_help()
        sys.exit(1)

    # Check the number of output files
    if not args.output:
        args.output = '-'
    output_len = len(args.output)
    if not (output_len == 1 or output_len == len(args.dataset_location)):
        print(
            'The number of output files must either be one or the same as the number of datasets',
            file=sys.stderr)
        sys.exit(2)

    # Run the compliance checker
    # 2 modes, concatenated output file or multiple output files
    return_values = []
    had_errors = []
    if output_len == 1:
        if args.format != 'json':
            print("Running Compliance Checker on the datasets from: {}".format(
                args.dataset_location),
                  file=sys.stderr)
        return_value, errors = ComplianceChecker.run_checker(
            args.dataset_location, args.test or ['acdd'], args.verbose,
            args.criteria, args.skip_checks, args.output[0], args.format
            or ['text'])
        return_values.append(return_value)
        had_errors.append(errors)
    else:
        for output, dataset in zip(args.output, args.dataset_location):
            if args.format != 'json':
                print("Running Compliance Checker on the dataset from: {}".
                      format(dataset),
                      file=sys.stderr)
            return_value, errors = ComplianceChecker.run_checker(
                [dataset], args.test or ['acdd'], args.verbose, args.criteria,
                args.skip_checks, output, args.format or ['text'])
            return_values.append(return_value)
            had_errors.append(errors)

    if any(had_errors):
        sys.exit(2)
    if all(return_values):
        sys.exit(0)
    sys.exit(1)
Example #4
0
def main():

    if hasattr(CheckSuite, 'templates_root'):
        CheckSuite.templates_root = "xsf_checker.library"

    # Load all available checker classes
    check_suite = CheckSuite()
    check_suite.load_all_available_checkers()

    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--test', default=None, action='append',
                        help='Select the test (defaults: [\"xsf\", \"cf\"]). '
                             'Version can be specified via \"-t <test_standard>:<version>\". '
                             'If `<version>` is omitted (or \"latest\"), the latest version is used.')
    parser.add_argument('-c', '--criteria', nargs='?', default='normal',
                        choices=['lenient', 'normal', 'strict'],
                        help='Define the checking criteria (default: \"normal\").')
    parser.add_argument('-s', '--skip-checks', action='append',
                        help='Specify the tests to skip')
    parser.add_argument('-f', '--format', default=None, action='append', choices=['text', 'html', 'json_new'],
                        help='Set output formats (default: \"text\").')
    parser.add_argument('-o', '--output', default=[], action='append',
                        help=('Set output filenames. '
                              'If \"-\", output to stdout. '
                              'If 1 file is supplied, all the output goes in that file. '
                              'If more outputs are supplied, their number must match the inputs'))

    parser.add_argument('-v', '--verbose', action='count', default=0,
                        help='Increase output verbosity (up to 3 times).')
    parser.add_argument('--version', action='store_true',
                        help='Display the XSF Checker version information.')
    parser.add_argument('--ioos-version', action='store_true',
                        help='Display the IOOS Compliance Checker version information.')

    parser.add_argument('input', nargs='*',
                        help="Define the input dataset to be checked.")
    parser.add_argument('-l', '--list-tests', action='store_true',
                        help='List the available tests')
    parser.add_argument('-d', '--download-standard-names',
                        help='Specify the CF version of standard name table to download')

    # Add command line args from generator plugins
    check_suite.add_plugin_args(parser)

    args = parser.parse_args()

    check_suite.load_generated_checkers(args)

    if args.version:
        print("XSF Checker version %s" % xsf_checker_version)
        return 0

    if args.ioos_version:
        print("IOOS compliance checker version %s" % ioos_checker_version)
        return 0

    if args.list_tests:
        print("Available checker suites:")
        for checker in sorted(check_suite.checkers.keys()):
            version = getattr(check_suite.checkers[checker],
                              '_cc_checker_version', "???")
            if args.verbose:
                print(" - {} (v{})".format(checker, version))
            elif ':' in checker and not checker.endswith(':latest'):  # Skip the "latest" output
                print(" - {}".format(checker))
        return 0

    if args.download_standard_names:
        download_cf_standard_name_table(args.download_standard_names)

    nr_inputs = len(args.input)
    if nr_inputs == 0:
        parser.print_help()
        return 1

    # Check the number of output files
    if not args.output:
        args.output = '-'
    nr_outputs = len(args.output)
    if (nr_outputs != 1) and (nr_outputs != nr_inputs):
        print('The number of outputs must either be 1 or the same as the number of inputs:\n'
              '- current inputs: %d\n'
              '- current outputs: %d' % (nr_inputs, nr_outputs),
              file=sys.stderr)
        sys.exit(2)

    if args.test is None:
        args.test = ['cf', 'xsf']

    if args.format is None:
        args.format = ['text', ]

    print("Parameters:\n"
          "- Tests: %s\n"
          "- Checks to skip: %s\n"
          "- Criteria: %s\n"
          "- Output format: %s\n"
          "- Verbosity: %s"
          % (args.test, args.skip_checks, args.criteria, args.format, args.verbose)
          )

    # Run the compliance checker
    # 2 modes, concatenated output file or multiple output files
    return_values = []
    had_errors = []

    if nr_outputs == 1:
        if args.format != 'json':
            print("Running on input: %s" % args.input, file=sys.stderr)
        return_value, errors = ComplianceChecker.run_checker(
            args.input,
            args.test,
            args.verbose,
            args.criteria,
            args.skip_checks,
            args.output[0],
            args.format)
        return_values.append(return_value)
        had_errors.append(errors)
    else:
        for output, input in zip(args.output, args.input):
            if args.format != 'json':
                print("Running on input: %s" % args.input, file=sys.stderr)
            return_value, errors = ComplianceChecker.run_checker(
                [input],
                args.test,
                args.verbose,
                args.criteria,
                args.skip_checks,
                output,
                args.format)
            return_values.append(return_value)
            had_errors.append(errors)

    if any(had_errors):
        return 2
    if all(return_values):
        return 0
    return 1
Example #5
0
def main():
    # Load all available checker classes
    check_suite = CheckSuite()
    check_suite.load_all_available_checkers()

    parser = argparse.ArgumentParser()
    parser.add_argument('--test', '-t', '--test=', '-t=', default=[],
                        action='append',
                        help=("Select the Checks you want to perform. Defaults to 'acdd'"
                              " if unspecified.  Versions of standards can be specified via "
                              "`-t <test_standard>:<version>`.  If `<version>` is omitted, or "
                              "is \"latest\", the latest version of the test standard is used."))

    parser.add_argument('--criteria', '-c',
                        help=("Define the criteria for the checks. "
                              "Either Strict, Normal, or Lenient.  Defaults to Normal."),
                        nargs='?', default='normal',
                        choices=['lenient', 'normal', 'strict'])

    parser.add_argument('--verbose', '-v',
                        help="Increase output. May be specified up to three times.",
                        action="count",
                        default=0)

    parser.add_argument('--skip-checks', '-s',
                        help=dedent("""
                                    Specifies tests to skip. Can take the form
                                    of either `<check_name>` or
                                    `<check_name>:<skip_level>`.  The first
                                    form skips any checks matching the name.
                                    In the second form <skip_level> may be
                                    specified as "A", "M", or "L".  "A" skips
                                    all checks and is equivalent to calling
                                    the first form. "M" will only show high
                                    priority output from the given check and
                                    will skip medium and low.  "L" will show
                                    both high and medium priority issues, while
                                    skipping low priority issues.
                                    """),
                        action='append')

    parser.add_argument('-f', '--format', default=[], action='append',
                        help=("Output format(s). Options are 'text', 'html', 'json', 'json_new'."
                              " The difference between the 'json' and the 'json_new'"
                              " formats is that the 'json' format has the check as the top level"
                              " key, whereas the 'json_new' format has the dataset name(s) as the"
                              " main key in the output follow by any checks as subkeys.  Also, "
                              "'json' format can be only be run against one input file, whereas "
                              "'json_new' can be run against multiple files."),
                        choices=['text', 'html', 'json', 'json_new'])

    parser.add_argument('-o', '--output', default=[], action='append',
                        help=("Output filename(s).  If '-' is supplied, output to stdout."
                              " Can either be one or many files.  If one file is supplied,"
                              " but the checker is run against many files, all the output"
                              " from the checks goes to that file (does not presently work "
                              "with 'json' format).  If more than one output file is "
                              "supplied, the number of input datasets supplied must match "
                              "the number of output files."))

    parser.add_argument('-V', '--version', action='store_true',
                        help='Display the IOOS Compliance Checker version information.')

    parser.add_argument('dataset_location', nargs='*',
                        help="Defines the location of the dataset to be checked.")

    parser.add_argument('-l', '--list-tests', action='store_true',
                        help='List the available tests')

    parser.add_argument('-d', '--download-standard-names',
                        help=("Specify a version of the cf standard name table"
                              " to download as packaged version"))

    # Add command line args from generator plugins
    check_suite.add_plugin_args(parser)

    args = parser.parse_args()

    check_suite.load_generated_checkers(args)

    if args.version:
        print("IOOS compliance checker version %s" % __version__)
        return 0

    if args.list_tests:
        print("IOOS compliance checker available checker suites:")
        for checker in sorted(check_suite.checkers.keys()):
            version = getattr(check_suite.checkers[checker],
                              '_cc_checker_version', "???")
            if args.verbose:
                print(" - {} (v{})".format(checker, version))
            elif ':' in checker and not checker.endswith(':latest'):  # Skip the "latest" output
                print(" - {}".format(checker))
        return 0

    if args.download_standard_names:
        download_cf_standard_name_table(args.download_standard_names)

    if len(args.dataset_location) == 0:
        parser.print_help()
        return 1

    # Check the number of output files
    if not args.output:
        args.output = '-'
    output_len = len(args.output)
    if not (output_len == 1 or output_len == len(args.dataset_location)):
        print('The number of output files must either be one or the same as the number of datasets', file=sys.stderr)
        sys.exit(2)

    # Run the compliance checker
    # 2 modes, concatenated output file or multiple output files
    return_values = []
    had_errors = []
    if output_len == 1:
        if args.format != 'json':
            print("Running Compliance Checker on the datasets from: {}".format(args.dataset_location), file=sys.stderr)
        return_value, errors = ComplianceChecker.run_checker(args.dataset_location,
                                                             args.test or ['acdd'],
                                                             args.verbose,
                                                             args.criteria,
                                                             args.skip_checks,
                                                             args.output[0],
                                                             args.format or ['text'])
        return_values.append(return_value)
        had_errors.append(errors)
    else:
        for output, dataset in zip(args.output, args.dataset_location):
            if args.format != 'json':
                print("Running Compliance Checker on the dataset from: {}".format(dataset), file=sys.stderr)
            return_value, errors = ComplianceChecker.run_checker([dataset],
                                                                args.test or ['acdd'],
                                                                args.verbose,
                                                                args.criteria,
                                                                args.skip_checks,
                                                                output,
                                                                args.format or ['text'])
            return_values.append(return_value)
            had_errors.append(errors)

    if any(had_errors):
        return 2
    if all(return_values):
        return 0
    return 1