|
1 | 1 | from io import StringIO
|
2 | 2 | from json import JSONDecodeError
|
| 3 | +from pathlib import Path |
3 | 4 | from textwrap import dedent
|
4 | 5 | from unittest import TestCase
|
5 | 6 | import errno
|
6 | 7 | import json
|
7 | 8 | import os
|
8 | 9 | import subprocess
|
9 | 10 | import sys
|
| 11 | +import tempfile |
10 | 12 |
|
11 | 13 | from jsonschema import Draft4Validator, Draft7Validator, __version__, cli
|
12 |
| -from jsonschema.exceptions import SchemaError, ValidationError |
| 14 | +from jsonschema.exceptions import ( |
| 15 | + RefResolutionError, |
| 16 | + SchemaError, |
| 17 | + ValidationError, |
| 18 | +) |
13 | 19 | from jsonschema.tests._helpers import captured_output
|
14 | 20 | from jsonschema.validators import _LATEST_VERSION, validate
|
15 | 21 |
|
@@ -683,6 +689,87 @@ def test_successful_validation_of_just_the_schema_pretty_output(self):
|
683 | 689 | stderr="",
|
684 | 690 | )
|
685 | 691 |
|
| 692 | + def test_successful_validation_via_explicit_base_uri(self): |
| 693 | + ref_schema_file = tempfile.NamedTemporaryFile(delete=False) |
| 694 | + self.addCleanup(os.remove, ref_schema_file.name) |
| 695 | + |
| 696 | + ref_path = Path(ref_schema_file.name) |
| 697 | + ref_path.write_text('{"definitions": {"num": {"type": "integer"}}}') |
| 698 | + |
| 699 | + schema = f'{{"$ref": "{ref_path.name}#definitions/num"}}' |
| 700 | + |
| 701 | + self.assertOutputs( |
| 702 | + files=dict(some_schema=schema, some_instance='1'), |
| 703 | + argv=[ |
| 704 | + "-i", "some_instance", |
| 705 | + "--base-uri", ref_path.parent.as_uri() + "/", |
| 706 | + "some_schema", |
| 707 | + ], |
| 708 | + stdout="", |
| 709 | + stderr="", |
| 710 | + ) |
| 711 | + |
| 712 | + def test_unsuccessful_validation_via_explicit_base_uri(self): |
| 713 | + ref_schema_file = tempfile.NamedTemporaryFile(delete=False) |
| 714 | + self.addCleanup(os.remove, ref_schema_file.name) |
| 715 | + |
| 716 | + ref_path = Path(ref_schema_file.name) |
| 717 | + ref_path.write_text('{"definitions": {"num": {"type": "integer"}}}') |
| 718 | + |
| 719 | + schema = f'{{"$ref": "{ref_path.name}#definitions/num"}}' |
| 720 | + |
| 721 | + self.assertOutputs( |
| 722 | + files=dict(some_schema=schema, some_instance='"1"'), |
| 723 | + argv=[ |
| 724 | + "-i", "some_instance", |
| 725 | + "--base-uri", ref_path.parent.as_uri() + "/", |
| 726 | + "some_schema", |
| 727 | + ], |
| 728 | + exit_code=1, |
| 729 | + stdout="", |
| 730 | + stderr="1: '1' is not of type 'integer'\n", |
| 731 | + ) |
| 732 | + |
| 733 | + def test_nonexistent_file_with_explicit_base_uri(self): |
| 734 | + schema = '{"$ref": "someNonexistentFile.json#definitions/num"}' |
| 735 | + instance = "1" |
| 736 | + |
| 737 | + with self.assertRaises(RefResolutionError) as e: |
| 738 | + self.assertOutputs( |
| 739 | + files=dict( |
| 740 | + some_schema=schema, |
| 741 | + some_instance=instance, |
| 742 | + ), |
| 743 | + argv=[ |
| 744 | + "-i", "some_instance", |
| 745 | + "--base-uri", Path.cwd().as_uri(), |
| 746 | + "some_schema", |
| 747 | + ], |
| 748 | + ) |
| 749 | + error = str(e.exception) |
| 750 | + self.assertIn("/someNonexistentFile.json'", error) |
| 751 | + |
| 752 | + def test_invalid_exlicit_base_uri(self): |
| 753 | + schema = '{"$ref": "foo.json#definitions/num"}' |
| 754 | + instance = "1" |
| 755 | + |
| 756 | + with self.assertRaises(RefResolutionError) as e: |
| 757 | + self.assertOutputs( |
| 758 | + files=dict( |
| 759 | + some_schema=schema, |
| 760 | + some_instance=instance, |
| 761 | + ), |
| 762 | + argv=[ |
| 763 | + "-i", "some_instance", |
| 764 | + "--base-uri", "not@UR1", |
| 765 | + "some_schema", |
| 766 | + ], |
| 767 | + ) |
| 768 | + error = str(e.exception) |
| 769 | + self.assertEqual( |
| 770 | + error, "unknown url type: 'foo.json'", |
| 771 | + ) |
| 772 | + |
686 | 773 | def test_it_validates_using_the_latest_validator_when_unspecified(self):
|
687 | 774 | # There isn't a better way now I can think of to ensure that the
|
688 | 775 | # latest version was used, given that the call to validator_for
|
|
0 commit comments