Skip to content

Commit 3d49748

Browse files
committed
Fix schema readers to cache data
The previous implementation tried to repeatedly read data for a schema input, even across multiple instances. As a result, if the schema source was ephemeral (e.g. a memfd), the subsequent reads would fail.
1 parent b02f492 commit 3d49748

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

src/check_jsonschema/schema_loader/readers.py

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@
1515
yaml = ruamel.yaml.YAML(typ="safe")
1616

1717

18+
class _UnsetType:
19+
pass
20+
21+
22+
_UNSET = _UnsetType()
23+
24+
1825
def _run_load_callback(schema_location: str, callback: t.Callable) -> dict:
1926
try:
2027
schema = callback()
@@ -31,6 +38,7 @@ def __init__(self, filename: str) -> None:
3138
self.path = filename2path(filename)
3239
self.filename = str(self.path)
3340
self.parsers = ParserSet()
41+
self._parsed_schema: dict | _UnsetType = _UNSET
3442

3543
def get_retrieval_uri(self) -> str | None:
3644
return self.path.as_uri()
@@ -39,21 +47,26 @@ def _read_impl(self) -> t.Any:
3947
return self.parsers.parse_file(self.path, default_filetype="json")
4048

4149
def read_schema(self) -> dict:
42-
return _run_load_callback(self.filename, self._read_impl)
50+
if self._parsed_schema is _UNSET:
51+
self._parsed_schema = _run_load_callback(self.filename, self._read_impl)
52+
return self._parsed_schema
4353

4454

4555
class StdinSchemaReader:
4656
def __init__(self) -> None:
4757
self.parsers = ParserSet()
58+
self._parsed_schema: dict | _UnsetType = _UNSET
4859

4960
def get_retrieval_uri(self) -> str | None:
5061
return None
5162

5263
def read_schema(self) -> dict:
53-
try:
54-
return json.load(sys.stdin)
55-
except ValueError as e:
56-
raise ParseError("Failed to parse JSON from stdin") from e
64+
if self._parsed_schema is _UNSET:
65+
try:
66+
self._parsed_schema = json.load(sys.stdin)
67+
except ValueError as e:
68+
raise ParseError("Failed to parse JSON from stdin") from e
69+
return self._parsed_schema
5770

5871

5972
class HttpSchemaReader:
@@ -71,14 +84,12 @@ def __init__(
7184
disable_cache=disable_cache,
7285
validation_callback=self._parse,
7386
)
74-
self._parsed_schema: t.Any | None = None
87+
self._parsed_schema: dict | _UnsetType = _UNSET
7588

7689
def _parse(self, schema_bytes: bytes) -> t.Any:
77-
if self._parsed_schema is None:
78-
self._parsed_schema = self.parsers.parse_data_with_path(
79-
io.BytesIO(schema_bytes), self.url, default_filetype="json"
80-
)
81-
return self._parsed_schema
90+
return self.parsers.parse_data_with_path(
91+
io.BytesIO(schema_bytes), self.url, default_filetype="json"
92+
)
8293

8394
def get_retrieval_uri(self) -> str | None:
8495
return self.url
@@ -88,4 +99,6 @@ def _read_impl(self) -> t.Any:
8899
return self._parse(fp.read())
89100

90101
def read_schema(self) -> dict:
91-
return _run_load_callback(self.url, self._read_impl)
102+
if self._parsed_schema is _UNSET:
103+
self._parsed_schema = _run_load_callback(self.url, self._read_impl)
104+
return self._parsed_schema

0 commit comments

Comments
 (0)