Skip to content

Commit 6345ad8

Browse files
committed
Add more prose docs on adding resources to registries.
1 parent 19b82a6 commit 6345ad8

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

docs/intro.rst

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,153 @@ You could also confirm your resource is in the registry if you'd like, via `refe
5252
.. testoutput::
5353

5454
{'type': 'integer'}
55+
56+
Populating Registries
57+
---------------------
58+
59+
There are a few different methods you can use to populate registries with resources.
60+
Which one you want to use depends on things like:
61+
62+
* do you already have an instance of `referencing.Resource`, or are you creating one out of some loaded JSON?
63+
If not, does the JSON have some sort of identifier that can be used to determine which specification it belongs to (e.g. the JSON Schema ``$schema`` keyword)?
64+
* does your resource have an internal ID (e.g. the JSON Schema ``$id`` keyword)?
65+
* do you have additional (external) URIs you want to refer to the same resource as well?
66+
* do you have one resource to add or many?
67+
68+
We'll assume for example's sake that we're dealing with JSON Schema resources for the following examples, and we'll furthermore assume you have some initial `referencing.Registry` to add them to, perhaps an empty one:
69+
70+
.. testcode::
71+
72+
from referencing import Registry
73+
initial_registry = Registry()
74+
75+
Recall that registries are immutable, so we'll be "adding" our resources by creating new registries containing the additional resource(s) we add.
76+
77+
In the ideal case, you have a JSON Schema with an internal ID, and which also identifies itself for a specific version of JSON Schema e.g.:
78+
79+
.. code:: json
80+
81+
{
82+
"$id": "urn:example:my-schema",
83+
"$schema": "https://json-schema.org/draft/2020-12/schema",
84+
"type": "integer"
85+
}
86+
87+
If you have such a schema in some JSON text, and wish to add a resource to our registry and be able to identify it using its internal ID (``urn:example:my-schema``) you can simply use:
88+
89+
.. testcode::
90+
91+
import json
92+
93+
loaded = json.loads(
94+
"""
95+
{
96+
"$id": "urn:example:my-schema",
97+
"$schema": "https://json-schema.org/draft/2020-12/schema",
98+
"type": "integer"
99+
}
100+
""",
101+
)
102+
resource = Resource.from_contents(loaded)
103+
registry = resource @ initial_registry
104+
105+
which will give you a registry with our resource added to it.
106+
Let's check by using `Registry.contents`, which takes a URI and should show us the contents of our resource:
107+
108+
.. testcode::
109+
110+
print(registry.contents("urn:example:my-schema"))
111+
112+
.. testoutput::
113+
114+
{'$id': 'urn:example:my-schema', '$schema': 'https://json-schema.org/draft/2020-12/schema', 'type': 'integer'}
115+
116+
If your schema did *not* have a ``$schema`` keyword, you'd get an error:
117+
118+
.. testcode::
119+
120+
another = json.loads(
121+
"""
122+
{
123+
"$id": "urn:example:my-second-schema",
124+
"type": "integer"
125+
}
126+
""",
127+
)
128+
print(Resource.from_contents(another))
129+
130+
.. testoutput::
131+
132+
Traceback (most recent call last):
133+
...
134+
referencing.exceptions.CannotDetermineSpecification: {'$id': 'urn:example:my-second-schema', 'type': 'integer'}
135+
136+
which is telling you that the resource you've tried to create is ambiguous -- there's no way to know which version of JSON Schema you intend it to be written for.
137+
138+
You can of course instead directly create a `Resource`, instead of using `Resource.from_contents`, which will allow you to specify which version of JSON Schema you're intending your schema to be written for:
139+
140+
.. testcode::
141+
142+
import referencing.jsonschema
143+
second = Resource(contents=another, specification=referencing.jsonschema.DRAFT202012)
144+
145+
and now of course can add it as above:
146+
147+
.. testcode::
148+
149+
registry = second @ registry
150+
print(registry.contents("urn:example:my-second-schema"))
151+
152+
.. testoutput::
153+
154+
{'$id': 'urn:example:my-second-schema', 'type': 'integer'}
155+
156+
As a shorthand, you can also use `Specification.create_resource` to create a `Resource` slightly more tersely.
157+
E.g., an equivalent way to create the above resource is:
158+
159+
.. testcode::
160+
161+
second_again = referencing.jsonschema.DRAFT202012.create_resource(another)
162+
print(second_again == second)
163+
164+
.. testoutput::
165+
166+
True
167+
168+
If your resource doesn't contain an ``$id`` keyword, you'll get a different error if you attempt to add it to a registry:
169+
170+
.. testcode::
171+
172+
third = Resource(
173+
contents=json.loads("""{"type": "integer"}"""),
174+
specification=referencing.jsonschema.DRAFT202012,
175+
)
176+
registry = third @ registry
177+
178+
.. testoutput::
179+
180+
Traceback (most recent call last):
181+
...
182+
referencing.exceptions.NoInternalID: Resource(contents={'type': 'integer'}, _specification=<Specification name='draft2020-12'>)
183+
184+
which is now saying that there's no way to add this resource to a registry directly, as it has no ``$id`` -- you must provide whatever URI you intend to use to refer to this resource to be able to add it.
185+
186+
You can do so using `referencing.Registry.with_resource` instead of the `@ operator <referencing.Registry.__rmatmul__>` which we have used thus far, and which takes the explicit URI you wish to use as an argument:
187+
188+
.. testcode::
189+
190+
registry = registry.with_resource(uri="urn:example:my-third-schema", resource=third)
191+
192+
which now allows us to use the URI we associated with our third resource to retrieve it:
193+
194+
.. testcode::
195+
196+
print(registry.contents("urn:example:my-third-schema"))
197+
198+
.. testoutput::
199+
200+
{'type': 'integer'}
201+
202+
If you have more than one resource to add, you can use `Registry.with_resources` (with an ``s``) to add many at once, or, if they meet the criteria to use ``@``, you can use ``[one, two, three] @ registry`` to add all three resources at once.
203+
204+
You may also want to have a look at `Registry.with_contents` for a further method to add resources to a registry without constructing a `Resource` object yourself.

0 commit comments

Comments
 (0)