diff options
author | maxim-yurchuk <maxim-yurchuk@yandex-team.com> | 2024-10-09 12:29:46 +0300 |
---|---|---|
committer | maxim-yurchuk <maxim-yurchuk@yandex-team.com> | 2024-10-09 13:14:22 +0300 |
commit | 9731d8a4bb7ee2cc8554eaf133bb85498a4c7d80 (patch) | |
tree | a8fb3181d5947c0d78cf402aa56e686130179049 /contrib/python/jsonschema | |
parent | a44b779cd359f06c3ebbef4ec98c6b38609d9d85 (diff) | |
download | ydb-9731d8a4bb7ee2cc8554eaf133bb85498a4c7d80.tar.gz |
publishFullContrib: true for ydb
<HIDDEN_URL>
commit_hash:c82a80ac4594723cebf2c7387dec9c60217f603e
Diffstat (limited to 'contrib/python/jsonschema')
15 files changed, 1184 insertions, 0 deletions
diff --git a/contrib/python/jsonschema/py2/.yandex_meta/yamaker.yaml b/contrib/python/jsonschema/py2/.yandex_meta/yamaker.yaml new file mode 100644 index 0000000000..da6fd45b32 --- /dev/null +++ b/contrib/python/jsonschema/py2/.yandex_meta/yamaker.yaml @@ -0,0 +1,4 @@ +exclude: + - json/* +mark_as_tests: + - jsonschema/benchmarks/* diff --git a/contrib/python/jsonschema/py2/jsonschema/benchmarks/__init__.py b/contrib/python/jsonschema/py2/jsonschema/benchmarks/__init__.py new file mode 100644 index 0000000000..e3dcc68993 --- /dev/null +++ b/contrib/python/jsonschema/py2/jsonschema/benchmarks/__init__.py @@ -0,0 +1,5 @@ +""" +Benchmarks for validation. + +This package is *not* public API. +""" diff --git a/contrib/python/jsonschema/py2/jsonschema/benchmarks/issue232.py b/contrib/python/jsonschema/py2/jsonschema/benchmarks/issue232.py new file mode 100644 index 0000000000..65e3aedf79 --- /dev/null +++ b/contrib/python/jsonschema/py2/jsonschema/benchmarks/issue232.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +""" +A performance benchmark using the example from issue #232. + +See https://github.com/Julian/jsonschema/pull/232. +""" +from twisted.python.filepath import FilePath +from pyperf import Runner +from pyrsistent import m + +from jsonschema.tests._suite import Version +import jsonschema + + +issue232 = Version( + path=FilePath(__file__).sibling("issue232"), + remotes=m(), + name="issue232", +) + + +if __name__ == "__main__": + issue232.benchmark( + runner=Runner(), + Validator=jsonschema.Draft4Validator, + ) diff --git a/contrib/python/jsonschema/py2/jsonschema/benchmarks/json_schema_test_suite.py b/contrib/python/jsonschema/py2/jsonschema/benchmarks/json_schema_test_suite.py new file mode 100644 index 0000000000..5add5051df --- /dev/null +++ b/contrib/python/jsonschema/py2/jsonschema/benchmarks/json_schema_test_suite.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +""" +A performance benchmark using the official test suite. + +This benchmarks jsonschema using every valid example in the +JSON-Schema-Test-Suite. It will take some time to complete. +""" +from pyperf import Runner + +from jsonschema.tests._suite import Suite + + +if __name__ == "__main__": + Suite().benchmark(runner=Runner()) diff --git a/contrib/python/jsonschema/py2/jsonschema/tests/_suite.py b/contrib/python/jsonschema/py2/jsonschema/tests/_suite.py new file mode 100644 index 0000000000..b68a7b668c --- /dev/null +++ b/contrib/python/jsonschema/py2/jsonschema/tests/_suite.py @@ -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__"] diff --git a/contrib/python/jsonschema/py2/jsonschema/tests/test_jsonschema_test_suite.py b/contrib/python/jsonschema/py2/jsonschema/tests/test_jsonschema_test_suite.py new file mode 100644 index 0000000000..ebccf29735 --- /dev/null +++ b/contrib/python/jsonschema/py2/jsonschema/tests/test_jsonschema_test_suite.py @@ -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, + ), + ) diff --git a/contrib/python/jsonschema/py2/patches/01-fix-tests.patch b/contrib/python/jsonschema/py2/patches/01-fix-tests.patch new file mode 100644 index 0000000000..f35892f04f --- /dev/null +++ b/contrib/python/jsonschema/py2/patches/01-fix-tests.patch @@ -0,0 +1,23 @@ +--- contrib/python/jsonschema/py2/jsonschema/tests/test_cli.py (index) ++++ contrib/python/jsonschema/py2/jsonschema/tests/test_cli.py (working tree) +@@ -49,7 +49,7 @@ class TestParser(TestCase): + arguments = cli.parse_args( + [ + "--validator", +- "jsonschema.tests.test_cli.TestParser.FakeValidator", ++ "__tests__.test_cli.TestParser.FakeValidator", # XXX Arcadia + "--instance", self.instance_file, + self.schema_file, + ] +@@ -141,11 +141,3 @@ class TestCLI(TestCase): + 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__) diff --git a/contrib/python/jsonschema/py3/.yandex_meta/yamaker.yaml b/contrib/python/jsonschema/py3/.yandex_meta/yamaker.yaml new file mode 100644 index 0000000000..da6fd45b32 --- /dev/null +++ b/contrib/python/jsonschema/py3/.yandex_meta/yamaker.yaml @@ -0,0 +1,4 @@ +exclude: + - json/* +mark_as_tests: + - jsonschema/benchmarks/* diff --git a/contrib/python/jsonschema/py3/jsonschema/benchmarks/__init__.py b/contrib/python/jsonschema/py3/jsonschema/benchmarks/__init__.py new file mode 100644 index 0000000000..e3dcc68993 --- /dev/null +++ b/contrib/python/jsonschema/py3/jsonschema/benchmarks/__init__.py @@ -0,0 +1,5 @@ +""" +Benchmarks for validation. + +This package is *not* public API. +""" diff --git a/contrib/python/jsonschema/py3/jsonschema/benchmarks/issue232.py b/contrib/python/jsonschema/py3/jsonschema/benchmarks/issue232.py new file mode 100644 index 0000000000..65e3aedf79 --- /dev/null +++ b/contrib/python/jsonschema/py3/jsonschema/benchmarks/issue232.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +""" +A performance benchmark using the example from issue #232. + +See https://github.com/Julian/jsonschema/pull/232. +""" +from twisted.python.filepath import FilePath +from pyperf import Runner +from pyrsistent import m + +from jsonschema.tests._suite import Version +import jsonschema + + +issue232 = Version( + path=FilePath(__file__).sibling("issue232"), + remotes=m(), + name="issue232", +) + + +if __name__ == "__main__": + issue232.benchmark( + runner=Runner(), + Validator=jsonschema.Draft4Validator, + ) diff --git a/contrib/python/jsonschema/py3/jsonschema/benchmarks/json_schema_test_suite.py b/contrib/python/jsonschema/py3/jsonschema/benchmarks/json_schema_test_suite.py new file mode 100644 index 0000000000..5add5051df --- /dev/null +++ b/contrib/python/jsonschema/py3/jsonschema/benchmarks/json_schema_test_suite.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +""" +A performance benchmark using the official test suite. + +This benchmarks jsonschema using every valid example in the +JSON-Schema-Test-Suite. It will take some time to complete. +""" +from pyperf import Runner + +from jsonschema.tests._suite import Suite + + +if __name__ == "__main__": + Suite().benchmark(runner=Runner()) diff --git a/contrib/python/jsonschema/py3/jsonschema/tests/_suite.py b/contrib/python/jsonschema/py3/jsonschema/tests/_suite.py new file mode 100644 index 0000000000..b68a7b668c --- /dev/null +++ b/contrib/python/jsonschema/py3/jsonschema/tests/_suite.py @@ -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__"] diff --git a/contrib/python/jsonschema/py3/jsonschema/tests/test_jsonschema_test_suite.py b/contrib/python/jsonschema/py3/jsonschema/tests/test_jsonschema_test_suite.py new file mode 100644 index 0000000000..ebccf29735 --- /dev/null +++ b/contrib/python/jsonschema/py3/jsonschema/tests/test_jsonschema_test_suite.py @@ -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, + ), + ) diff --git a/contrib/python/jsonschema/py3/patches/01-fix-tests.patch b/contrib/python/jsonschema/py3/patches/01-fix-tests.patch new file mode 100644 index 0000000000..4a23eff69a --- /dev/null +++ b/contrib/python/jsonschema/py3/patches/01-fix-tests.patch @@ -0,0 +1,23 @@ +--- contrib/python/jsonschema/py3/jsonschema/tests/test_cli.py (index) ++++ contrib/python/jsonschema/py3/jsonschema/tests/test_cli.py (working tree) +@@ -49,7 +49,7 @@ class TestParser(TestCase): + arguments = cli.parse_args( + [ + "--validator", +- "jsonschema.tests.test_cli.TestParser.FakeValidator", ++ "__tests__.test_cli.TestParser.FakeValidator", # XXX Arcadia + "--instance", self.instance_file, + self.schema_file, + ] +@@ -141,11 +141,3 @@ class TestCLI(TestCase): + 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__) diff --git a/contrib/python/jsonschema/py3/patches/02-support-python-3.12.patch b/contrib/python/jsonschema/py3/patches/02-support-python-3.12.patch new file mode 100644 index 0000000000..691c43b437 --- /dev/null +++ b/contrib/python/jsonschema/py3/patches/02-support-python-3.12.patch @@ -0,0 +1,8 @@ +--- contrib/python/jsonschema/py3/jsonschema/tests/test_validators.py (8114480972e2ddb6aa7203d22024fbc36b1b6fec) ++++ contrib/python/jsonschema/py3/jsonschema/tests/test_validators.py (462a1dacdcd6f4eb462650be556c7378a1dc9e4a) +@@ -1528 +1528 @@ class TestValidate(SynchronousTestCase): +- self.assertRegexpMatches( ++ self.assertRegex( +@@ -1536 +1536 @@ class TestValidate(SynchronousTestCase): +- self.assertRegexpMatches( ++ self.assertRegex( |