summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Berman <Julian@GrayVines.com>2022-08-18 11:22:16 +0300
committerJulian Berman <Julian@GrayVines.com>2022-08-18 11:22:16 +0300
commite69cb7ab504740a58766fad757bb5d01e5e812f6 (patch)
tree361f6a90486e88d868cbf171709c10f2d2aacfed
parent549f9e545aae5ab6812940e082795527557e1448 (diff)
downloadjsonschema-e69cb7ab504740a58766fad757bb5d01e5e812f6.tar.gz
Warn at runtime when subclassing validator classes.v4.12.0
Doing so was not intended to be public API, though it seems some downstream libraries do so. A future version will make this an error, as it is brittle and better served by composing validator objects instead. Feel free to reach out if there are any cases where changing existing code seems difficult and I can try to provide guidance. Refs: #982
-rw-r--r--jsonschema/tests/test_deprecations.py25
-rw-r--r--jsonschema/tests/test_validators.py9
-rw-r--r--jsonschema/validators.py15
3 files changed, 45 insertions, 4 deletions
diff --git a/jsonschema/tests/test_deprecations.py b/jsonschema/tests/test_deprecations.py
index 58fd050..fcf7902 100644
--- a/jsonschema/tests/test_deprecations.py
+++ b/jsonschema/tests/test_deprecations.py
@@ -121,3 +121,28 @@ class TestDeprecations(TestCase):
"Passing a schema to Validator.iter_errors is deprecated ",
),
)
+
+ def test_Validator_subclassing(self):
+ """
+ As of v4.12.0, subclassing a validator class produces an explicit
+ deprecation warning.
+
+ This was never intended to be public API (and some comments over the
+ years in issues said so, but obviously that's not a great way to make
+ sure it's followed).
+
+ A future version will explicitly raise an error.
+ """
+
+ with self.assertWarns(DeprecationWarning) as w:
+ class Subclass(validators.Draft202012Validator):
+ pass
+
+ self.assertEqual(w.filename, __file__)
+ self.assertTrue(
+ str(w.warning).startswith("Subclassing validator classes is "),
+ )
+
+ with self.assertWarns(DeprecationWarning) as w:
+ class AnotherSubclass(validators.create(meta_schema={})):
+ pass
diff --git a/jsonschema/tests/test_validators.py b/jsonschema/tests/test_validators.py
index 4ebc8db..e4f60ea 100644
--- a/jsonschema/tests/test_validators.py
+++ b/jsonschema/tests/test_validators.py
@@ -1485,10 +1485,11 @@ class ValidatorTestMixin(MetaSchemaTestsMixin, object):
the interim, we haven't broken those users.
"""
- @attr.s
- class OhNo(self.Validator):
- foo = attr.ib(factory=lambda: [1, 2, 3])
- _bar = attr.ib(default=37)
+ with self.assertWarns(DeprecationWarning):
+ @attr.s
+ class OhNo(self.Validator):
+ foo = attr.ib(factory=lambda: [1, 2, 3])
+ _bar = attr.ib(default=37)
validator = OhNo({}, bar=12)
self.assertEqual(validator.foo, [1, 2, 3])
diff --git a/jsonschema/validators.py b/jsonschema/validators.py
index 79a8da3..e6d5370 100644
--- a/jsonschema/validators.py
+++ b/jsonschema/validators.py
@@ -191,6 +191,21 @@ def create(
resolver = attr.ib(default=None, repr=False)
format_checker = attr.ib(default=None)
+ def __init_subclass__(cls):
+ warnings.warn(
+ (
+ "Subclassing validator classes is not intended to "
+ "be part of their public API. A future version "
+ "will make doing so an error, as the behavior of "
+ "subclasses isn't guaranteed to stay the same "
+ "between releases of jsonschema. Instead, prefer "
+ "composition of validators, wrapping them in an object "
+ "owned entirely by the downstream library."
+ ),
+ DeprecationWarning,
+ stacklevel=2,
+ )
+
def __attrs_post_init__(self):
if self.resolver is None:
self.resolver = RefResolver.from_schema(