Skip to content

Commit 7990e85

Browse files
committed
support for cli specifying --base-uri local or remote and add test cases
1 parent b936179 commit 7990e85

File tree

2 files changed

+142
-14
lines changed

2 files changed

+142
-14
lines changed

jsonschema/cli.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import os
1111
import sys
1212
import traceback
13+
import urllib
1314

1415
import attr
1516

@@ -263,20 +264,30 @@ def load(_):
263264

264265
if arguments["base_uri"] is None:
265266
resolver = None
266-
elif "http:" in arguments["base_uri"] or "https:" in arguments["base_uri"]\
267-
or "urn:" in arguments["base_uri"]:
268-
resolver = RefResolver(
269-
base_uri=arguments["base_uri"],
270-
referrer=schema,
271-
)
272267
else:
273-
file_prefix = "file:///{}/" if "nt" == os.name else "file://{}/"
274-
resolver = RefResolver(
275-
base_uri=file_prefix.format(
276-
os.path.abspath(arguments["base_uri"])
277-
),
278-
referrer=schema,
279-
)
268+
scheme = urllib.parse.urlsplit(arguments["base_uri"]).scheme
269+
alphabet_list = [chr(ord('a') + i) for i in range(0, 26)]
270+
local_path_flag = True \
271+
if scheme == '' or scheme in alphabet_list else False
272+
273+
if local_path_flag:
274+
file_prefix = "file:///{}/" if "nt" == os.name else "file://{}/"
275+
abs_path_flag = os.path.isabs(arguments["base_uri"])
276+
277+
resolver = RefResolver(
278+
base_uri=file_prefix.format(arguments["base_uri"]),
279+
referrer=schema,
280+
) if abs_path_flag is True else RefResolver(
281+
base_uri=file_prefix.format(
282+
os.path.abspath(arguments["base_uri"])
283+
),
284+
referrer=schema,
285+
)
286+
else:
287+
resolver = RefResolver(
288+
base_uri=arguments["base_uri"],
289+
referrer=schema,
290+
)
280291

281292
validator = arguments["validator"](schema, resolver=resolver)
282293
exit_code = 0

jsonschema/tests/test_cli.py

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ def test_successful_validation_of_just_the_schema_pretty_output(self):
684684
stderr="",
685685
)
686686

687-
def test_successful_validation_with_specifying_base_uri(self):
687+
def test_successful_validate_with_specifying_base_uri_relative_path(self):
688688
try:
689689
schema_file = tempfile.NamedTemporaryFile(
690690
mode='w+',
@@ -710,6 +710,123 @@ def test_successful_validation_with_specifying_base_uri(self):
710710
stderr="",
711711
)
712712

713+
def test_failure_validate_with_specifying_base_uri_relative_path(self):
714+
try:
715+
schema_file = tempfile.NamedTemporaryFile(
716+
mode='w+',
717+
prefix='schema',
718+
suffix='.json',
719+
dir='..',
720+
delete=False
721+
)
722+
self.addCleanup(os.remove, schema_file.name)
723+
schema = """
724+
{"type": "object", "properties": {"KEY1":
725+
{"$ref": %s%s#definitions/schemas"}},
726+
"definitions": {"schemas": {"type": "string"}}}
727+
""" % ("\"", os.path.basename(schema_file.name))
728+
schema_file.write(schema)
729+
finally:
730+
schema_file.close()
731+
732+
self.assertOutputs(
733+
files=dict(some_schema=schema, some_instance='{"KEY1": 1}'),
734+
argv=["-i", "some_instance", "--base-uri", "..", "some_schema"],
735+
exit_code=1,
736+
stdout="",
737+
stderr="1: 1 is not of type 'string'\n",
738+
)
739+
740+
def test_successful_validate_with_specifying_base_uri_absolute_path(self):
741+
try:
742+
schema_file = tempfile.NamedTemporaryFile(
743+
mode='w+',
744+
prefix='schema',
745+
suffix='.json',
746+
dir='/',
747+
delete=False
748+
)
749+
self.addCleanup(os.remove, schema_file.name)
750+
schema = """
751+
{"type": "object", "properties": {"KEY1":
752+
{"$ref": %s%s#definitions/schemas"}},
753+
"definitions": {"schemas": {"type": "string"}}}
754+
""" % ("\"", os.path.basename(schema_file.name))
755+
schema_file.write(schema)
756+
finally:
757+
schema_file.close()
758+
759+
self.assertOutputs(
760+
files=dict(some_schema=schema, some_instance='{"KEY1": "1"}'),
761+
argv=["-i", "some_instance", "--base-uri", "/", "some_schema"],
762+
stdout="",
763+
stderr="",
764+
)
765+
766+
def test_failure_validate_with_specifying_base_uri_absolute_path(self):
767+
try:
768+
schema_file = tempfile.NamedTemporaryFile(
769+
mode='w+',
770+
prefix='schema',
771+
suffix='.json',
772+
dir='/',
773+
delete=False
774+
)
775+
self.addCleanup(os.remove, schema_file.name)
776+
schema = """
777+
{"type": "object", "properties": {"KEY1":
778+
{"$ref": %s%s#definitions/schemas"}},
779+
"definitions": {"schemas": {"type": "string"}}}
780+
""" % ("\"", os.path.basename(schema_file.name))
781+
schema_file.write(schema)
782+
finally:
783+
schema_file.close()
784+
785+
self.assertOutputs(
786+
files=dict(some_schema=schema, some_instance='{"KEY1": 1}'),
787+
argv=["-i", "some_instance", "--base-uri", "/", "some_schema"],
788+
exit_code=1,
789+
stdout="",
790+
stderr="1: 1 is not of type 'string'\n",
791+
)
792+
793+
def test_successful_validate_with_specifying_base_uri_remote_path(self):
794+
schema = """
795+
{"type": "object", "properties": {
796+
"KEY1":{"$ref": "organization.json"}}}
797+
"""
798+
self.assertOutputs(
799+
files=dict(some_schema=schema,
800+
some_instance='{"KEY1": {"name": "remote"}}'
801+
),
802+
argv=[
803+
"-i", "some_instance",
804+
"--base-uri", "https://project-open-data.cio.gov/v1.1/schema/",
805+
"some_schema"
806+
],
807+
stdout="",
808+
stderr="",
809+
)
810+
811+
def test_failure_validate_with_specifying_base_uri_remote_path(self):
812+
schema = """
813+
{"type": "object", "properties": {
814+
"KEY1":{"$ref": "organization.json"}}}
815+
"""
816+
self.assertOutputs(
817+
files=dict(some_schema=schema,
818+
some_instance='{"KEY1": {"fail": "remote"}}'
819+
),
820+
argv=[
821+
"-i", "some_instance",
822+
"--base-uri", "https://project-open-data.cio.gov/v1.1/schema/",
823+
"some_schema"
824+
],
825+
exit_code=1,
826+
stdout="",
827+
stderr="{'fail': 'remote'}: 'name' is a required property\n",
828+
)
829+
713830
def test_it_validates_using_the_latest_validator_when_unspecified(self):
714831
# There isn't a better way now I can think of to ensure that the
715832
# latest version was used, given that the call to validator_for

0 commit comments

Comments
 (0)