def resolve(self, ref, document=None):
"""Resolve a fragment within the schema.
If the resolved value contains a $ref, it will attempt to resolve that
as well, until it gets something that is not a reference. Circular
references will raise a SchemaError.
:param str ref: URI to resolve.
:param dict document: Optional schema in which to resolve the URI.
:returns: a tuple of the final, resolved URI (after any recursion) and
resolved value in the schema that the URI references.
"""
try:
# This logic is basically the RefResolver's resolve function, but
# updated to support fragments of dynamic documents. The jsonschema
# module supports passing documents when resolving fragments, but
# it doesn't expose that capability in the resolve function.
url = self._urljoin_cache(self.resolution_scope, ref)
if document is None:
# No document passed, so just resolve it as we normally would.
resolved = self._remote_cache(url)
else:
# Document passed, so assume it's a fragment.
_, fragment = urldefrag(url)
resolved = self.resolve_fragment(document, fragment)
except jsonschema.RefResolutionError as e:
# Failed to find a ref. Make the error a bit prettier so we can
# figure out where it came from.
message = e.args[0]
if self._scopes_stack:
message = '{} (from {})'.format(
message, self._format_stack(self._scopes_stack))
raise SchemaError(message)
if isinstance(resolved, dict) and '$ref' in resolved:
# Try to resolve the reference, so we can get the actual value we
# want, instead of a useless dict with a $ref in it.
if url in self._scopes_stack:
# We've already tried to look up this URL, so this must
# be a circular reference in the schema.
raise SchemaError(
'Circular reference in schema: {}'.format(
self._format_stack(self._scopes_stack + [url])))
try:
self.push_scope(url)
return self.resolve(resolved['$ref'])
finally:
self.pop_scope()
else:
return url, resolved
评论列表
文章目录