Skip to content

Commit a68e282

Browse files
committed
STDIO spec support
1 parent 827b49c commit a68e282

File tree

4 files changed

+77
-21
lines changed

4 files changed

+77
-21
lines changed

openapi_spec_validator/__init__.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from openapi_spec_validator.shortcuts import (
33
validate_spec_factory, validate_spec_url_factory,
44
)
5-
from openapi_spec_validator.handlers import UrlHandler
5+
from openapi_spec_validator.handlers import UrlHandler, FileObjectHandler
66
from openapi_spec_validator.schemas import get_openapi_schema
77
from openapi_spec_validator.factories import JSONSpecValidatorFactory
88
from openapi_spec_validator.validators import SpecValidator
@@ -19,8 +19,10 @@
1919
'validate_v2_spec_url', 'validate_v3_spec_url', 'validate_spec_url',
2020
]
2121

22+
file_object_handler = FileObjectHandler()
23+
all_urls_handler = UrlHandler('http', 'https', 'file')
2224
default_handlers = {
23-
'<all_urls>': UrlHandler('http', 'https', 'file'),
25+
'<all_urls>': all_urls_handler,
2426
'http': UrlHandler('http'),
2527
'https': UrlHandler('https'),
2628
'file': UrlHandler('file'),

openapi_spec_validator/__main__.py

+41-13
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
import pathlib2 as pathlib
88
import sys
99

10-
11-
from openapi_spec_validator import validate_spec_url, validate_v2_spec_url
10+
from openapi_spec_validator import (
11+
openapi_v2_spec_validator, openapi_v3_spec_validator, all_urls_handler,
12+
file_object_handler,
13+
)
1214
from openapi_spec_validator.exceptions import ValidationError
1315

1416
logger = logging.getLogger(__name__)
@@ -18,6 +20,19 @@
1820
)
1921

2022

23+
def read_from_stdin(filename):
24+
return file_object_handler(sys.stdin), ''
25+
26+
27+
def read_from_filename(filename):
28+
if not os.path.isfile(filename):
29+
raise SystemError("No such file {0}".format(filename))
30+
31+
filename = os.path.abspath(filename)
32+
uri = pathlib.Path(filename).as_uri()
33+
return all_urls_handler(uri), uri
34+
35+
2136
def main(args=None):
2237
parser = argparse.ArgumentParser()
2338
parser.add_argument('filename', help="Absolute or relative path to file")
@@ -29,21 +44,34 @@ def main(args=None):
2944
default='3.0.0'
3045
)
3146
args = parser.parse_args(args)
32-
filename = args.filename
33-
filename = os.path.abspath(filename)
47+
48+
# choose source
49+
reader = read_from_filename
50+
if args.filename == '-':
51+
reader = read_from_stdin
52+
53+
# read source
54+
try:
55+
spec, spec_url = reader(args.filename)
56+
except Exception as exc:
57+
print(exc)
58+
sys.exit(1)
59+
3460
# choose the validator
35-
if args.schema == '2.0':
36-
validate_url = validate_v2_spec_url
37-
elif args.schema == '3.0.0':
38-
validate_url = validate_spec_url
61+
validators = {
62+
'2.0': openapi_v2_spec_validator,
63+
'3.0.0': openapi_v3_spec_validator,
64+
}
65+
validator = validators[args.schema]
66+
3967
# validate
4068
try:
41-
validate_url(pathlib.Path(filename).as_uri())
42-
except ValidationError as e:
43-
print(e)
69+
validator.validate(spec, spec_url=spec_url)
70+
except ValidationError as exc:
71+
print(exc)
4472
sys.exit(1)
45-
except Exception as e:
46-
print(e)
73+
except Exception as exc:
74+
print(exc)
4775
sys.exit(2)
4876
else:
4977
print('OK')

openapi_spec_validator/handlers.py

+17-6
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,30 @@
88
from openapi_spec_validator.loaders import ExtendedSafeLoader
99

1010

11-
class UrlHandler:
12-
"""OpenAPI spec validator URL scheme handler."""
11+
class FileObjectHandler(object):
12+
"""OpenAPI spec validator file-like object handler."""
1313

14-
def __init__(self, *allowed_schemes, **options):
15-
self.allowed_schemes = allowed_schemes
14+
def __init__(self, **options):
1615
self.options = options
1716

1817
@property
1918
def loader(self):
2019
return self.options.get('loader', ExtendedSafeLoader)
2120

21+
def __call__(self, f):
22+
return load(f, self.loader)
23+
24+
25+
class UrlHandler(FileObjectHandler):
26+
"""OpenAPI spec validator URL scheme handler."""
27+
28+
def __init__(self, *allowed_schemes, **options):
29+
super(UrlHandler, self).__init__(**options)
30+
self.allowed_schemes = allowed_schemes
31+
2232
def __call__(self, url, timeout=1):
2333
assert urlparse(url).scheme in self.allowed_schemes
2434

25-
with contextlib.closing(urlopen(url, timeout=timeout)) as fh:
26-
return load(fh, self.loader)
35+
f = urlopen(url, timeout=timeout)
36+
with contextlib.closing(f) as fh:
37+
return super(UrlHandler, self).__call__(fh)

tests/integration/test_main.py

+15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import mock
2+
13
import pytest
4+
from six import StringIO
25

36
from openapi_spec_validator.__main__ import main
47

@@ -44,3 +47,15 @@ def test_nonexisting_file():
4447
testargs = ['i_dont_exist.yaml']
4548
with pytest.raises(SystemExit):
4649
main(testargs)
50+
51+
52+
def test_schema_stdin():
53+
"""Test schema from STDIN"""
54+
spes_path = './tests/integration/data/v3.0/petstore.yaml'
55+
with open(spes_path, 'r') as spec_file:
56+
spec_lines = spec_file.readlines()
57+
spec_io = StringIO("".join(spec_lines))
58+
59+
testargs = ['-']
60+
with mock.patch('openapi_spec_validator.__main__.sys.stdin', spec_io):
61+
main(testargs)

0 commit comments

Comments
 (0)