-
Notifications
You must be signed in to change notification settings - Fork 137
Add FrozenDocumentLoader for offline / vetted JSON-LD contexts #250
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
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
6d202c5
Add `DocumentLoader` ABC and `RemoteDocument` `TypedDict`
anatoly-scherbakov 166d527
Add `FrozenDocumentLoader` and `BUNDLED_CONTEXTS`
anatoly-scherbakov 8bcc516
Vendor `https://www.w3.org/ns/activitystreams` context
anatoly-scherbakov a56be1f
Vendor `https://www.w3.org/ns/did/v1` context
anatoly-scherbakov 4d278b0
Vendor `https://www.w3.org/2018/credentials/v1` context
anatoly-scherbakov ea8c083
Vendor `https://www.w3.org/ns/credentials/v2` context
anatoly-scherbakov fcd3889
Vendor `https://w3id.org/security/v1` context
anatoly-scherbakov d491d0e
Vendor `https://w3id.org/security/v2` context
anatoly-scherbakov de4e3ae
Vendor `https://w3id.org/security/suites/ed25519-2020/v1` context
anatoly-scherbakov 6d70d58
Vendor `https://w3id.org/security/suites/jws-2020/v1` context
anatoly-scherbakov 646dc13
Add `scripts/download_contexts.py` to refresh bundled contexts
anatoly-scherbakov dd782e1
Add `download-bundled-contexts` Makefile target
anatoly-scherbakov f5c543f
Add tests for `FrozenDocumentLoader` and `BUNDLED_CONTEXTS`
anatoly-scherbakov 694ab5b
Re-export `DocumentLoader`, `FrozenDocumentLoader`, `BUNDLED_CONTEXTS…
anatoly-scherbakov 5416db4
Ship bundled `*.jsonld` contexts in `pyld.documentloader.frozen` package
anatoly-scherbakov eb84a1d
Include bundled `*.jsonld` contexts in source distributions
anatoly-scherbakov 128b404
Document `FrozenDocumentLoader` and `BUNDLED_CONTEXTS` in README
anatoly-scherbakov 5b9aae9
Add Sphinx autoclass entries for `DocumentLoader` and `FrozenDocument…
anatoly-scherbakov a99447f
Note `FrozenDocumentLoader` and `BUNDLED_CONTEXTS` in 3.1.0 changelog
anatoly-scherbakov 005e0f8
Replace FrozenDocumentLoader dataclass initialization
anatoly-scherbakov ffc27a7
Add FrozenDocumentLoader test docstrings
anatoly-scherbakov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| include README.rst README.txt LICENSE CHANGELOG.md | ||
| recursive-include lib/pyld/documentloader/frozen/bundled *.jsonld |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| """ | ||
| Abstract base class for class-based JSON-LD document loaders. | ||
|
|
||
| .. module:: jsonld.documentloader.base | ||
| :synopsis: DocumentLoader abstract base class | ||
| """ | ||
|
|
||
| from abc import ABC, abstractmethod | ||
| from typing import Any, TypedDict | ||
|
|
||
|
|
||
| class RemoteDocument(TypedDict): | ||
| """Shape returned by a JSON-LD document loader. | ||
|
|
||
| Mirrors the *RemoteDocument* structure defined in the W3C JSON-LD 1.1 API | ||
| (https://www.w3.org/TR/json-ld11-api/#remotedocument). | ||
| """ | ||
|
|
||
| contentType: str | ||
| contextUrl: str | None | ||
| documentUrl: str | ||
| document: Any | ||
|
|
||
|
|
||
| class DocumentLoader(ABC): | ||
| """Abstract base class for class-based JSON-LD document loaders. | ||
|
|
||
| Concrete subclasses implement :meth:`__call__` to fetch a document for a | ||
| given URL and return a :class:`RemoteDocument`. | ||
|
|
||
| Existing function-based loaders (:func:`pyld.jsonld.requests_document_loader`, | ||
| :func:`pyld.jsonld.aiohttp_document_loader`) remain valid: pyld's loader | ||
| contract is "any callable with the right signature". This ABC is for new | ||
| class-based loaders only. | ||
| """ | ||
|
|
||
| @abstractmethod | ||
| def __call__(self, url: str, options: dict) -> RemoteDocument: | ||
| """Retrieve the JSON-LD document at ``url``. | ||
|
|
||
| :param url: the URL to retrieve. | ||
| :param options: loader options (e.g. ``headers``). | ||
| :return: a :class:`RemoteDocument`. | ||
| """ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| """ | ||
| Frozen JSON-LD document loader. | ||
|
|
||
| A document loader that serves *only* the URLs in its ``documents`` allowlist | ||
| and refuses everything else with :class:`pyld.jsonld.JsonLdError`. Suitable for | ||
| secure / air-gapped / privacy-sensitive deployments and for honoring the | ||
| guidance in the W3C *JSON-LD Best Practices* note that clients SHOULD attempt | ||
| to use a locally cached version of contexts (§ Cache JSON-LD Contexts, | ||
| https://w3c.github.io/json-ld-bp/#cache-json-ld-contexts). | ||
|
|
||
| This module also defines :data:`BUNDLED_CONTEXTS`, a curated mapping of | ||
| high-traffic public W3C / W3ID JSON-LD context URLs to vendored on-disk copies | ||
| shipped with the package. See ``scripts/download_contexts.py`` for how the | ||
| files in ``bundled/`` are refreshed. | ||
|
|
||
| .. module:: jsonld.documentloader.frozen | ||
| :synopsis: FrozenDocumentLoader and BUNDLED_CONTEXTS | ||
| """ | ||
|
|
||
| import json | ||
| from collections.abc import Mapping | ||
| from pathlib import Path | ||
|
|
||
| from pyld.documentloader.base import DocumentLoader, RemoteDocument | ||
| from pyld.jsonld import JsonLdError | ||
|
|
||
| _BUNDLED_DIR = Path(__file__).parent / 'bundled' | ||
|
|
||
|
|
||
| BUNDLED_CONTEXTS: Mapping[str, Path] = { | ||
| 'https://www.w3.org/ns/activitystreams': _BUNDLED_DIR / 'activitystreams.jsonld', | ||
| 'https://www.w3.org/ns/did/v1': _BUNDLED_DIR / 'did-v1.jsonld', | ||
| 'https://www.w3.org/2018/credentials/v1': _BUNDLED_DIR / 'credentials-v1.jsonld', | ||
| 'https://www.w3.org/ns/credentials/v2': _BUNDLED_DIR / 'credentials-v2.jsonld', | ||
| 'https://w3id.org/security/v1': _BUNDLED_DIR / 'security-v1.jsonld', | ||
| 'https://w3id.org/security/v2': _BUNDLED_DIR / 'security-v2.jsonld', | ||
| 'https://w3id.org/security/suites/ed25519-2020/v1': _BUNDLED_DIR | ||
| / 'security-ed25519-2020-v1.jsonld', | ||
| 'https://w3id.org/security/suites/jws-2020/v1': _BUNDLED_DIR | ||
| / 'security-jws-2020-v1.jsonld', | ||
| } | ||
|
|
||
|
|
||
| class FrozenDocumentLoader(DocumentLoader): | ||
| """Document loader that serves only a sealed allowlist of URLs. | ||
|
|
||
| ``documents`` maps each allowed URL to either a parsed JSON-LD ``dict`` or | ||
| a :class:`pathlib.Path` pointing to a JSON file on disk. Path entries are | ||
| read and parsed lazily on first request, then cached in place so subsequent | ||
| calls skip the file read. Any URL not present in the mapping raises | ||
| :class:`pyld.jsonld.JsonLdError` with code ``'loading document failed'``. | ||
|
|
||
| With no arguments, a ``FrozenDocumentLoader`` serves the curated | ||
| :data:`BUNDLED_CONTEXTS` set. To extend rather than replace the bundle:: | ||
|
|
||
| FrozenDocumentLoader(documents=dict(BUNDLED_CONTEXTS, **extras)) | ||
| """ | ||
|
|
||
| def __init__(self, documents: Mapping[str, dict | Path] | None = None) -> None: | ||
| # Take ownership of the mapping so we can cache parsed Paths in place | ||
| # without mutating the caller's dict. | ||
| if documents is None: | ||
| documents = BUNDLED_CONTEXTS | ||
| self.documents = dict(documents) | ||
|
|
||
| def __call__(self, url: str, options: dict) -> RemoteDocument: | ||
| if url not in self.documents: | ||
| raise JsonLdError( | ||
| 'Refusing to load document outside the allowed set.', | ||
| 'jsonld.LoadDocumentError', | ||
| {'url': url}, | ||
| code='loading document failed', | ||
| ) | ||
| value: dict | Path = self.documents[url] | ||
| if isinstance(value, Path): | ||
| value = json.loads(value.read_text(encoding='utf-8')) | ||
| self.documents[url] = value | ||
| return { | ||
| 'contentType': 'application/ld+json', | ||
| 'contextUrl': None, | ||
| 'documentUrl': url, | ||
| 'document': value, | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.