Skip to content

Commit df1501c

Browse files
authored
Merge pull request #1049 from python-jsonschema/referencing
Replace `$ref` & `$dynamicRef` support / `RefResolver` with the new referencing library
2 parents 6b749cf + fcbeced commit df1501c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1052
-2113
lines changed

.github/workflows/ci.yml

-12
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,6 @@ jobs:
3838
toxenv: pypy3-formatnongpl-build
3939
- name: pypy-3.9
4040
toxenv: pypy3-formatnongpl-tests
41-
- name: 3.7
42-
toxenv: py37-noextra-build
43-
- name: 3.7
44-
toxenv: py37-noextra-tests
45-
- name: 3.7
46-
toxenv: py37-format-build
47-
- name: 3.7
48-
toxenv: py37-format-tests
49-
- name: 3.7
50-
toxenv: py37-formatnongpl-build
51-
- name: 3.7
52-
toxenv: py37-formatnongpl-tests
5341
- name: 3.8
5442
toxenv: py38-noextra-build
5543
- name: 3.8

CHANGELOG.rst

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
v4.18.0
2+
=======
3+
4+
* ``jsonschema.RefResolver`` is now deprecated in favor of the new `referencing library <https://github.com/python-jsonschema/referencing/>`_.
5+
``referencing`` will begin in beta, but already is more compliant than the existing ``$ref`` support.
6+
Please file issues on the ``referencing`` tracker if there is functionality missing from it.
7+
18
v4.17.3
29
=======
310

README.rst

+1-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ It can also be used from the command line by installing `check-jsonschema <https
5959
Features
6060
--------
6161

62-
* Partial support for `Draft 2020-12 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft202012Validator>`_ and `Draft 2019-09 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft201909Validator>`_, except for ``dynamicRef`` / ``recursiveRef`` and ``$vocabulary`` (in-progress).
63-
Full support for `Draft 7 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft7Validator>`_, `Draft 6 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft6Validator>`_, `Draft 4 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft4Validator>`_ and `Draft 3 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft3Validator>`_
62+
* Full support for `Draft 2020-12 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft202012Validator>`_, `Draft 2019-09 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft201909Validator>`_, `Draft 7 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft7Validator>`_, `Draft 6 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft6Validator>`_, `Draft 4 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft4Validator>`_ and `Draft 3 <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/validators/#jsonschema.validators.Draft3Validator>`_
6463

6564
* `Lazy validation <https://python-jsonschema.readthedocs.io/en/latest/api/jsonschema/protocols/#jsonschema.protocols.Validator.iter_errors>`_ that can iteratively report *all* validation errors.
6665

docs/api/jsonschema/validators/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
.. automodule:: jsonschema.validators
55
:members:
66
:undoc-members:
7+
:private-members: _RefResolver

docs/conf.py

+18-10
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,36 @@
3838

3939
# See sphinx-doc/sphinx#10785
4040
_TYPE_ALIASES = {
41-
"jsonschema._format._F", # format checkers
41+
"jsonschema._format._F": ("data", "_F"),
4242
}
4343

4444

45-
def _resolve_type_aliases(app, env, node, contnode):
46-
if (
47-
node["refdomain"] == "py"
48-
and node["reftype"] == "class"
49-
and node["reftarget"] in _TYPE_ALIASES
50-
):
45+
def _resolve_broken_refs(app, env, node, contnode):
46+
if node["refdomain"] != "py":
47+
return
48+
49+
if node["reftarget"].startswith("referencing."): # :( :( :( :( :(
50+
node["reftype"] = "data"
51+
from sphinx.ext import intersphinx
52+
return intersphinx.resolve_reference_in_inventory(
53+
env, "referencing", node, contnode,
54+
)
55+
56+
kind, target = _TYPE_ALIASES.get(node["reftarget"], (None, None))
57+
if kind is not None:
5158
return app.env.get_domain("py").resolve_xref(
5259
env,
5360
node["refdoc"],
5461
app.builder,
55-
"data",
56-
node["reftarget"],
62+
kind,
63+
target,
5764
node,
5865
contnode,
5966
)
6067

6168

6269
def setup(app):
63-
app.connect("missing-reference", _resolve_type_aliases)
70+
app.connect("missing-reference", _resolve_broken_refs)
6471

6572

6673
# = Builders =
@@ -116,6 +123,7 @@ def entire_domain(host):
116123

117124
intersphinx_mapping = {
118125
"python": ("https://docs.python.org/3", None),
126+
"referencing": ("https://referencing.readthedocs.io/en/stable/", None),
119127
"ujs": ("https://json-schema.org/understanding-json-schema/", None),
120128
}
121129

docs/errors.rst

+1
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ error objects.
273273

274274
.. testcode::
275275

276+
from jsonschema.exceptions import ErrorTree
276277
tree = ErrorTree(v.iter_errors(instance))
277278

278279
As you can see, `jsonschema.exceptions.ErrorTree` takes an

docs/faq.rst

+2-55
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,10 @@ The JSON object ``{}`` is simply the Python `dict` ``{}``, and a JSON Schema lik
8585

8686
The :kw:`$ref` keyword is a single notable exception.
8787

88-
Specifically, in the case where `jsonschema` is asked to `resolve a remote reference <jsonschema.validators.RefResolver>`, it has no choice but to assume that the remote reference is serialized as JSON, and to deserialize it using the `json` module.
88+
Specifically, in the case where `jsonschema` is asked to resolve a remote reference, it has no choice but to assume that the remote reference is serialized as JSON, and to deserialize it using the `json` module.
8989

9090
One cannot today therefore reference some remote piece of YAML and have it deserialized into Python objects by this library without doing some additional work.
91+
See `Resolving References to Schemas Written in YAML <referencing:Resolving References to Schemas Written in YAML>` for details.
9192

9293
In practice what this means for JSON-like formats like YAML and TOML is that indeed one can generally schematize and then validate them exactly as if they were JSON by simply first deserializing them using libraries like ``PyYAML`` or the like, and passing the resulting Python objects into functions within this library.
9394

@@ -99,60 +100,6 @@ In such cases one is recommended to first pre-process the data such that the res
99100
In the previous example, if the desired behavior is to transparently coerce numeric properties to strings, as Javascript might, then do the conversion explicitly before passing data to this library.
100101

101102

102-
How do I configure a base URI for $ref resolution using local files?
103-
--------------------------------------------------------------------
104-
105-
`jsonschema` supports loading schemas from the filesystem.
106-
107-
The most common mistake when configuring a `jsonschema.validators.RefResolver`
108-
to retrieve schemas from the local filesystem is to give it a base URI
109-
which points to a directory, but forget to add a trailing slash.
110-
111-
For example, given a directory ``/tmp/foo/`` with ``bar/schema.json``
112-
within it, you should use something like:
113-
114-
.. code-block:: python
115-
116-
from pathlib import Path
117-
118-
import jsonschema.validators
119-
120-
path = Path("/tmp/foo")
121-
resolver = jsonschema.validators.RefResolver(
122-
base_uri=f"{path.as_uri()}/",
123-
referrer=True,
124-
)
125-
jsonschema.validate(
126-
instance={},
127-
schema={"$ref": "bar/schema.json"},
128-
resolver=resolver,
129-
)
130-
131-
where note:
132-
133-
* the base URI has a trailing slash, even though
134-
`pathlib.PurePath.as_uri` does not add it!
135-
* any relative refs are now given relative to the provided directory
136-
137-
If you forget the trailing slash, you'll find references are resolved a
138-
directory too high.
139-
140-
You're likely familiar with this behavior from your browser. If you
141-
visit a page at ``https://example.com/foo``, then links on it like
142-
``<a href="./bar">`` take you to ``https://example.com/bar``, not
143-
``https://example.com/foo/bar``. For this reason many sites will
144-
redirect ``https://example.com/foo`` to ``https://example.com/foo/``,
145-
i.e. add the trailing slash, so that relative links on the page will keep the
146-
last path component.
147-
148-
There are, in summary, 2 ways to do this properly:
149-
150-
* Remember to include a trailing slash, so your base URI is
151-
``file:///foo/bar/`` rather than ``file:///foo/bar``, as shown above
152-
* Use a file within the directory as your base URI rather than the
153-
directory itself, i.e. ``file://foo/bar/baz.json``, which will of course
154-
cause ``baz.json`` to be removed while resolving relative URIs
155-
156103
Why doesn't my schema's default property set the default on my instance?
157104
------------------------------------------------------------------------
158105

docs/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Contents
1212

1313
validate
1414
errors
15+
referencing
1516
creating
1617
faq
1718
api/index

0 commit comments

Comments
 (0)