Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
0
venv/Lib/site-packages/jsonschema/tests/__init__.py
Normal file
0
venv/Lib/site-packages/jsonschema/tests/__init__.py
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
5
venv/Lib/site-packages/jsonschema/tests/_helpers.py
Normal file
5
venv/Lib/site-packages/jsonschema/tests/_helpers.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
def bug(issue=None):
|
||||
message = "A known bug."
|
||||
if issue is not None:
|
||||
message += " See issue #{issue}.".format(issue=issue)
|
||||
return message
|
239
venv/Lib/site-packages/jsonschema/tests/_suite.py
Normal file
239
venv/Lib/site-packages/jsonschema/tests/_suite.py
Normal file
|
@ -0,0 +1,239 @@
|
|||
"""
|
||||
Python representations of the JSON Schema Test Suite tests.
|
||||
"""
|
||||
|
||||
from functools import partial
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from twisted.python.filepath import FilePath
|
||||
import attr
|
||||
|
||||
from jsonschema.compat import PY3
|
||||
from jsonschema.validators import validators
|
||||
import jsonschema
|
||||
|
||||
|
||||
def _find_suite():
|
||||
root = os.environ.get("JSON_SCHEMA_TEST_SUITE")
|
||||
if root is not None:
|
||||
return FilePath(root)
|
||||
|
||||
root = FilePath(jsonschema.__file__).parent().sibling("json")
|
||||
if not root.isdir(): # pragma: no cover
|
||||
raise ValueError(
|
||||
(
|
||||
"Can't find the JSON-Schema-Test-Suite directory. "
|
||||
"Set the 'JSON_SCHEMA_TEST_SUITE' environment "
|
||||
"variable or run the tests from alongside a checkout "
|
||||
"of the suite."
|
||||
),
|
||||
)
|
||||
return root
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class Suite(object):
|
||||
|
||||
_root = attr.ib(default=attr.Factory(_find_suite))
|
||||
|
||||
def _remotes(self):
|
||||
jsonschema_suite = self._root.descendant(["bin", "jsonschema_suite"])
|
||||
remotes = subprocess.check_output(
|
||||
[sys.executable, jsonschema_suite.path, "remotes"],
|
||||
)
|
||||
return {
|
||||
"http://localhost:1234/" + name: schema
|
||||
for name, schema in json.loads(remotes.decode("utf-8")).items()
|
||||
}
|
||||
|
||||
def benchmark(self, runner): # pragma: no cover
|
||||
for name in validators:
|
||||
self.version(name=name).benchmark(runner=runner)
|
||||
|
||||
def version(self, name):
|
||||
return Version(
|
||||
name=name,
|
||||
path=self._root.descendant(["tests", name]),
|
||||
remotes=self._remotes(),
|
||||
)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class Version(object):
|
||||
|
||||
_path = attr.ib()
|
||||
_remotes = attr.ib()
|
||||
|
||||
name = attr.ib()
|
||||
|
||||
def benchmark(self, runner, **kwargs): # pragma: no cover
|
||||
for suite in self.tests():
|
||||
for test in suite:
|
||||
runner.bench_func(
|
||||
test.fully_qualified_name,
|
||||
partial(test.validate_ignoring_errors, **kwargs),
|
||||
)
|
||||
|
||||
def tests(self):
|
||||
return (
|
||||
test
|
||||
for child in self._path.globChildren("*.json")
|
||||
for test in self._tests_in(
|
||||
subject=child.basename()[:-5],
|
||||
path=child,
|
||||
)
|
||||
)
|
||||
|
||||
def format_tests(self):
|
||||
path = self._path.descendant(["optional", "format"])
|
||||
return (
|
||||
test
|
||||
for child in path.globChildren("*.json")
|
||||
for test in self._tests_in(
|
||||
subject=child.basename()[:-5],
|
||||
path=child,
|
||||
)
|
||||
)
|
||||
|
||||
def tests_of(self, name):
|
||||
return self._tests_in(
|
||||
subject=name,
|
||||
path=self._path.child(name + ".json"),
|
||||
)
|
||||
|
||||
def optional_tests_of(self, name):
|
||||
return self._tests_in(
|
||||
subject=name,
|
||||
path=self._path.descendant(["optional", name + ".json"]),
|
||||
)
|
||||
|
||||
def to_unittest_testcase(self, *suites, **kwargs):
|
||||
name = kwargs.pop("name", "Test" + self.name.title())
|
||||
methods = {
|
||||
test.method_name: test.to_unittest_method(**kwargs)
|
||||
for suite in suites
|
||||
for tests in suite
|
||||
for test in tests
|
||||
}
|
||||
cls = type(name, (unittest.TestCase,), methods)
|
||||
|
||||
try:
|
||||
cls.__module__ = _someone_save_us_the_module_of_the_caller()
|
||||
except Exception: # pragma: no cover
|
||||
# We're doing crazy things, so if they go wrong, like a function
|
||||
# behaving differently on some other interpreter, just make them
|
||||
# not happen.
|
||||
pass
|
||||
|
||||
return cls
|
||||
|
||||
def _tests_in(self, subject, path):
|
||||
for each in json.loads(path.getContent().decode("utf-8")):
|
||||
yield (
|
||||
_Test(
|
||||
version=self,
|
||||
subject=subject,
|
||||
case_description=each["description"],
|
||||
schema=each["schema"],
|
||||
remotes=self._remotes,
|
||||
**test
|
||||
) for test in each["tests"]
|
||||
)
|
||||
|
||||
|
||||
@attr.s(hash=True, repr=False)
|
||||
class _Test(object):
|
||||
|
||||
version = attr.ib()
|
||||
|
||||
subject = attr.ib()
|
||||
case_description = attr.ib()
|
||||
description = attr.ib()
|
||||
|
||||
data = attr.ib()
|
||||
schema = attr.ib(repr=False)
|
||||
|
||||
valid = attr.ib()
|
||||
|
||||
_remotes = attr.ib()
|
||||
|
||||
def __repr__(self): # pragma: no cover
|
||||
return "<Test {}>".format(self.fully_qualified_name)
|
||||
|
||||
@property
|
||||
def fully_qualified_name(self): # pragma: no cover
|
||||
return " > ".join(
|
||||
[
|
||||
self.version.name,
|
||||
self.subject,
|
||||
self.case_description,
|
||||
self.description,
|
||||
]
|
||||
)
|
||||
|
||||
@property
|
||||
def method_name(self):
|
||||
delimiters = r"[\W\- ]+"
|
||||
name = "test_%s_%s_%s" % (
|
||||
re.sub(delimiters, "_", self.subject),
|
||||
re.sub(delimiters, "_", self.case_description),
|
||||
re.sub(delimiters, "_", self.description),
|
||||
)
|
||||
|
||||
if not PY3: # pragma: no cover
|
||||
name = name.encode("utf-8")
|
||||
return name
|
||||
|
||||
def to_unittest_method(self, skip=lambda test: None, **kwargs):
|
||||
if self.valid:
|
||||
def fn(this):
|
||||
self.validate(**kwargs)
|
||||
else:
|
||||
def fn(this):
|
||||
with this.assertRaises(jsonschema.ValidationError):
|
||||
self.validate(**kwargs)
|
||||
|
||||
fn.__name__ = self.method_name
|
||||
reason = skip(self)
|
||||
return unittest.skipIf(reason is not None, reason)(fn)
|
||||
|
||||
def validate(self, Validator, **kwargs):
|
||||
resolver = jsonschema.RefResolver.from_schema(
|
||||
schema=self.schema,
|
||||
store=self._remotes,
|
||||
id_of=Validator.ID_OF,
|
||||
)
|
||||
jsonschema.validate(
|
||||
instance=self.data,
|
||||
schema=self.schema,
|
||||
cls=Validator,
|
||||
resolver=resolver,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def validate_ignoring_errors(self, Validator): # pragma: no cover
|
||||
try:
|
||||
self.validate(Validator=Validator)
|
||||
except jsonschema.ValidationError:
|
||||
pass
|
||||
|
||||
|
||||
def _someone_save_us_the_module_of_the_caller():
|
||||
"""
|
||||
The FQON of the module 2nd stack frames up from here.
|
||||
|
||||
This is intended to allow us to dynamicallly return test case classes that
|
||||
are indistinguishable from being defined in the module that wants them.
|
||||
|
||||
Otherwise, trial will mis-print the FQON, and copy pasting it won't re-run
|
||||
the class that really is running.
|
||||
|
||||
Save us all, this is all so so so so so terrible.
|
||||
"""
|
||||
|
||||
return sys._getframe(2).f_globals["__name__"]
|
151
venv/Lib/site-packages/jsonschema/tests/test_cli.py
Normal file
151
venv/Lib/site-packages/jsonschema/tests/test_cli.py
Normal file
|
@ -0,0 +1,151 @@
|
|||
from unittest import TestCase
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from jsonschema import Draft4Validator, ValidationError, cli, __version__
|
||||
from jsonschema.compat import NativeIO
|
||||
from jsonschema.exceptions import SchemaError
|
||||
|
||||
|
||||
def fake_validator(*errors):
|
||||
errors = list(reversed(errors))
|
||||
|
||||
class FakeValidator(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def iter_errors(self, instance):
|
||||
if errors:
|
||||
return errors.pop()
|
||||
return []
|
||||
|
||||
def check_schema(self, schema):
|
||||
pass
|
||||
|
||||
return FakeValidator
|
||||
|
||||
|
||||
class TestParser(TestCase):
|
||||
|
||||
FakeValidator = fake_validator()
|
||||
instance_file = "foo.json"
|
||||
schema_file = "schema.json"
|
||||
|
||||
def setUp(self):
|
||||
cli.open = self.fake_open
|
||||
self.addCleanup(delattr, cli, "open")
|
||||
|
||||
def fake_open(self, path):
|
||||
if path == self.instance_file:
|
||||
contents = ""
|
||||
elif path == self.schema_file:
|
||||
contents = {}
|
||||
else: # pragma: no cover
|
||||
self.fail("What is {!r}".format(path))
|
||||
return NativeIO(json.dumps(contents))
|
||||
|
||||
def test_find_validator_by_fully_qualified_object_name(self):
|
||||
arguments = cli.parse_args(
|
||||
[
|
||||
"--validator",
|
||||
"jsonschema.tests.test_cli.TestParser.FakeValidator",
|
||||
"--instance", self.instance_file,
|
||||
self.schema_file,
|
||||
]
|
||||
)
|
||||
self.assertIs(arguments["validator"], self.FakeValidator)
|
||||
|
||||
def test_find_validator_in_jsonschema(self):
|
||||
arguments = cli.parse_args(
|
||||
[
|
||||
"--validator", "Draft4Validator",
|
||||
"--instance", self.instance_file,
|
||||
self.schema_file,
|
||||
]
|
||||
)
|
||||
self.assertIs(arguments["validator"], Draft4Validator)
|
||||
|
||||
|
||||
class TestCLI(TestCase):
|
||||
def test_draft3_schema_draft4_validator(self):
|
||||
stdout, stderr = NativeIO(), NativeIO()
|
||||
with self.assertRaises(SchemaError):
|
||||
cli.run(
|
||||
{
|
||||
"validator": Draft4Validator,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{"minimum": 20},
|
||||
{"type": "string"},
|
||||
{"required": True},
|
||||
],
|
||||
},
|
||||
"instances": [1],
|
||||
"error_format": "{error.message}",
|
||||
},
|
||||
stdout=stdout,
|
||||
stderr=stderr,
|
||||
)
|
||||
|
||||
def test_successful_validation(self):
|
||||
stdout, stderr = NativeIO(), NativeIO()
|
||||
exit_code = cli.run(
|
||||
{
|
||||
"validator": fake_validator(),
|
||||
"schema": {},
|
||||
"instances": [1],
|
||||
"error_format": "{error.message}",
|
||||
},
|
||||
stdout=stdout,
|
||||
stderr=stderr,
|
||||
)
|
||||
self.assertFalse(stdout.getvalue())
|
||||
self.assertFalse(stderr.getvalue())
|
||||
self.assertEqual(exit_code, 0)
|
||||
|
||||
def test_unsuccessful_validation(self):
|
||||
error = ValidationError("I am an error!", instance=1)
|
||||
stdout, stderr = NativeIO(), NativeIO()
|
||||
exit_code = cli.run(
|
||||
{
|
||||
"validator": fake_validator([error]),
|
||||
"schema": {},
|
||||
"instances": [1],
|
||||
"error_format": "{error.instance} - {error.message}",
|
||||
},
|
||||
stdout=stdout,
|
||||
stderr=stderr,
|
||||
)
|
||||
self.assertFalse(stdout.getvalue())
|
||||
self.assertEqual(stderr.getvalue(), "1 - I am an error!")
|
||||
self.assertEqual(exit_code, 1)
|
||||
|
||||
def test_unsuccessful_validation_multiple_instances(self):
|
||||
first_errors = [
|
||||
ValidationError("9", instance=1),
|
||||
ValidationError("8", instance=1),
|
||||
]
|
||||
second_errors = [ValidationError("7", instance=2)]
|
||||
stdout, stderr = NativeIO(), NativeIO()
|
||||
exit_code = cli.run(
|
||||
{
|
||||
"validator": fake_validator(first_errors, second_errors),
|
||||
"schema": {},
|
||||
"instances": [1, 2],
|
||||
"error_format": "{error.instance} - {error.message}\t",
|
||||
},
|
||||
stdout=stdout,
|
||||
stderr=stderr,
|
||||
)
|
||||
self.assertFalse(stdout.getvalue())
|
||||
self.assertEqual(stderr.getvalue(), "1 - 9\t1 - 8\t2 - 7\t")
|
||||
self.assertEqual(exit_code, 1)
|
||||
|
||||
def test_version(self):
|
||||
version = subprocess.check_output(
|
||||
[sys.executable, "-m", "jsonschema", "--version"],
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
version = version.decode("utf-8").strip()
|
||||
self.assertEqual(version, __version__)
|
462
venv/Lib/site-packages/jsonschema/tests/test_exceptions.py
Normal file
462
venv/Lib/site-packages/jsonschema/tests/test_exceptions.py
Normal file
|
@ -0,0 +1,462 @@
|
|||
from unittest import TestCase
|
||||
import textwrap
|
||||
|
||||
from jsonschema import Draft4Validator, exceptions
|
||||
from jsonschema.compat import PY3
|
||||
|
||||
|
||||
class TestBestMatch(TestCase):
|
||||
def best_match(self, errors):
|
||||
errors = list(errors)
|
||||
best = exceptions.best_match(errors)
|
||||
reversed_best = exceptions.best_match(reversed(errors))
|
||||
msg = "Didn't return a consistent best match!\nGot: {0}\n\nThen: {1}"
|
||||
self.assertEqual(
|
||||
best._contents(), reversed_best._contents(),
|
||||
msg=msg.format(best, reversed_best),
|
||||
)
|
||||
return best
|
||||
|
||||
def test_shallower_errors_are_better_matches(self):
|
||||
validator = Draft4Validator(
|
||||
{
|
||||
"properties": {
|
||||
"foo": {
|
||||
"minProperties": 2,
|
||||
"properties": {"bar": {"type": "object"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
best = self.best_match(validator.iter_errors({"foo": {"bar": []}}))
|
||||
self.assertEqual(best.validator, "minProperties")
|
||||
|
||||
def test_oneOf_and_anyOf_are_weak_matches(self):
|
||||
"""
|
||||
A property you *must* match is probably better than one you have to
|
||||
match a part of.
|
||||
"""
|
||||
|
||||
validator = Draft4Validator(
|
||||
{
|
||||
"minProperties": 2,
|
||||
"anyOf": [{"type": "string"}, {"type": "number"}],
|
||||
"oneOf": [{"type": "string"}, {"type": "number"}],
|
||||
}
|
||||
)
|
||||
best = self.best_match(validator.iter_errors({}))
|
||||
self.assertEqual(best.validator, "minProperties")
|
||||
|
||||
def test_if_the_most_relevant_error_is_anyOf_it_is_traversed(self):
|
||||
"""
|
||||
If the most relevant error is an anyOf, then we traverse its context
|
||||
and select the otherwise *least* relevant error, since in this case
|
||||
that means the most specific, deep, error inside the instance.
|
||||
|
||||
I.e. since only one of the schemas must match, we look for the most
|
||||
relevant one.
|
||||
"""
|
||||
|
||||
validator = Draft4Validator(
|
||||
{
|
||||
"properties": {
|
||||
"foo": {
|
||||
"anyOf": [
|
||||
{"type": "string"},
|
||||
{"properties": {"bar": {"type": "array"}}},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
best = self.best_match(validator.iter_errors({"foo": {"bar": 12}}))
|
||||
self.assertEqual(best.validator_value, "array")
|
||||
|
||||
def test_if_the_most_relevant_error_is_oneOf_it_is_traversed(self):
|
||||
"""
|
||||
If the most relevant error is an oneOf, then we traverse its context
|
||||
and select the otherwise *least* relevant error, since in this case
|
||||
that means the most specific, deep, error inside the instance.
|
||||
|
||||
I.e. since only one of the schemas must match, we look for the most
|
||||
relevant one.
|
||||
"""
|
||||
|
||||
validator = Draft4Validator(
|
||||
{
|
||||
"properties": {
|
||||
"foo": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"properties": {"bar": {"type": "array"}}},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
best = self.best_match(validator.iter_errors({"foo": {"bar": 12}}))
|
||||
self.assertEqual(best.validator_value, "array")
|
||||
|
||||
def test_if_the_most_relevant_error_is_allOf_it_is_traversed(self):
|
||||
"""
|
||||
Now, if the error is allOf, we traverse but select the *most* relevant
|
||||
error from the context, because all schemas here must match anyways.
|
||||
"""
|
||||
|
||||
validator = Draft4Validator(
|
||||
{
|
||||
"properties": {
|
||||
"foo": {
|
||||
"allOf": [
|
||||
{"type": "string"},
|
||||
{"properties": {"bar": {"type": "array"}}},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
best = self.best_match(validator.iter_errors({"foo": {"bar": 12}}))
|
||||
self.assertEqual(best.validator_value, "string")
|
||||
|
||||
def test_nested_context_for_oneOf(self):
|
||||
validator = Draft4Validator(
|
||||
{
|
||||
"properties": {
|
||||
"foo": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"properties": {
|
||||
"bar": {"type": "array"},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
best = self.best_match(validator.iter_errors({"foo": {"bar": 12}}))
|
||||
self.assertEqual(best.validator_value, "array")
|
||||
|
||||
def test_one_error(self):
|
||||
validator = Draft4Validator({"minProperties": 2})
|
||||
error, = validator.iter_errors({})
|
||||
self.assertEqual(
|
||||
exceptions.best_match(validator.iter_errors({})).validator,
|
||||
"minProperties",
|
||||
)
|
||||
|
||||
def test_no_errors(self):
|
||||
validator = Draft4Validator({})
|
||||
self.assertIsNone(exceptions.best_match(validator.iter_errors({})))
|
||||
|
||||
|
||||
class TestByRelevance(TestCase):
|
||||
def test_short_paths_are_better_matches(self):
|
||||
shallow = exceptions.ValidationError("Oh no!", path=["baz"])
|
||||
deep = exceptions.ValidationError("Oh yes!", path=["foo", "bar"])
|
||||
match = max([shallow, deep], key=exceptions.relevance)
|
||||
self.assertIs(match, shallow)
|
||||
|
||||
match = max([deep, shallow], key=exceptions.relevance)
|
||||
self.assertIs(match, shallow)
|
||||
|
||||
def test_global_errors_are_even_better_matches(self):
|
||||
shallow = exceptions.ValidationError("Oh no!", path=[])
|
||||
deep = exceptions.ValidationError("Oh yes!", path=["foo"])
|
||||
|
||||
errors = sorted([shallow, deep], key=exceptions.relevance)
|
||||
self.assertEqual(
|
||||
[list(error.path) for error in errors],
|
||||
[["foo"], []],
|
||||
)
|
||||
|
||||
errors = sorted([deep, shallow], key=exceptions.relevance)
|
||||
self.assertEqual(
|
||||
[list(error.path) for error in errors],
|
||||
[["foo"], []],
|
||||
)
|
||||
|
||||
def test_weak_validators_are_lower_priority(self):
|
||||
weak = exceptions.ValidationError("Oh no!", path=[], validator="a")
|
||||
normal = exceptions.ValidationError("Oh yes!", path=[], validator="b")
|
||||
|
||||
best_match = exceptions.by_relevance(weak="a")
|
||||
|
||||
match = max([weak, normal], key=best_match)
|
||||
self.assertIs(match, normal)
|
||||
|
||||
match = max([normal, weak], key=best_match)
|
||||
self.assertIs(match, normal)
|
||||
|
||||
def test_strong_validators_are_higher_priority(self):
|
||||
weak = exceptions.ValidationError("Oh no!", path=[], validator="a")
|
||||
normal = exceptions.ValidationError("Oh yes!", path=[], validator="b")
|
||||
strong = exceptions.ValidationError("Oh fine!", path=[], validator="c")
|
||||
|
||||
best_match = exceptions.by_relevance(weak="a", strong="c")
|
||||
|
||||
match = max([weak, normal, strong], key=best_match)
|
||||
self.assertIs(match, strong)
|
||||
|
||||
match = max([strong, normal, weak], key=best_match)
|
||||
self.assertIs(match, strong)
|
||||
|
||||
|
||||
class TestErrorTree(TestCase):
|
||||
def test_it_knows_how_many_total_errors_it_contains(self):
|
||||
# FIXME: https://github.com/Julian/jsonschema/issues/442
|
||||
errors = [
|
||||
exceptions.ValidationError("Something", validator=i)
|
||||
for i in range(8)
|
||||
]
|
||||
tree = exceptions.ErrorTree(errors)
|
||||
self.assertEqual(tree.total_errors, 8)
|
||||
|
||||
def test_it_contains_an_item_if_the_item_had_an_error(self):
|
||||
errors = [exceptions.ValidationError("a message", path=["bar"])]
|
||||
tree = exceptions.ErrorTree(errors)
|
||||
self.assertIn("bar", tree)
|
||||
|
||||
def test_it_does_not_contain_an_item_if_the_item_had_no_error(self):
|
||||
errors = [exceptions.ValidationError("a message", path=["bar"])]
|
||||
tree = exceptions.ErrorTree(errors)
|
||||
self.assertNotIn("foo", tree)
|
||||
|
||||
def test_validators_that_failed_appear_in_errors_dict(self):
|
||||
error = exceptions.ValidationError("a message", validator="foo")
|
||||
tree = exceptions.ErrorTree([error])
|
||||
self.assertEqual(tree.errors, {"foo": error})
|
||||
|
||||
def test_it_creates_a_child_tree_for_each_nested_path(self):
|
||||
errors = [
|
||||
exceptions.ValidationError("a bar message", path=["bar"]),
|
||||
exceptions.ValidationError("a bar -> 0 message", path=["bar", 0]),
|
||||
]
|
||||
tree = exceptions.ErrorTree(errors)
|
||||
self.assertIn(0, tree["bar"])
|
||||
self.assertNotIn(1, tree["bar"])
|
||||
|
||||
def test_children_have_their_errors_dicts_built(self):
|
||||
e1, e2 = (
|
||||
exceptions.ValidationError("1", validator="foo", path=["bar", 0]),
|
||||
exceptions.ValidationError("2", validator="quux", path=["bar", 0]),
|
||||
)
|
||||
tree = exceptions.ErrorTree([e1, e2])
|
||||
self.assertEqual(tree["bar"][0].errors, {"foo": e1, "quux": e2})
|
||||
|
||||
def test_multiple_errors_with_instance(self):
|
||||
e1, e2 = (
|
||||
exceptions.ValidationError(
|
||||
"1",
|
||||
validator="foo",
|
||||
path=["bar", "bar2"],
|
||||
instance="i1"),
|
||||
exceptions.ValidationError(
|
||||
"2",
|
||||
validator="quux",
|
||||
path=["foobar", 2],
|
||||
instance="i2"),
|
||||
)
|
||||
exceptions.ErrorTree([e1, e2])
|
||||
|
||||
def test_it_does_not_contain_subtrees_that_are_not_in_the_instance(self):
|
||||
error = exceptions.ValidationError("123", validator="foo", instance=[])
|
||||
tree = exceptions.ErrorTree([error])
|
||||
|
||||
with self.assertRaises(IndexError):
|
||||
tree[0]
|
||||
|
||||
def test_if_its_in_the_tree_anyhow_it_does_not_raise_an_error(self):
|
||||
"""
|
||||
If a validator is dumb (like :validator:`required` in draft 3) and
|
||||
refers to a path that isn't in the instance, the tree still properly
|
||||
returns a subtree for that path.
|
||||
"""
|
||||
|
||||
error = exceptions.ValidationError(
|
||||
"a message", validator="foo", instance={}, path=["foo"],
|
||||
)
|
||||
tree = exceptions.ErrorTree([error])
|
||||
self.assertIsInstance(tree["foo"], exceptions.ErrorTree)
|
||||
|
||||
|
||||
class TestErrorInitReprStr(TestCase):
|
||||
def make_error(self, **kwargs):
|
||||
defaults = dict(
|
||||
message=u"hello",
|
||||
validator=u"type",
|
||||
validator_value=u"string",
|
||||
instance=5,
|
||||
schema={u"type": u"string"},
|
||||
)
|
||||
defaults.update(kwargs)
|
||||
return exceptions.ValidationError(**defaults)
|
||||
|
||||
def assertShows(self, expected, **kwargs):
|
||||
if PY3: # pragma: no cover
|
||||
expected = expected.replace("u'", "'")
|
||||
expected = textwrap.dedent(expected).rstrip("\n")
|
||||
|
||||
error = self.make_error(**kwargs)
|
||||
message_line, _, rest = str(error).partition("\n")
|
||||
self.assertEqual(message_line, error.message)
|
||||
self.assertEqual(rest, expected)
|
||||
|
||||
def test_it_calls_super_and_sets_args(self):
|
||||
error = self.make_error()
|
||||
self.assertGreater(len(error.args), 1)
|
||||
|
||||
def test_repr(self):
|
||||
self.assertEqual(
|
||||
repr(exceptions.ValidationError(message="Hello!")),
|
||||
"<ValidationError: %r>" % "Hello!",
|
||||
)
|
||||
|
||||
def test_unset_error(self):
|
||||
error = exceptions.ValidationError("message")
|
||||
self.assertEqual(str(error), "message")
|
||||
|
||||
kwargs = {
|
||||
"validator": "type",
|
||||
"validator_value": "string",
|
||||
"instance": 5,
|
||||
"schema": {"type": "string"},
|
||||
}
|
||||
# Just the message should show if any of the attributes are unset
|
||||
for attr in kwargs:
|
||||
k = dict(kwargs)
|
||||
del k[attr]
|
||||
error = exceptions.ValidationError("message", **k)
|
||||
self.assertEqual(str(error), "message")
|
||||
|
||||
def test_empty_paths(self):
|
||||
self.assertShows(
|
||||
"""
|
||||
Failed validating u'type' in schema:
|
||||
{u'type': u'string'}
|
||||
|
||||
On instance:
|
||||
5
|
||||
""",
|
||||
path=[],
|
||||
schema_path=[],
|
||||
)
|
||||
|
||||
def test_one_item_paths(self):
|
||||
self.assertShows(
|
||||
"""
|
||||
Failed validating u'type' in schema:
|
||||
{u'type': u'string'}
|
||||
|
||||
On instance[0]:
|
||||
5
|
||||
""",
|
||||
path=[0],
|
||||
schema_path=["items"],
|
||||
)
|
||||
|
||||
def test_multiple_item_paths(self):
|
||||
self.assertShows(
|
||||
"""
|
||||
Failed validating u'type' in schema[u'items'][0]:
|
||||
{u'type': u'string'}
|
||||
|
||||
On instance[0][u'a']:
|
||||
5
|
||||
""",
|
||||
path=[0, u"a"],
|
||||
schema_path=[u"items", 0, 1],
|
||||
)
|
||||
|
||||
def test_uses_pprint(self):
|
||||
self.assertShows(
|
||||
"""
|
||||
Failed validating u'maxLength' in schema:
|
||||
{0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 4,
|
||||
5: 5,
|
||||
6: 6,
|
||||
7: 7,
|
||||
8: 8,
|
||||
9: 9,
|
||||
10: 10,
|
||||
11: 11,
|
||||
12: 12,
|
||||
13: 13,
|
||||
14: 14,
|
||||
15: 15,
|
||||
16: 16,
|
||||
17: 17,
|
||||
18: 18,
|
||||
19: 19}
|
||||
|
||||
On instance:
|
||||
[0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24]
|
||||
""",
|
||||
instance=list(range(25)),
|
||||
schema=dict(zip(range(20), range(20))),
|
||||
validator=u"maxLength",
|
||||
)
|
||||
|
||||
def test_str_works_with_instances_having_overriden_eq_operator(self):
|
||||
"""
|
||||
Check for https://github.com/Julian/jsonschema/issues/164 which
|
||||
rendered exceptions unusable when a `ValidationError` involved
|
||||
instances with an `__eq__` method that returned truthy values.
|
||||
"""
|
||||
|
||||
class DontEQMeBro(object):
|
||||
def __eq__(this, other): # pragma: no cover
|
||||
self.fail("Don't!")
|
||||
|
||||
def __ne__(this, other): # pragma: no cover
|
||||
self.fail("Don't!")
|
||||
|
||||
instance = DontEQMeBro()
|
||||
error = exceptions.ValidationError(
|
||||
"a message",
|
||||
validator="foo",
|
||||
instance=instance,
|
||||
validator_value="some",
|
||||
schema="schema",
|
||||
)
|
||||
self.assertIn(repr(instance), str(error))
|
||||
|
||||
|
||||
class TestHashable(TestCase):
|
||||
def test_hashable(self):
|
||||
set([exceptions.ValidationError("")])
|
||||
set([exceptions.SchemaError("")])
|
89
venv/Lib/site-packages/jsonschema/tests/test_format.py
Normal file
89
venv/Lib/site-packages/jsonschema/tests/test_format.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
"""
|
||||
Tests for the parts of jsonschema related to the :validator:`format` property.
|
||||
"""
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from jsonschema import FormatError, ValidationError, FormatChecker
|
||||
from jsonschema.validators import Draft4Validator
|
||||
|
||||
|
||||
BOOM = ValueError("Boom!")
|
||||
BANG = ZeroDivisionError("Bang!")
|
||||
|
||||
|
||||
def boom(thing):
|
||||
if thing == "bang":
|
||||
raise BANG
|
||||
raise BOOM
|
||||
|
||||
|
||||
class TestFormatChecker(TestCase):
|
||||
def test_it_can_validate_no_formats(self):
|
||||
checker = FormatChecker(formats=())
|
||||
self.assertFalse(checker.checkers)
|
||||
|
||||
def test_it_raises_a_key_error_for_unknown_formats(self):
|
||||
with self.assertRaises(KeyError):
|
||||
FormatChecker(formats=["o noes"])
|
||||
|
||||
def test_it_can_register_cls_checkers(self):
|
||||
original = dict(FormatChecker.checkers)
|
||||
self.addCleanup(FormatChecker.checkers.pop, "boom")
|
||||
FormatChecker.cls_checks("boom")(boom)
|
||||
self.assertEqual(
|
||||
FormatChecker.checkers,
|
||||
dict(original, boom=(boom, ())),
|
||||
)
|
||||
|
||||
def test_it_can_register_checkers(self):
|
||||
checker = FormatChecker()
|
||||
checker.checks("boom")(boom)
|
||||
self.assertEqual(
|
||||
checker.checkers,
|
||||
dict(FormatChecker.checkers, boom=(boom, ()))
|
||||
)
|
||||
|
||||
def test_it_catches_registered_errors(self):
|
||||
checker = FormatChecker()
|
||||
checker.checks("boom", raises=type(BOOM))(boom)
|
||||
|
||||
with self.assertRaises(FormatError) as cm:
|
||||
checker.check(instance=12, format="boom")
|
||||
|
||||
self.assertIs(cm.exception.cause, BOOM)
|
||||
self.assertIs(cm.exception.__cause__, BOOM)
|
||||
|
||||
# Unregistered errors should not be caught
|
||||
with self.assertRaises(type(BANG)):
|
||||
checker.check(instance="bang", format="boom")
|
||||
|
||||
def test_format_error_causes_become_validation_error_causes(self):
|
||||
checker = FormatChecker()
|
||||
checker.checks("boom", raises=ValueError)(boom)
|
||||
validator = Draft4Validator({"format": "boom"}, format_checker=checker)
|
||||
|
||||
with self.assertRaises(ValidationError) as cm:
|
||||
validator.validate("BOOM")
|
||||
|
||||
self.assertIs(cm.exception.cause, BOOM)
|
||||
self.assertIs(cm.exception.__cause__, BOOM)
|
||||
|
||||
def test_format_checkers_come_with_defaults(self):
|
||||
# This is bad :/ but relied upon.
|
||||
# The docs for quite awhile recommended people do things like
|
||||
# validate(..., format_checker=FormatChecker())
|
||||
# We should change that, but we can't without deprecation...
|
||||
checker = FormatChecker()
|
||||
with self.assertRaises(FormatError):
|
||||
checker.check(instance="not-an-ipv4", format="ipv4")
|
||||
|
||||
def test_repr(self):
|
||||
checker = FormatChecker(formats=())
|
||||
checker.checks("foo")(lambda thing: True)
|
||||
checker.checks("bar")(lambda thing: True)
|
||||
checker.checks("baz")(lambda thing: True)
|
||||
self.assertEqual(
|
||||
repr(checker),
|
||||
"<FormatChecker checkers=['bar', 'baz', 'foo']>",
|
||||
)
|
|
@ -0,0 +1,277 @@
|
|||
"""
|
||||
Test runner for the JSON Schema official test suite
|
||||
|
||||
Tests comprehensive correctness of each draft's validator.
|
||||
|
||||
See https://github.com/json-schema-org/JSON-Schema-Test-Suite for details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
from jsonschema import (
|
||||
Draft3Validator,
|
||||
Draft4Validator,
|
||||
Draft6Validator,
|
||||
Draft7Validator,
|
||||
draft3_format_checker,
|
||||
draft4_format_checker,
|
||||
draft6_format_checker,
|
||||
draft7_format_checker,
|
||||
)
|
||||
from jsonschema.tests._helpers import bug
|
||||
from jsonschema.tests._suite import Suite
|
||||
from jsonschema.validators import _DEPRECATED_DEFAULT_TYPES, create
|
||||
|
||||
|
||||
SUITE = Suite()
|
||||
DRAFT3 = SUITE.version(name="draft3")
|
||||
DRAFT4 = SUITE.version(name="draft4")
|
||||
DRAFT6 = SUITE.version(name="draft6")
|
||||
DRAFT7 = SUITE.version(name="draft7")
|
||||
|
||||
|
||||
def skip(message, **kwargs):
|
||||
def skipper(test):
|
||||
if all(value == getattr(test, attr) for attr, value in kwargs.items()):
|
||||
return message
|
||||
return skipper
|
||||
|
||||
|
||||
def missing_format(checker):
|
||||
def missing_format(test):
|
||||
schema = test.schema
|
||||
if schema is True or schema is False or "format" not in schema:
|
||||
return
|
||||
|
||||
if schema["format"] not in checker.checkers:
|
||||
return "Format checker {0!r} not found.".format(schema["format"])
|
||||
return missing_format
|
||||
|
||||
|
||||
is_narrow_build = sys.maxunicode == 2 ** 16 - 1
|
||||
if is_narrow_build: # pragma: no cover
|
||||
message = "Not running surrogate Unicode case, this Python is narrow."
|
||||
|
||||
def narrow_unicode_build(test): # pragma: no cover
|
||||
return skip(
|
||||
message=message,
|
||||
description="one supplementary Unicode code point is not long enough",
|
||||
)(test) or skip(
|
||||
message=message,
|
||||
description="two supplementary Unicode code points is long enough",
|
||||
)(test)
|
||||
else:
|
||||
def narrow_unicode_build(test): # pragma: no cover
|
||||
return
|
||||
|
||||
|
||||
TestDraft3 = DRAFT3.to_unittest_testcase(
|
||||
DRAFT3.tests(),
|
||||
DRAFT3.optional_tests_of(name="bignum"),
|
||||
DRAFT3.optional_tests_of(name="format"),
|
||||
DRAFT3.optional_tests_of(name="zeroTerminatedFloats"),
|
||||
Validator=Draft3Validator,
|
||||
format_checker=draft3_format_checker,
|
||||
skip=lambda test: (
|
||||
narrow_unicode_build(test)
|
||||
or missing_format(draft3_format_checker)(test)
|
||||
or skip(
|
||||
message="Upstream bug in strict_rfc3339",
|
||||
subject="format",
|
||||
description="case-insensitive T and Z",
|
||||
)(test)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
TestDraft4 = DRAFT4.to_unittest_testcase(
|
||||
DRAFT4.tests(),
|
||||
DRAFT4.optional_tests_of(name="bignum"),
|
||||
DRAFT4.optional_tests_of(name="format"),
|
||||
DRAFT4.optional_tests_of(name="zeroTerminatedFloats"),
|
||||
Validator=Draft4Validator,
|
||||
format_checker=draft4_format_checker,
|
||||
skip=lambda test: (
|
||||
narrow_unicode_build(test)
|
||||
or missing_format(draft4_format_checker)(test)
|
||||
or skip(
|
||||
message=bug(),
|
||||
subject="ref",
|
||||
case_description="Recursive references between schemas",
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(371),
|
||||
subject="ref",
|
||||
case_description="Location-independent identifier",
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(371),
|
||||
subject="ref",
|
||||
case_description=(
|
||||
"Location-independent identifier with absolute URI"
|
||||
),
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(371),
|
||||
subject="ref",
|
||||
case_description=(
|
||||
"Location-independent identifier with base URI change in subschema"
|
||||
),
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(),
|
||||
subject="refRemote",
|
||||
case_description="base URI change - change folder in subschema",
|
||||
)(test)
|
||||
or skip(
|
||||
message="Upstream bug in strict_rfc3339",
|
||||
subject="format",
|
||||
description="case-insensitive T and Z",
|
||||
)(test)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
TestDraft6 = DRAFT6.to_unittest_testcase(
|
||||
DRAFT6.tests(),
|
||||
DRAFT6.optional_tests_of(name="bignum"),
|
||||
DRAFT6.optional_tests_of(name="format"),
|
||||
DRAFT6.optional_tests_of(name="zeroTerminatedFloats"),
|
||||
Validator=Draft6Validator,
|
||||
format_checker=draft6_format_checker,
|
||||
skip=lambda test: (
|
||||
narrow_unicode_build(test)
|
||||
or missing_format(draft6_format_checker)(test)
|
||||
or skip(
|
||||
message=bug(),
|
||||
subject="ref",
|
||||
case_description="Recursive references between schemas",
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(371),
|
||||
subject="ref",
|
||||
case_description="Location-independent identifier",
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(371),
|
||||
subject="ref",
|
||||
case_description=(
|
||||
"Location-independent identifier with absolute URI"
|
||||
),
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(371),
|
||||
subject="ref",
|
||||
case_description=(
|
||||
"Location-independent identifier with base URI change in subschema"
|
||||
),
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(),
|
||||
subject="refRemote",
|
||||
case_description="base URI change - change folder in subschema",
|
||||
)(test)
|
||||
or skip(
|
||||
message="Upstream bug in strict_rfc3339",
|
||||
subject="format",
|
||||
description="case-insensitive T and Z",
|
||||
)(test)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
TestDraft7 = DRAFT7.to_unittest_testcase(
|
||||
DRAFT7.tests(),
|
||||
DRAFT7.format_tests(),
|
||||
DRAFT7.optional_tests_of(name="bignum"),
|
||||
DRAFT7.optional_tests_of(name="content"),
|
||||
DRAFT7.optional_tests_of(name="zeroTerminatedFloats"),
|
||||
Validator=Draft7Validator,
|
||||
format_checker=draft7_format_checker,
|
||||
skip=lambda test: (
|
||||
narrow_unicode_build(test)
|
||||
or missing_format(draft7_format_checker)(test)
|
||||
or skip(
|
||||
message=bug(),
|
||||
subject="ref",
|
||||
case_description="Recursive references between schemas",
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(371),
|
||||
subject="ref",
|
||||
case_description="Location-independent identifier",
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(371),
|
||||
subject="ref",
|
||||
case_description=(
|
||||
"Location-independent identifier with absolute URI"
|
||||
),
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(371),
|
||||
subject="ref",
|
||||
case_description=(
|
||||
"Location-independent identifier with base URI change in subschema"
|
||||
),
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(),
|
||||
subject="refRemote",
|
||||
case_description="base URI change - change folder in subschema",
|
||||
)(test)
|
||||
or skip(
|
||||
message="Upstream bug in strict_rfc3339",
|
||||
subject="date-time",
|
||||
description="case-insensitive T and Z",
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(593),
|
||||
subject="content",
|
||||
case_description=(
|
||||
"validation of string-encoded content based on media type"
|
||||
),
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(593),
|
||||
subject="content",
|
||||
case_description="validation of binary string-encoding",
|
||||
)(test)
|
||||
or skip(
|
||||
message=bug(593),
|
||||
subject="content",
|
||||
case_description=(
|
||||
"validation of binary-encoded media type documents"
|
||||
),
|
||||
)(test)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
|
||||
TestDraft3LegacyTypeCheck = DRAFT3.to_unittest_testcase(
|
||||
# Interestingly the any part couldn't really be done w/the old API.
|
||||
(
|
||||
(test for test in each if test.schema != {"type": "any"})
|
||||
for each in DRAFT3.tests_of(name="type")
|
||||
),
|
||||
name="TestDraft3LegacyTypeCheck",
|
||||
Validator=create(
|
||||
meta_schema=Draft3Validator.META_SCHEMA,
|
||||
validators=Draft3Validator.VALIDATORS,
|
||||
default_types=_DEPRECATED_DEFAULT_TYPES,
|
||||
),
|
||||
)
|
||||
|
||||
TestDraft4LegacyTypeCheck = DRAFT4.to_unittest_testcase(
|
||||
DRAFT4.tests_of(name="type"),
|
||||
name="TestDraft4LegacyTypeCheck",
|
||||
Validator=create(
|
||||
meta_schema=Draft4Validator.META_SCHEMA,
|
||||
validators=Draft4Validator.VALIDATORS,
|
||||
default_types=_DEPRECATED_DEFAULT_TYPES,
|
||||
),
|
||||
)
|
190
venv/Lib/site-packages/jsonschema/tests/test_types.py
Normal file
190
venv/Lib/site-packages/jsonschema/tests/test_types.py
Normal file
|
@ -0,0 +1,190 @@
|
|||
"""
|
||||
Tests on the new type interface. The actual correctness of the type checking
|
||||
is handled in test_jsonschema_test_suite; these tests check that TypeChecker
|
||||
functions correctly and can facilitate extensions to type checking
|
||||
"""
|
||||
from collections import namedtuple
|
||||
from unittest import TestCase
|
||||
|
||||
from jsonschema import ValidationError, _validators
|
||||
from jsonschema._types import TypeChecker
|
||||
from jsonschema.exceptions import UndefinedTypeCheck
|
||||
from jsonschema.validators import Draft4Validator, extend
|
||||
|
||||
|
||||
def equals_2(checker, instance):
|
||||
return instance == 2
|
||||
|
||||
|
||||
def is_namedtuple(instance):
|
||||
return isinstance(instance, tuple) and getattr(instance, "_fields", None)
|
||||
|
||||
|
||||
def is_object_or_named_tuple(checker, instance):
|
||||
if Draft4Validator.TYPE_CHECKER.is_type(instance, "object"):
|
||||
return True
|
||||
return is_namedtuple(instance)
|
||||
|
||||
|
||||
def coerce_named_tuple(fn):
|
||||
def coerced(validator, value, instance, schema):
|
||||
if is_namedtuple(instance):
|
||||
instance = instance._asdict()
|
||||
return fn(validator, value, instance, schema)
|
||||
return coerced
|
||||
|
||||
|
||||
required = coerce_named_tuple(_validators.required)
|
||||
properties = coerce_named_tuple(_validators.properties)
|
||||
|
||||
|
||||
class TestTypeChecker(TestCase):
|
||||
def test_is_type(self):
|
||||
checker = TypeChecker({"two": equals_2})
|
||||
self.assertEqual(
|
||||
(
|
||||
checker.is_type(instance=2, type="two"),
|
||||
checker.is_type(instance="bar", type="two"),
|
||||
),
|
||||
(True, False),
|
||||
)
|
||||
|
||||
def test_is_unknown_type(self):
|
||||
with self.assertRaises(UndefinedTypeCheck) as context:
|
||||
TypeChecker().is_type(4, "foobar")
|
||||
self.assertIn("foobar", str(context.exception))
|
||||
|
||||
def test_checks_can_be_added_at_init(self):
|
||||
checker = TypeChecker({"two": equals_2})
|
||||
self.assertEqual(checker, TypeChecker().redefine("two", equals_2))
|
||||
|
||||
def test_redefine_existing_type(self):
|
||||
self.assertEqual(
|
||||
TypeChecker().redefine("two", object()).redefine("two", equals_2),
|
||||
TypeChecker().redefine("two", equals_2),
|
||||
)
|
||||
|
||||
def test_remove(self):
|
||||
self.assertEqual(
|
||||
TypeChecker({"two": equals_2}).remove("two"),
|
||||
TypeChecker(),
|
||||
)
|
||||
|
||||
def test_remove_unknown_type(self):
|
||||
with self.assertRaises(UndefinedTypeCheck) as context:
|
||||
TypeChecker().remove("foobar")
|
||||
self.assertIn("foobar", str(context.exception))
|
||||
|
||||
def test_redefine_many(self):
|
||||
self.assertEqual(
|
||||
TypeChecker().redefine_many({"foo": int, "bar": str}),
|
||||
TypeChecker().redefine("foo", int).redefine("bar", str),
|
||||
)
|
||||
|
||||
def test_remove_multiple(self):
|
||||
self.assertEqual(
|
||||
TypeChecker({"foo": int, "bar": str}).remove("foo", "bar"),
|
||||
TypeChecker(),
|
||||
)
|
||||
|
||||
def test_type_check_can_raise_key_error(self):
|
||||
"""
|
||||
Make sure no one writes:
|
||||
|
||||
try:
|
||||
self._type_checkers[type](...)
|
||||
except KeyError:
|
||||
|
||||
ignoring the fact that the function itself can raise that.
|
||||
"""
|
||||
|
||||
error = KeyError("Stuff")
|
||||
|
||||
def raises_keyerror(checker, instance):
|
||||
raise error
|
||||
|
||||
with self.assertRaises(KeyError) as context:
|
||||
TypeChecker({"foo": raises_keyerror}).is_type(4, "foo")
|
||||
|
||||
self.assertIs(context.exception, error)
|
||||
|
||||
|
||||
class TestCustomTypes(TestCase):
|
||||
def test_simple_type_can_be_extended(self):
|
||||
def int_or_str_int(checker, instance):
|
||||
if not isinstance(instance, (int, str)):
|
||||
return False
|
||||
try:
|
||||
int(instance)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
CustomValidator = extend(
|
||||
Draft4Validator,
|
||||
type_checker=Draft4Validator.TYPE_CHECKER.redefine(
|
||||
"integer", int_or_str_int,
|
||||
),
|
||||
)
|
||||
validator = CustomValidator({"type": "integer"})
|
||||
|
||||
validator.validate(4)
|
||||
validator.validate("4")
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
validator.validate(4.4)
|
||||
|
||||
def test_object_can_be_extended(self):
|
||||
schema = {"type": "object"}
|
||||
|
||||
Point = namedtuple("Point", ["x", "y"])
|
||||
|
||||
type_checker = Draft4Validator.TYPE_CHECKER.redefine(
|
||||
u"object", is_object_or_named_tuple,
|
||||
)
|
||||
|
||||
CustomValidator = extend(Draft4Validator, type_checker=type_checker)
|
||||
validator = CustomValidator(schema)
|
||||
|
||||
validator.validate(Point(x=4, y=5))
|
||||
|
||||
def test_object_extensions_require_custom_validators(self):
|
||||
schema = {"type": "object", "required": ["x"]}
|
||||
|
||||
type_checker = Draft4Validator.TYPE_CHECKER.redefine(
|
||||
u"object", is_object_or_named_tuple,
|
||||
)
|
||||
|
||||
CustomValidator = extend(Draft4Validator, type_checker=type_checker)
|
||||
validator = CustomValidator(schema)
|
||||
|
||||
Point = namedtuple("Point", ["x", "y"])
|
||||
# Cannot handle required
|
||||
with self.assertRaises(ValidationError):
|
||||
validator.validate(Point(x=4, y=5))
|
||||
|
||||
def test_object_extensions_can_handle_custom_validators(self):
|
||||
schema = {
|
||||
"type": "object",
|
||||
"required": ["x"],
|
||||
"properties": {"x": {"type": "integer"}},
|
||||
}
|
||||
|
||||
type_checker = Draft4Validator.TYPE_CHECKER.redefine(
|
||||
u"object", is_object_or_named_tuple,
|
||||
)
|
||||
|
||||
CustomValidator = extend(
|
||||
Draft4Validator,
|
||||
type_checker=type_checker,
|
||||
validators={"required": required, "properties": properties},
|
||||
)
|
||||
|
||||
validator = CustomValidator(schema)
|
||||
|
||||
Point = namedtuple("Point", ["x", "y"])
|
||||
# Can now process required and properties
|
||||
validator.validate(Point(x=4, y=5))
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
validator.validate(Point(x="not an integer", y=5))
|
1762
venv/Lib/site-packages/jsonschema/tests/test_validators.py
Normal file
1762
venv/Lib/site-packages/jsonschema/tests/test_validators.py
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue