From 9a9a8ddeb31faeafe2aab73cf2e2e93e253cd26c Mon Sep 17 00:00:00 2001 From: Nick Timkovich Date: Fri, 17 May 2019 14:23:16 -0500 Subject: [PATCH] Add a CLI tool --- README.md | 22 +++++++++---- setup.py | 5 +++ swagger_spec_validator/cli.py | 60 +++++++++++++++++++++++++++++++++++ tests/cli_test.py | 35 ++++++++++++++++++++ 4 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 swagger_spec_validator/cli.py create mode 100644 tests/cli_test.py diff --git a/README.md b/README.md index 584b9d2..52b546b 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,24 @@ Swagger Spec Validator is a Python library that validates Swagger Specs against the [Swagger 1.2](https://github.com/swagger-api/swagger-spec/blob/master/versions/1.2.md) or [Swagger 2.0](https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md) specification. The validator aims to check for full compliance with the Specification. -## Example Usage +## Installation + + $ pip install swagger_spec_validator -Validate a spec from a url: +## Usage -```python +Validate a spec from a URL: + +### Command Line Tool + +```bash +$ swagger-spec-validator http://petstore.swagger.io/v2/swagger.json +Validation successful! +``` +### Python API + +```python from swagger_spec_validator import validate_spec_url # example for swagger spec v1.2 @@ -26,10 +38,6 @@ validate_spec_url('http://petstore.swagger.io/v2/swagger.json') More documentation is available at http://swagger_spec_validator.readthedocs.org -## Installation - - $ pip install swagger_spec_validator - ## Contributing 1. Fork it ( http://github.com/Yelp/swagger_spec_validator/fork ) diff --git a/setup.py b/setup.py index 7ad4566..13670c3 100644 --- a/setup.py +++ b/setup.py @@ -45,4 +45,9 @@ "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", ], + entry_points={ + "console_scripts": [ + "swagger-spec-validator = swagger_spec_validator.cli:main", + ], + }, ) diff --git a/swagger_spec_validator/cli.py b/swagger_spec_validator/cli.py new file mode 100644 index 0000000..44c78d3 --- /dev/null +++ b/swagger_spec_validator/cli.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +""" +Swagger spec validator. +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import argparse +import sys + +from swagger_spec_validator.common import SwaggerValidationError +from swagger_spec_validator.util import validate_spec_url + + +def _extract_error_message(exc): + """ + The validators return nested errors coming from common.wrap_exception, so to + present as a nice string to print we need to dig out the original message. + """ + try: + return exc.args[1].args[0] + except IndexError: + # not 100% sure it is *always* wrapped, but this should provide a + # fallback. + return str(exc) + + +def main(argv=None): + if argv is None: + argv = sys.argv[1:] # pragma: no cover + + parser = argparse.ArgumentParser(description=__doc__) + + parser.add_argument("url", type=str, help="URL of Swagger spec to validate") + parser.add_argument( + "-q", + "--quiet", + action="store_true", + help="No output if validation is successful", + ) + + args = parser.parse_args(argv) + + try: + validate_spec_url(args.url) + except SwaggerValidationError as exc: + error_message = _extract_error_message(exc) + print(error_message, file=sys.stderr) + return 1 + + if not args.quiet: + print("Validation successful!", file=sys.stderr) + + return 0 + + +if __name__ == "__main__": # pragma: no cover + sys.exit(main()) diff --git a/tests/cli_test.py b/tests/cli_test.py new file mode 100644 index 0000000..8a00066 --- /dev/null +++ b/tests/cli_test.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from swagger_spec_validator.cli import main +from swagger_spec_validator.common import get_uri_from_file_path + + +def test_cli_main_goodfile(): + good_file = "./tests/data/v2.0/petstore.json" + file_uri = get_uri_from_file_path(good_file) + + exit_code = main([file_uri]) + + assert exit_code == 0 + + +def test_cli_main_badfile(): + bad_file = "./tests/data/v2.0/test_fails_on_invalid_external_ref_in_list/petstore.json" + file_uri = get_uri_from_file_path(bad_file) + + exit_code = main([file_uri]) + + assert exit_code == 1 + + +def test_cli_main_invalidfile(): + missing_file = "./tests/data/this-file-doesnt-exist.json" + file_uri = get_uri_from_file_path(missing_file) + + exit_code = main([file_uri]) + + assert exit_code == 1