Skip to content

Commit

Permalink
Improve internal terminology for retrieval URI
Browse files Browse the repository at this point in the history
The retrieval URI was internally called the 'ref base' or 'schema
URI', both of which suggest that it is definitively the base URI used
for reference resolution. This makes it confusing that adjusting this
URI might not change the base URI used.

Instead, call it properly 'retrieval URI'.

Base URI is newly introduced inside of the retrieve callback, after
receiving both the `$id` (if any) and the retrieval URI.
  • Loading branch information
sirosen committed Aug 3, 2023
1 parent b785746 commit 9294f46
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 16 deletions.
10 changes: 5 additions & 5 deletions src/check_jsonschema/schema_loader/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ def _get_schema_reader(self) -> LocalSchemaReader | HttpSchemaReader:
f"detected parsed URL had an unrecognized scheme: {self.url_info}"
)

def get_schema_ref_base(self) -> str | None:
return self.reader.get_ref_base()
def get_schema_retrieval_uri(self) -> str | None:
return self.reader.get_retrieval_uri()

def get_schema(self) -> dict[str, t.Any]:
return self.reader.read_schema()
Expand All @@ -113,7 +113,7 @@ def get_validator(
format_opts: FormatOptions,
fill_defaults: bool,
) -> jsonschema.Validator:
schema_uri = self.get_schema_ref_base()
retrieval_uri = self.get_schema_retrieval_uri()
schema = self.get_schema()

schema_dialect = schema.get("$schema")
Expand All @@ -123,7 +123,7 @@ def get_validator(

# reference resolution
# with support for YAML, TOML, and other formats from the parsers
reference_registry = make_reference_registry(self._parsers, schema_uri, schema)
reference_registry = make_reference_registry(self._parsers, retrieval_uri, schema)

# get the correct validator class and check the schema under its metaschema
validator_cls = jsonschema.validators.validator_for(schema)
Expand All @@ -147,7 +147,7 @@ def __init__(self, schema_name: str) -> None:
self.schema_name = schema_name
self._parsers = ParserSet()

def get_schema_ref_base(self) -> str | None:
def get_schema_retrieval_uri(self) -> str | None:
return None

def get_schema(self) -> dict[str, t.Any]:
Expand Down
4 changes: 2 additions & 2 deletions src/check_jsonschema/schema_loader/readers.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def __init__(self, filename: str) -> None:
self.filename = str(self.path)
self.parsers = ParserSet()

def get_ref_base(self) -> str:
def get_retrieval_uri(self) -> str:
return self.path.as_uri()

def _read_impl(self) -> t.Any:
Expand All @@ -55,7 +55,7 @@ def __init__(
validation_callback=json.loads,
)

def get_ref_base(self) -> str:
def get_retrieval_uri(self) -> str:
return self.url

def _read_impl(self) -> t.Any:
Expand Down
26 changes: 17 additions & 9 deletions src/check_jsonschema/schema_loader/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,46 @@


def make_reference_registry(
parsers: ParserSet, schema_uri: str | None, schema: dict
parsers: ParserSet, retrieval_uri: str | None, schema: dict
) -> referencing.Registry:
id_attribute_: t.Any = schema.get("$id")
if isinstance(id_attribute_, str):
id_attribute: str | None = id_attribute_
else:
id_attribute = None

schema_resource = referencing.Resource.from_contents(
schema, default_specification=DRAFT202012
)
# mypy does not recognize that Registry is an `attrs` class and has `retrieve` as an
# argument to its implicit initializer
registry: referencing.Registry = referencing.Registry( # type: ignore[call-arg]
retrieve=create_retrieve_callable(parsers, schema_uri)
retrieve=create_retrieve_callable(parsers, retrieval_uri, id_attribute)
)

if schema_uri is not None:
registry = registry.with_resource(uri=schema_uri, resource=schema_resource)

id_attribute = schema.get("$id")
if retrieval_uri is not None:
registry = registry.with_resource(uri=retrieval_uri, resource=schema_resource)
if id_attribute is not None:
registry = registry.with_resource(uri=id_attribute, resource=schema_resource)

return registry


def create_retrieve_callable(
parser_set: ParserSet, schema_uri: str | None
parser_set: ParserSet, retrieval_uri: str | None, id_attribute: str | None
) -> t.Callable[[str], referencing.Resource[Schema]]:
base_uri = id_attribute
if base_uri is None:
base_uri = retrieval_uri

def get_local_file(uri: str) -> t.Any:
path = filename2path(uri)
return parser_set.parse_file(path, "json")

def retrieve_reference(uri: str) -> referencing.Resource[Schema]:
scheme = urllib.parse.urlsplit(uri).scheme
if scheme == "" and schema_uri is not None:
full_uri = urllib.parse.urljoin(schema_uri, uri)
if scheme == "" and base_uri is not None:
full_uri = urllib.parse.urljoin(base_uri, uri)
else:
full_uri = uri

Expand Down

0 comments on commit 9294f46

Please sign in to comment.