Skip to content

Commit 78f5a18

Browse files
anton-bAnton Benkevich
andauthored
Handle uris (#103)
* Properly handle uris Convert local path to uri on input * Add testing under windows linux and macos Co-authored-by: Anton Benkevich <[email protected]>
1 parent 394aff6 commit 78f5a18

File tree

3 files changed

+53
-16
lines changed

3 files changed

+53
-16
lines changed

.travis.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,24 @@ jobs:
99
python: 3.8
1010
install: pip install -U tox-travis
1111
script: tox
12+
- python: 3.8
13+
install:
14+
- pip install ./
15+
script: python scripts/validate_my_definition.py -d alsdkdefs/apis/assets_query/
1216
- python: 3.7
1317
install: pip install -U tox-travis
1418
script: tox
19+
- stage: test_other_os
20+
language: sh
21+
python: 3
22+
before_install:
23+
- choco install python3
24+
- export PATH="/c/Python38:/c/Python38/Scripts:$PATH"
25+
- python -m pip install --upgrade pip wheel
26+
- python -m pip install -r requirements.txt
27+
name: 'Run python tests on windows'
28+
script: python -m unittest
29+
os: windows
1530
- stage: merge-automated-prs
1631
name: "(Pipeline Stage 1)Merge pull request produced by automation"
1732
if: "(fork = false) AND (head_branch =~ /^auto-update-\\d*/) AND (type = pull_request)"

alsdkdefs/__init__.py

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import glob
44
import collections
55
import jsonschema
6-
from urllib.parse import urlparse
7-
from urllib.request import urlopen
6+
from urllib.parse import urlparse, urlsplit, urlunsplit
7+
from urllib.request import urlopen, url2pathname
88
import yaml
99
import yaml.resolver
1010
from functools import reduce, lru_cache
@@ -13,6 +13,7 @@
1313
import re
1414

1515
OPENAPI_SCHEMA_URL = 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/schemas/v3.0/schema.json'
16+
URI_SCHEMES = ['file', 'http', 'https']
1617

1718

1819
class AlertLogicOpenApiValidationException(Exception):
@@ -62,7 +63,6 @@ class OpenAPIKeyWord:
6263
COMPONENTS = "components"
6364
SCHEMAS = "schemas"
6465
PROPERTIES = "properties"
65-
REQUIRED = "required"
6666
CONTENT = "content"
6767
DEFAULT = "default"
6868
ENCODING = "encoding"
@@ -127,25 +127,24 @@ def load_service_spec(service_name, apis_dir=None, version=None):
127127
version = version > new_version and version or new_version
128128
else:
129129
version = version[:1] != "v" and version or version[1:]
130-
service_spec_file = f"file:///{pjoin(service_api_dir, service_name)}.v{version}.yaml"
131-
return load_spec(service_spec_file)
130+
service_spec_file_path = f"{pjoin(service_api_dir, service_name)}.v{version}.yaml"
131+
return load_spec(service_spec_file_path)
132132

133133

134-
def load_spec(uri):
134+
def load_spec(uri_or_path):
135135
"""Loads spec out of RFC3986 URI, resolves refs, normalizes"""
136-
return normalize_spec(get_spec(uri), uri)
136+
uri_or_path = __normalize_uri(uri_or_path)
137+
return normalize_spec(uri_or_path, get_spec(uri_or_path))
137138

138139

139-
def normalize_spec(spec, uri):
140+
def normalize_spec(uri_or_path, spec):
140141
"""Resolves refs, normalizes"""
141-
return __normalize_spec(__resolve_refs(uri, spec))
142+
uri_or_path = __normalize_uri(uri_or_path)
143+
return __normalize_spec(__resolve_refs(__base_uri(uri_or_path), spec))
142144

143145

144146
def get_spec(uri):
145147
"""Loads spec out of RFC3986 URI, yaml's Reader detects encoding automatically"""
146-
parsed = urlparse(uri)
147-
if not parsed.scheme:
148-
uri = f"file://{uri}"
149148
with urlopen(uri) as stream:
150149
try:
151150
return yaml.load(stream, _YamlOrderedLoader)
@@ -210,22 +209,45 @@ def al_specific_validations(spec):
210209
checks = [validate_operation_ids(spec), validate_path_parameters(spec)]
211210
all(checks)
212211

213-
obj = normalize_spec(spec, uri)
212+
obj = normalize_spec(uri, spec)
214213
jsonschema.validate(obj, schema)
215214
return al_specific_validations(spec)
216215

217216

217+
def make_file_uri(path):
218+
return make_uri('file', '', path, '', '')
219+
220+
221+
def make_uri(scheme, netloc, url, query, fragment):
222+
return urlunsplit((scheme, netloc, url, query, fragment))
223+
224+
218225
# Private functions
219226

227+
def __normalize_uri(uri_or_path):
228+
parsed = urlparse(uri_or_path)
229+
if parsed.scheme not in URI_SCHEMES:
230+
return make_file_uri(uri_or_path)
231+
else:
232+
return uri_or_path
233+
234+
235+
def __base_uri(uri):
236+
(scheme, netloc, path, query, fragment) = urlsplit(uri)
237+
path = os.path.dirname(url2pathname(path)) + '/'
238+
return urlunsplit((scheme, netloc, path, query, fragment))
239+
240+
220241
def __list_flatten(l):
221242
return [item for sublist in l for item in sublist]
222243

223244

224-
def __resolve_refs(file_uri, spec):
245+
def __resolve_refs(file_base_uri, spec):
225246
def spec_ref_handler(uri):
226247
return __resolve_refs(uri, get_spec(uri))
248+
227249
handlers = {'': spec_ref_handler, 'file': spec_ref_handler, 'http': spec_ref_handler, 'https': spec_ref_handler}
228-
resolver = jsonschema.RefResolver(file_uri, spec, handlers=handlers)
250+
resolver = jsonschema.RefResolver(file_base_uri, spec, handlers=handlers)
229251

230252
def _do_resolve(node):
231253
if isinstance(node, collections.abc.Mapping) and OpenAPIKeyWord.REF in node:

tests/test_apis_validate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ def test_validate_definitions(self):
1818
print("Validating ", service)
1919
for defintion_file in alsdkdefs.get_service_defs(service):
2020
print("Validating def", defintion_file)
21-
obj = alsdkdefs.get_spec(defintion_file)
21+
obj = alsdkdefs.get_spec(alsdkdefs.make_file_uri(defintion_file))
2222
alsdkdefs.validate(obj, defintion_file)

0 commit comments

Comments
 (0)