Skip to content

Replace $ref & $dynamicRef support / RefResolver with the new referencing library #1049

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 33 commits into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0ce3cef
Drop support for 3.7.
Julian Dec 28, 2022
bf94d57
Move to retrieving schemas from the jsonschema-specifications registry.
Julian Dec 28, 2022
238e711
Deprecate jsonschema.RefResolver from both places it is importable.
Julian Dec 29, 2022
f6aa053
Load the test suite into a referencing.Registry for running tests.
Julian Feb 9, 2023
2c8f643
Minor regrouping of some to-be-modified/deprecated RefResolver tests.
Julian Feb 9, 2023
52340d7
Offload a small initial bit of id-related code to referencing.
Julian Feb 14, 2023
4ec24ab
Inline a function that will be RefResolver specific.
Julian Feb 15, 2023
9da55df
Move reference resolution to a (private) Validator method.
Julian Feb 15, 2023
635dc13
Deprecate Validator.resolver.
Julian Feb 15, 2023
69f3899
Actually depend on referencing and update docs requirements.
Julian Feb 16, 2023
2889feb
Make an evolve test not refer to reference resolution.
Julian Feb 16, 2023
a39e5c9
Move Validator._resolver to _ref_resolver.
Julian Feb 16, 2023
e826629
Resolve $ref using the referencing library.
Julian Feb 16, 2023
a93e88b
Claim full support now that we pass all referencing tests.
Julian Feb 16, 2023
bdda723
Flail to get Sphinx to find references again.
Julian Feb 16, 2023
a42bbd9
Fix the benchmark to pass the right type for remotes again.
Julian Feb 16, 2023
bd6a7d0
Update docs requirements.
Julian Feb 19, 2023
33e2882
Pin to newer pyrsistent.
Julian Feb 21, 2023
fcea5ad
Tighten up a type in the tests.
Julian Feb 21, 2023
34d19dc
Add some prose documentation on the new referencing API.
Julian Feb 22, 2023
8c4cd7c
These pass now actually.
Julian Feb 22, 2023
e922e79
Style
Julian Feb 22, 2023
25f40e5
Again bump the referencing version.
Julian Feb 23, 2023
787dbc9
Re-add the direct test of RefResolver's deprecation.
Julian Feb 23, 2023
3801d9a
Improve error messages for deprecation tests when they fail.
Julian Feb 23, 2023
19bdf61
Three more exception-related deprecations.
Julian Feb 23, 2023
84199e9
Elaborate a bit more in the referencing doc
Julian Feb 27, 2023
eb00447
Replace the other usages of pyrsistent with rpds.
Julian Mar 5, 2023
2b547c7
Avoid whatever nonsense pkg_resources error.
Julian Mar 6, 2023
94c60e4
Speed up Validator.evolve by pre-computing fields.
Julian Mar 6, 2023
1854b26
Bump requirements.
Julian Mar 8, 2023
4d6bff9
Link to the new referencing doc page.
Julian Mar 9, 2023
fcbeced
Another version bump.
Julian Mar 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Elaborate a bit more in the referencing doc
  • Loading branch information
Julian committed Feb 27, 2023
commit 84199e984aba5f2c6bf5b121eb95faedc53951fc
61 changes: 60 additions & 1 deletion docs/referencing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,53 @@ The examples below essentially follow these two steps.
.. [1] One that in fact is independent of this `jsonschema` library itself, and may some day be used by other tools or implementations.


Introduction to the `referencing <referencing:index>` API
---------------------------------------------------------

There are 3 main objects to be aware of in the `referencing` API:

* `referencing.Registry`, which represents a specific immutable set of JSON Schemas (either in-memory or retrievable)
* `referencing.Specification`, which represents a specific *version* of the JSON Schema specification, which can have differing referencing behavior.
JSON Schema-specific specifications live in the `referencing.jsonschema` module and are named like `referencing.jsonschema.DRAFT202012`.
* `referencing.Resource`, which represents a specific JSON Schema (often a Python `dict`) *along* with a specific `referencing.Specification` it is to be interpreted under.

As a concrete example, the simple schema ``{"type": "integer"}`` may be interpreted as a schema under either Draft 2020-12 or Draft 4 of the JSON Schema specification (amongst others); in draft 2020-12, the float ``2.0`` must be considered an integer, whereas in draft 4, it potentially is not.
If you mean the former (i.e. to associate this schema with draft 2020-12), you'd use ``referencing.Resource(contents={"type": "integer"}, specification=referencing.jsonschema.DRAFT202012)``, whereas for the latter you'd use `referencing.jsonschema.DRAFT4`.

.. seealso:: the JSON Schema :kw:`$schema` keyword

Which should generally be used to remove all ambiguity and identify *internally* to the schema what version it is written for.

A schema may be identified via one or more URIs, either because they contain an :kw:`$id` keyword (in suitable versions of the JSON Schema specification) which indicates their canonical URI, or simply because you wish to externally associate a URI with the schema, regardless of whether it contains an ``$id`` keyword.
You could add the aforementioned simple schema to a `referencing.Registry` by creating an empty registry and then identifying it via some URI:

.. testcode::

from referencing import Registry, Resource
from referencing.jsonschema import DRAFT202012
schema = Resource(contents={"type": "integer"}, specification=DRAFT202012)
registry = Registry().with_resource(uri="http://example.com/my/schema", resource=schema)
print(registry)

.. testoutput::

<Registry (1 uncrawled resource)>

.. note::

`referencing.Registry` is an entirely immutable object.
All of its methods which add schemas (resources) to itself return *new* registry objects containing the added schemas.

You could also confirm your schema is in the registry if you'd like, via `referencing.Registry.contents`, which will show you the contents of a resource at a given URI:

.. testcode::

print(registry.contents("http://example.com/my/schema"))

.. testoutput::

{'type': 'integer'}

Common Scenarios
----------------

Expand Down Expand Up @@ -244,7 +291,19 @@ Older versions of `jsonschema` used a different object -- `_RefResolver` -- for

If you are not already constructing your own `_RefResolver`, this change should be transparent to you (or even recognizably improved, as the point of the migration was to improve the quality of the referencing implementation and enable some new functionality).

If you *were* configuring your own `_RefResolver`, here's how to migrate to the newer APIs:
.. table:: Rough equivalence between `_RefResolver` and `referencing.Registry` APIs
:widths: auto

=========================================================== =====================================================================================================================
Old API New API
=========================================================== =====================================================================================================================
``RefResolver.from_schema({"$id": "urn:example:foo", ...}`` ``Registry().with_resource(uri="urn:example:foo", resource=Resource.from_contents({"$id": "urn:example:foo", ...}))``
Overriding ``RefResolver.resolve_from_url`` Passing a callable to `referencing.Registry`\ 's ``retrieve`` argument
``DraftNValidator(..., resolver=_RefResolver(...))`` `` DraftNValidator(..., registry=Registry().with_resources(...))``
=========================================================== =====================================================================================================================


Here are some more specifics on how to migrate to the newer APIs:

The ``store`` argument
~~~~~~~~~~~~~~~~~~~~~~
Expand Down
8 changes: 4 additions & 4 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jinja2==3.1.2
# sphinx-autoapi
file:.#egg=jsonschema
# via -r docs/requirements.in
jsonschema-specifications==2023.3.1
jsonschema-specifications==2023.3.2
# via jsonschema
kiwisolver==1.4.4
# via matplotlib
Expand Down Expand Up @@ -82,7 +82,7 @@ pytz==2022.7.1
# via babel
pyyaml==6.0
# via sphinx-autoapi
referencing==0.21.0
referencing==0.21.1
# via
# jsonschema
# jsonschema-specifications
Expand Down Expand Up @@ -113,7 +113,7 @@ sphinx-basic-ng==1.0.0b1
# via furo
sphinx-copybutton==0.5.1
# via -r docs/requirements.in
sphinx-json-schema-spec==2023.2.2
sphinx-json-schema-spec==2023.2.4
# via -r docs/requirements.in
sphinxcontrib-applehelp==1.0.4
# via sphinx
Expand All @@ -135,5 +135,5 @@ unidecode==1.3.6
# via sphinx-autoapi
urllib3==1.26.14
# via requests
wrapt==1.14.1
wrapt==1.15.0
# via astroid
1 change: 1 addition & 0 deletions docs/spelling-wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ ValidationError

# 0th, sigh...
th
amongst
callables
# non-codeblocked cls from autoapi
cls
Expand Down