PyLD 3.0.0__tar.gz → 3.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. {pyld-3.0.0 → pyld-3.2.0}/CHANGELOG.md +92 -1
  2. pyld-3.2.0/MANIFEST.in +2 -0
  3. pyld-3.2.0/PKG-INFO +468 -0
  4. pyld-3.2.0/README.md +424 -0
  5. pyld-3.2.0/README.txt +424 -0
  6. pyld-3.2.0/lib/PyLD.egg-info/PKG-INFO +468 -0
  7. pyld-3.2.0/lib/PyLD.egg-info/SOURCES.txt +45 -0
  8. {pyld-3.0.0 → pyld-3.2.0}/lib/PyLD.egg-info/requires.txt +3 -0
  9. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/__about__.py +1 -1
  10. pyld-3.2.0/lib/pyld/__init__.py +21 -0
  11. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/context_resolver.py +13 -5
  12. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/documentloader/aiohttp.py +32 -20
  13. pyld-3.2.0/lib/pyld/documentloader/base.py +42 -0
  14. pyld-3.2.0/lib/pyld/documentloader/frozen/__init__.py +83 -0
  15. pyld-3.2.0/lib/pyld/documentloader/frozen/bundled/activitystreams.jsonld +379 -0
  16. pyld-3.2.0/lib/pyld/documentloader/frozen/bundled/credentials-v1.jsonld +315 -0
  17. pyld-3.2.0/lib/pyld/documentloader/frozen/bundled/credentials-v2.jsonld +301 -0
  18. pyld-3.2.0/lib/pyld/documentloader/frozen/bundled/did-v1.jsonld +57 -0
  19. pyld-3.2.0/lib/pyld/documentloader/frozen/bundled/security-ed25519-2020-v1.jsonld +93 -0
  20. pyld-3.2.0/lib/pyld/documentloader/frozen/bundled/security-jws-2020-v1.jsonld +78 -0
  21. pyld-3.2.0/lib/pyld/documentloader/frozen/bundled/security-v1.jsonld +74 -0
  22. pyld-3.2.0/lib/pyld/documentloader/frozen/bundled/security-v2.jsonld +126 -0
  23. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/documentloader/requests.py +35 -19
  24. pyld-3.2.0/lib/pyld/documentloader/requests_sqlite_cache.py +55 -0
  25. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/iri_resolver.py +4 -0
  26. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/jsonld.py +513 -250
  27. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/nquads.py +2 -1
  28. pyld-3.2.0/lib/pyld/options.py +193 -0
  29. {pyld-3.0.0 → pyld-3.2.0}/setup.py +8 -2
  30. {pyld-3.0.0 → pyld-3.2.0}/tests/test_document_loader.py +58 -1
  31. pyld-3.2.0/tests/test_frozen_document_loader.py +119 -0
  32. pyld-3.2.0/tests/test_jsonld.py +1588 -0
  33. pyld-3.2.0/tests/test_sqlite_cache_requests_document_loader.py +125 -0
  34. pyld-3.0.0/MANIFEST.in +0 -1
  35. pyld-3.0.0/PKG-INFO +0 -381
  36. pyld-3.0.0/README.rst +0 -339
  37. pyld-3.0.0/README.txt +0 -339
  38. pyld-3.0.0/lib/PyLD.egg-info/PKG-INFO +0 -381
  39. pyld-3.0.0/lib/PyLD.egg-info/SOURCES.txt +0 -32
  40. pyld-3.0.0/lib/pyld/__init__.py +0 -6
  41. pyld-3.0.0/tests/test_jsonld.py +0 -571
  42. pyld-3.0.0/tests/test_nquads.py +0 -231
  43. {pyld-3.0.0 → pyld-3.2.0}/LICENSE +0 -0
  44. {pyld-3.0.0 → pyld-3.2.0}/lib/PyLD.egg-info/dependency_links.txt +0 -0
  45. {pyld-3.0.0 → pyld-3.2.0}/lib/PyLD.egg-info/top_level.txt +0 -0
  46. {pyld-3.0.0 → pyld-3.2.0}/lib/c14n/Canonicalize.py +0 -0
  47. {pyld-3.0.0 → pyld-3.2.0}/lib/c14n/NumberToJson.py +0 -0
  48. {pyld-3.0.0 → pyld-3.2.0}/lib/c14n/__init__.py +0 -0
  49. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/canon.py +0 -0
  50. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/documentloader/__init__.py +0 -0
  51. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/identifier_issuer.py +0 -0
  52. {pyld-3.0.0 → pyld-3.2.0}/lib/pyld/resolved_context.py +0 -0
  53. {pyld-3.0.0 → pyld-3.2.0}/pyproject.toml +0 -0
  54. {pyld-3.0.0 → pyld-3.2.0}/setup.cfg +0 -0
  55. {pyld-3.0.0 → pyld-3.2.0}/tests/test_iri_resolver.py +0 -0
  56. {pyld-3.0.0 → pyld-3.2.0}/tests/test_manifests.py +0 -0
@@ -1,8 +1,99 @@
1
1
  # pyld ChangeLog
2
2
 
3
+ ## 3.2.0 - 2026-08-17
4
+
5
+ ### Added
6
+ - `*Options` TypedDict types and a `Context` type alias in `pyld.options` for JSON-LD API option dicts (typing and documentation).
7
+ - `pyld.SqliteCacheRequestsDocumentLoader`: a SQLite-backed HTTP cache document loader using `requests-cache`.
8
+
9
+ ### Fixed
10
+ - If value objects contain array values for `@type` during expansion, an error is now raised. Fixes [expand#ter54](https://w3c.github.io/json-ld-api/tests/expand-manifest.html#ter54) and [toRdf#ter54](https://w3c.github.io/json-ld-api/tests/toRdf-manifest.html#ter54).
11
+ - Inline contexts that try to redefine @context now raise an error. Fixes [expand#ter56](https://w3c.github.io/json-ld-api/tests/expand-manifest.html#ter56) and [toRdf#ter56](https://w3c.github.io/json-ld-api/tests/toRdf-manifest.html#ter56).
12
+ - When using native types, values of `xsd:boolean` and `xsd:integer` are now properly converted. Fixes [fromRdf#t0027](https://w3c.github.io/json-ld-api/tests/fromRdf-manifest.html#t0027).
13
+ - Numbers with 0 as fractional part now parse to an `xsd:integer` instead of `xsd:double`. Fixes [toRdf#ttn02](https://w3c.github.io/json-ld-api/tests/toRdf-manifest.html#ttn02).
14
+ - Zeros are now truncated for numeric values with negative exponent.
15
+ - Blank node prefixes are now also used in IRI expansion.
16
+ - Numbers with no fractions but that are >= 1e21 are now represented as xsd:double in json-ld-1.1 processing mode.
17
+ - In `RequestsDocumentLoader`, constructor-level headers are now removed from `**kwargs` and stored separately, avoiding duplicate `headers=` when calling `session.get`. Per-call `options["headers"]` still takes precedence.
18
+
19
+ ## 3.1.0 - 2026-06-19
20
+
21
+ ### Fixed
22
+ - When compacting, expands the index mapping first, then compacts that expanded
23
+ IRI, matching the JSON-LD API compaction correction for compact-IRI index
24
+ mappings. Fixes testcases [compact#t0112](https://w3c.github.io/json-ld-api/tests/compact-manifest.html#t0112)
25
+ and [compact#t0113](https://w3c.github.io/json-ld-api/tests/compact-manifest.html#t0113).
26
+ - Fixes `AttributeError` when compacting with `@none`: the `@type` map
27
+ compaction path now only calls `.pop()` and inspects keys when
28
+ `compacted_item` is actually an object. Fixes
29
+ [compact#tm023](https://w3c.github.io/json-ld-api/tests/compact-manifest.html#tm023)
30
+ - An empty property-scoped context no longer resets the active context in
31
+ `_create_term_definition`. Now only explicit null becomes False; empty
32
+ contexts are preserved. Fixes [compact#tc028](https://w3c.github.io/json-ld-api/tests/compact-manifest.html#tc028),
33
+ [toRdf#tc036](https://w3c.github.io/json-ld-api/tests/toRdf-manifest.html#tc036)
34
+ and [expand#tc036](https://w3c.github.io/json-ld-api/tests/expand-manifest.html#tc036).
35
+ - Options from the test manifest now override the options configured in
36
+ `create_test_options()`, instead of the other way around. This fixes
37
+ tests not able to override default options in the test-setup such as
38
+ `extractAllScripts`. Fixes [html#tf004](https://w3c.github.io/json-ld-api/tests/html-manifest#tf004).
39
+ - When `@type` is `@json` in a frame, it no longer raises an "Invalid JSON-LD
40
+ syntax" error. Fixes [frame#t0069](https://w3c.github.io/json-ld-framing/tests/frame-manifest.html#t0069).
41
+ - Use safeguard for non-dict values of `options['link']`
42
+ - Local and type-scoped contexts are now properly resolved for nested node
43
+ objects, so a scoped context on a `@nest` term is being applied to nested
44
+ properties. Fixes [toRdf#tc037](https://w3c.github.io/json-ld-api/tests/toRdf-manifest.html#tc037),
45
+ [toRdf#tc038](https://w3c.github.io/json-ld-api/tests/toRdf-manifest.html#tc038),
46
+ [expand#tc037](https://w3c.github.io/json-ld-api/tests/expand-manifest.html#tc037)
47
+ and [expand#tc038](https://w3c.github.io/json-ld-api/tests/expand-manifest.html#tc038).
48
+
49
+ ### Changed
50
+ - `requests_document_loader()` and `aiohttp_document_loader()` now return
51
+ class-based `DocumentLoader` instances while preserving the existing
52
+ callable factory API. The concrete `RequestsDocumentLoader` and
53
+ `AioHttpDocumentLoader` classes are also importable from `pyld`.
54
+ - The `pytest` test runner now uses plain assert result == expect instead
55
+ of printing EXPECTED / ACTUAL and raising a generic failure. This enables
56
+ `pytests`'s native result comparison.
57
+ - Convert `./README.rst` and `./CONTRIBUTING.rst` (reStructuredText) to
58
+ `./README.md` and `./CONTRIBUTING.md` (markdown). Also update their
59
+ contents to reflect the current state of the repo.
60
+ - Replace the old Sphinx documentation with a MkDocs Material site and add a
61
+ GitHub Pages documentation workflow.
62
+
63
+ ### Added
64
+ - `pyld.DocumentLoader` abstract base class for class-based document loaders,
65
+ with a `RemoteDocument` `TypedDict` describing the expected return shape.
66
+ - `pyld.FrozenDocumentLoader`: a class-based loader that serves only URLs in
67
+ its `documents` allowlist and refuses everything else with
68
+ `JsonLdError(code='loading document failed')`. Instantiating with no
69
+ arguments serves the curated `pyld.BUNDLED_CONTEXTS` set; instantiating
70
+ with `dict(BUNDLED_CONTEXTS, **extras)` extends the bundle. Suitable for
71
+ air-gapped, reproducible-build, and security-hardened deployments.
72
+ - `pyld.BUNDLED_CONTEXTS`: curated mapping of high-traffic public W3C / W3ID
73
+ JSON-LD contexts (ActivityStreams, DID v1, VC v1/v2, Linked Data Security
74
+ v1/v2, Ed25519-2020, JWS-2020) to vendored on-disk copies. Refresh with
75
+ `make download-bundled-contexts`.
76
+ - `pyld.ContextResolver`: added the `max_context_urls` property that
77
+ determines maximum number of times contexts can be recusively fetched,
78
+ which replaces the role of the static `MAX_CONTEXT_URLS`. The constructor
79
+ now accepts a `max_context_urls` parameter that sets the value of
80
+ `max_context_urls` which defaults to `MAX_CONTEXT_URLS`.
81
+ - `pyld.fromRdf()` and `pyld.toRdf()` now support compound literals when
82
+ serializing/deserializing RDF to/from JSON-LD. Therefore, both methods accept
83
+ the value `'compound-literal'` for the `'rdfDirection'` option. Fixes
84
+ [fromRdf#tdi11](https://w3c.github.io/json-ld-api/tests/fromRdf-manifest.html#tdi11),
85
+ [fromRdf#tdi12](https://w3c.github.io/json-ld-api/tests/fromRdf-manifest.html#tdi12),
86
+ [toRdf#tdi11](https://w3c.github.io/json-ld-api/tests/toRdf-manifest.html#tdi11), and
87
+ [toRdf#tdi12](https://w3c.github.io/json-ld-api/tests/toRdf-manifest.html#tdi12).
88
+
3
89
  ## 3.0.0 - 2026-04-02
4
90
 
5
91
  ### Changed
92
+ - **BREAKING**: Compaction term selection now follows the JSON-LD 1.1 spec
93
+ (Inverse Context Creation, section 4.3 step 3): terms are ordered by
94
+ shortest first, with lexicographic tiebreak. Previously terms were ordered
95
+ lexicographically first, then by length. This changes which term is
96
+ selected when multiple context keys map to the same IRI. See #247.
6
97
  - **BREAKING**: Require supported Python version >= 3.10.
7
98
  - Update aiohttp document loader to work with Python 3.14.
8
99
  - Minimize async related changes to library code in this release.
@@ -216,7 +307,7 @@
216
307
  - **1.0.0**!
217
308
  - [Semantic Versioning](https://semver.org/) is now past the "initial
218
309
  development" 0.x.y stage (after 6+ years!).
219
- - [Conformance](README.rst#conformance):
310
+ - [Conformance](README.md#conformance):
220
311
  - JSON-LD 1.0 + JSON-LD 1.0 errata
221
312
  - JSON-LD 1.1 drafts
222
313
  - Thanks to the JSON-LD and related communities and the many many people over
pyld-3.2.0/MANIFEST.in ADDED
@@ -0,0 +1,2 @@
1
+ include README.md README.txt LICENSE CHANGELOG.md
2
+ recursive-include lib/pyld/documentloader/frozen/bundled *.jsonld
pyld-3.2.0/PKG-INFO ADDED
@@ -0,0 +1,468 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyLD
3
+ Version: 3.2.0
4
+ Summary: Python implementation of the JSON-LD API
5
+ Home-page: https://github.com/digitalbazaar/pyld
6
+ Author: Digital Bazaar
7
+ Author-email: support@digitalbazaar.com
8
+ License: BSD 3-Clause license
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Environment :: Web Environment
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: BSD License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Topic :: Internet
17
+ Classifier: Topic :: Software Development :: Libraries
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: cachetools
21
+ Requires-Dist: frozendict
22
+ Requires-Dist: lxml
23
+ Provides-Extra: requests
24
+ Requires-Dist: requests; extra == "requests"
25
+ Provides-Extra: aiohttp
26
+ Requires-Dist: aiohttp; extra == "aiohttp"
27
+ Provides-Extra: requests-cache
28
+ Requires-Dist: requests-cache>=1.3; extra == "requests-cache"
29
+ Provides-Extra: cachetools
30
+ Requires-Dist: cachetools; extra == "cachetools"
31
+ Provides-Extra: frozendict
32
+ Requires-Dist: frozendict; extra == "frozendict"
33
+ Dynamic: author
34
+ Dynamic: author-email
35
+ Dynamic: classifier
36
+ Dynamic: description
37
+ Dynamic: description-content-type
38
+ Dynamic: home-page
39
+ Dynamic: license
40
+ Dynamic: license-file
41
+ Dynamic: provides-extra
42
+ Dynamic: requires-dist
43
+ Dynamic: summary
44
+
45
+ # PyLD: A Python JSON-LD Processor
46
+
47
+ [Documentation](https://digitalbazaar.github.io/pyld/) |
48
+ [Installation](#installation) | [Usage](#usage) | [Advanced
49
+ Topics](#advanced-topics) | [Contributing](./CONTRIBUTING.md) |
50
+ [Changelog](./CHANGELOG.md)
51
+
52
+ ## Introduction
53
+
54
+ This library is an implementation of the JSON-LD specification in
55
+ [Python](https://www.python.org/).
56
+
57
+ JSON, as specified in [RFC7159](http://tools.ietf.org/html/rfc7159), is a simple
58
+ language for representing objects on the Web. Linked Data is a way of describing
59
+ content across different documents or Web sites. Web resources are described
60
+ using IRIs, and typically are dereferencable entities that may be used to find
61
+ more information, creating a "Web of Knowledge". [JSON-LD](https://json-ld.org/)
62
+ is intended to be a simple publishing method for expressing not only Linked Data
63
+ in JSON, but for adding semantics to existing JSON.
64
+
65
+ JSON-LD is designed as a light-weight syntax that can be used to express Linked
66
+ Data. It is primarily intended to be a way to express Linked Data in JavaScript
67
+ and other Web-based programming environments. It is also useful when building
68
+ interoperable Web Services and when storing Linked Data in JSON-based document
69
+ storage engines. It is practical and designed to be as simple as possible,
70
+ utilizing the large number of JSON parsers and existing code that is in use
71
+ today. It is designed to be able to express key-value pairs, RDF data,
72
+ [RDFa](http://www.w3.org/TR/rdfa-core/) data,
73
+ [Microformats](http://microformats.org/) data, and
74
+ [Microdata](http://www.w3.org/TR/microdata/). That is, it supports every major
75
+ Web-based structured data model in use today.
76
+
77
+ The syntax does not require many applications to change their JSON, but easily
78
+ add meaning by adding context in a way that is either in-band or out-of-band.
79
+ The syntax is designed to not disturb already deployed systems running on JSON,
80
+ but provide a smooth migration path from JSON to JSON with added semantics.
81
+ Finally, the format is intended to be fast to parse, fast to generate,
82
+ stream-based and document-based processing compatible, and require a very small
83
+ memory footprint in order to operate.
84
+
85
+ ## Requirements
86
+
87
+ * Python (3.10 or later)
88
+ * [Requests](http://docs.python-requests.org/) (optional)
89
+ * [aiohttp](https://aiohttp.readthedocs.io/) (optional)
90
+
91
+ ## Installation
92
+
93
+ PyLD can be installed with a [pip](http://www.pip-installer.org/)
94
+ [package](https://pypi.org/project/PyLD/):
95
+
96
+ ```bash
97
+ pip install PyLD
98
+ ```
99
+
100
+ Defining a dependency on pyld will not pull in
101
+ [Requests](http://docs.python-requests.org/) or
102
+ [aiohttp](https://aiohttp.readthedocs.io/). If you need one of these for a
103
+ [Document Loader](#document-loader) then either depend on the desired external library directly
104
+ or define the requirement as `PyLD[requests]` or `PyLD[aiohttp]`.
105
+
106
+ ## Usage
107
+
108
+ Here are some quick examples to get started:
109
+
110
+ ```python
111
+ from pyld import jsonld
112
+ import json
113
+
114
+ doc = {
115
+ "http://schema.org/name": "Manu Sporny",
116
+ "http://schema.org/url": {"@id": "http://manu.sporny.org/"},
117
+ "http://schema.org/image": {"@id": "http://manu.sporny.org/images/manu.png"}
118
+ }
119
+
120
+ context = {
121
+ "name": "http://schema.org/name",
122
+ "homepage": {"@id": "http://schema.org/url", "@type": "@id"},
123
+ "image": {"@id": "http://schema.org/image", "@type": "@id"}
124
+ }
125
+
126
+ # compact a document according to a particular context
127
+ # see: https://json-ld.org/spec/latest/json-ld/#compacted-document-form
128
+ compacted = jsonld.compact(doc, context)
129
+
130
+ print(json.dumps(compacted, indent=2))
131
+ # Output:
132
+ # {
133
+ # "@context": {...},
134
+ # "image": "http://manu.sporny.org/images/manu.png",
135
+ # "homepage": "http://manu.sporny.org/",
136
+ # "name": "Manu Sporny"
137
+ # }
138
+
139
+ # compact using URLs
140
+ jsonld.compact('http://example.org/doc', 'http://example.org/context')
141
+
142
+ # expand a document, removing its context
143
+ # see: https://json-ld.org/spec/latest/json-ld/#expanded-document-form
144
+ expanded = jsonld.expand(compacted)
145
+
146
+ print(json.dumps(expanded, indent=2))
147
+ # Output:
148
+ # [{
149
+ # "http://schema.org/image": [{"@id": "http://manu.sporny.org/images/manu.png"}],
150
+ # "http://schema.org/name": [{"@value": "Manu Sporny"}],
151
+ # "http://schema.org/url": [{"@id": "http://manu.sporny.org/"}]
152
+ # }]
153
+
154
+ # expand using URLs
155
+ jsonld.expand('http://example.org/doc')
156
+
157
+ # flatten a document
158
+ # see: https://json-ld.org/spec/latest/json-ld/#flattened-document-form
159
+ flattened = jsonld.flatten(doc)
160
+ # all deep-level trees flattened to the top-level
161
+
162
+ # frame a document
163
+ # see: https://json-ld.org/spec/latest/json-ld-framing/#introduction
164
+ framed = jsonld.frame(doc, frame)
165
+ # document transformed into a particular tree structure per the given frame
166
+
167
+ # normalize a document using the RDF Dataset Normalization Algorithm
168
+ # (URDNA2015), see: https://www.w3.org/TR/rdf-canon/
169
+ normalized = jsonld.normalize(
170
+ doc, {'algorithm': 'URDNA2015', 'format': 'application/n-quads'})
171
+ # normalized is a string that is a canonical representation of the document
172
+ # that can be used for hashing, comparison, etc.
173
+ ```
174
+
175
+ ## Features & conformance
176
+
177
+ This library aims to conform with the following W3C Recommendations:
178
+
179
+ | Standard | Status |
180
+ | :--- | :--- |
181
+ | [JSON-LD 1.1](https://www.w3.org/TR/json-ld11/) | W3C Recommendation |
182
+ | [JSON-LD 1.1 Processing Algorithms and API](https://www.w3.org/TR/json-ld11-api/) | W3C Recommendation |
183
+ | [JSON-LD 1.1 Framing](https://www.w3.org/TR/json-ld11-framing/) | W3C Recommendation |
184
+ | [RDF Dataset Canonicalization](https://www.w3.org/TR/rdf-canon/) | W3C Recommendation |
185
+
186
+
187
+ The [`test
188
+ runner`](https://github.com/digitalbazaar/pyld/blob/master/tests/runtests.py) is
189
+ often updated to note or skip newer tests that are not yet supported.
190
+
191
+ ## Advanced Topics
192
+
193
+ ### Document Loader
194
+
195
+ The default document loader for PyLD uses
196
+ [Requests](http://docs.python-requests.org/). In a production environment you
197
+ may want to setup a custom loader that, at a minimum, sets a timeout value. You
198
+ can also force requests to use https, set client certs, disable verification, or
199
+ set other Requests parameters.
200
+
201
+ ```python
202
+ jsonld.set_document_loader(jsonld.requests_document_loader(timeout=...))
203
+ ```
204
+
205
+ The factory remains the compatibility API, and the concrete class is also
206
+ available when class-based construction is preferred:
207
+
208
+ ```python
209
+ from pyld import RequestsDocumentLoader
210
+
211
+ jsonld.set_document_loader(RequestsDocumentLoader(timeout=...))
212
+ ```
213
+
214
+ An asynchronous document loader using aiohttp is also available. Please note
215
+ that this document loader limits asynchronicity to fetching documents only. The
216
+ processing loops remain synchronous.
217
+
218
+ ```python
219
+ jsonld.set_document_loader(jsonld.aiohttp_document_loader(timeout=...))
220
+ ```
221
+
222
+ The concrete aiohttp loader class is available from `pyld` as well:
223
+
224
+ ```python
225
+ from pyld import AioHttpDocumentLoader
226
+
227
+ jsonld.set_document_loader(AioHttpDocumentLoader(timeout=...))
228
+ ```
229
+
230
+ When no document loader is specified, the default loader is set to
231
+ [Requests](http://docs.python-requests.org/). If Requests is not available, the
232
+ loader is set to aiohttp. The fallback document loader is a dummy document
233
+ loader that raises an exception on every invocation.
234
+
235
+ ### Frozen Document Loader
236
+
237
+ For air-gapped runs, reproducible builds, and security-hardened deployments that
238
+ must not perform any remote context fetches at all, PyLD ships
239
+ `FrozenDocumentLoader`: a class-based loader that serves only the URLs in its
240
+ `documents` allowlist and refuses everything else with
241
+ `JsonLdError(code='loading document failed')`.
242
+
243
+ Instantiating with no arguments serves the curated `BUNDLED_CONTEXTS` set
244
+ (ActivityStreams, DID v1, Verifiable Credentials v1 and v2, Linked Data Security
245
+ v1/v2, Ed25519-2020, and JWS-2020). To extend the bundle with additional
246
+ pre-vetted contexts, pass a merged mapping:
247
+
248
+ ```python
249
+ from pyld import jsonld, FrozenDocumentLoader, BUNDLED_CONTEXTS
250
+
251
+ loader = FrozenDocumentLoader(documents=dict(
252
+ BUNDLED_CONTEXTS,
253
+ **{'https://example.com/my-ctx': Path('contexts/my-ctx.jsonld')},
254
+ ))
255
+ jsonld.expand(doc, options={'documentLoader': loader})
256
+ ```
257
+
258
+ This honors the W3C *JSON-LD Best Practices* recommendation that clients SHOULD
259
+ attempt to use a locally cached version of contexts (see
260
+ [§ Cache JSON-LD Contexts](https://w3c.github.io/json-ld-bp/#cache-json-ld-contexts)).
261
+ Refresh the bundled copies with `make download-bundled-contexts`.
262
+
263
+ ### Customizing the ContextResolver
264
+
265
+ You can customize the way contexts are loaded and cached by passing an instance
266
+ of `ContextResolver`. The following example implements a loader with a prefilled
267
+ custom document cache and uses a custom LRU cache for resolved contexts:
268
+
269
+ ```python
270
+ from pyld.jsonld import compact, expand, set_document_loader, ContextResolver
271
+ import json
272
+ from cachetools import LRUCache
273
+
274
+ # Load the Linked Art context from file-system
275
+ fh = open('linked-art.json')
276
+ js = json.load(fh)
277
+ fh.close()
278
+
279
+ # Add to document cache
280
+ docCache = {
281
+ "https://linked.art/ns/v1/linked-art.json": {
282
+ "contextUrl": None,
283
+ "documentUrl": "https://linked.art/ns/v1/linked-art.json",
284
+ "document": js
285
+ }
286
+ }
287
+
288
+ # Custom loader that uses the document cache
289
+ def load_document_and_cache(url, options={}):
290
+ if url in docCache:
291
+ return docCache[url]
292
+ doc = {"contextUrl": None, "documentUrl": url, "document": ""}
293
+ resp = requests.get(url)
294
+ doc["document"] = resp.json()
295
+ docCache[url] = doc
296
+ return doc
297
+
298
+ # Set the custom loader as global document loader
299
+ set_document_loader(load_document_and_cache)
300
+ # Create custom context resolver with custom LRU cache and custom loader
301
+ resolved_context_cache = LRUCache(maxsize=1000)
302
+ resolver = ContextResolver(resolved_context_cache, load_document_and_cache)
303
+
304
+ # Expand JSON-LD document using custom context resolver
305
+ input = {"@context":"https://linked.art/ns/v1/linked-art.json", "id": "tag:foo", "type": "Person"}
306
+ output = expand(input, options={'contextResolver': resolver})
307
+ ```
308
+
309
+ It is also possible to change the maximum number of times that the loader
310
+ recursively fetches contexts, by passing the `max_context_urls` parameter:
311
+
312
+ ```python
313
+ resolver = ContextResolver(resolved_context_cache, load_document_and_cache, max_context_urls=20)
314
+ # Or you can do...
315
+ # resolver = ContextResolver(resolved_context_cache, load_document_and_cache)
316
+ # resolver.max_context_urls = 20
317
+ output = expand(input, options={'contextResolver': resolver})
318
+ ```
319
+
320
+ ### Handling ignored properties during JSON-LD expansion
321
+
322
+ If a property in a JSON-LD document does not map to an absolute IRI then it is
323
+ ignored. You can customize this behaviour by passing a customizable handler to
324
+ `on_property_dropped` parameter of `jsonld.expand()`.
325
+
326
+ For example, you can introduce a strict mode by raising a ValueError on every
327
+ dropped property:
328
+
329
+ ```python
330
+ def raise_this(value):
331
+ raise ValueError(value)
332
+
333
+ jsonld.expand(doc, None, on_property_dropped=raise_this)
334
+ ```
335
+
336
+ ## Contributing
337
+
338
+ Want to contribute to PyLD? Great! Please consult [`CONTRIBUTING.md`](./CONTRIBUTING.md) for some guidelines.
339
+
340
+ ### Building the source
341
+
342
+ The source code for the Python implementation of the JSON-LD API is available
343
+ at:
344
+
345
+ [https://github.com/digitalbazaar/pyld](https://github.com/digitalbazaar/pyld)
346
+
347
+ You can install the source using `make`:
348
+
349
+ ```
350
+ pip install -r requirements.txt requirements-test.txt
351
+ make install
352
+ ```
353
+
354
+ ### Testing
355
+
356
+ This library includes a sample testing utility which may be used to verify that
357
+ changes to the processor maintain the correct output.
358
+
359
+ To run the sample tests you will need to get the test suite files, which by
360
+ default, are stored in the `specifications/` folder. The test suites can be
361
+ obtained by either using git submodules or by cloning them manually.
362
+
363
+ #### Using git submodules
364
+
365
+ The test suites are included as git submodules to ensure versions are in sync.
366
+ When cloning the repository, use the `--recurse-submodules` flag to
367
+ automatically clone the submodules. If you have cloned the repository without
368
+ the submodules, you can initialize them with the following commands:
369
+
370
+ ```bash
371
+ git submodule init
372
+ git submodule update
373
+ ```
374
+
375
+ #### Cloning manually
376
+
377
+ You can also avoid using git submodules by manually cloning the `json-ld-api`,
378
+ `json-ld-framing`, and `normalization` repositories hosted on GitHub using the
379
+ following commands:
380
+
381
+ ```bash
382
+ git clone https://github.com/w3c/json-ld-api ./specifications/json-ld-api
383
+ git clone https://github.com/w3c/json-ld-framing ./specifications/json-ld-framing
384
+ git clone https://github.com/json-ld/normalization ./specifications/normalization
385
+ ```
386
+
387
+ Note that you can clone these repositories into any location you wish; however,
388
+ if you do not clone them into the default `specifications/` folder, you will
389
+ need to provide the paths to the test runner as arguments when running the
390
+ tests, as explained below.
391
+
392
+ #### Running the sample test suites and unit tests using pytest
393
+
394
+ If the suites repositories are available in the `specifications/` folder of the
395
+ PyLD source directory, then all unittests, including the sample test suites, can
396
+ be run with `pytest`:
397
+
398
+ ```bash
399
+ pytest
400
+ ```
401
+
402
+ If you wish to store the test suites in a different location than the default
403
+ `specifications/` folder, or you want to test individual manifest `.jsonld`
404
+ files or directories containing a `manifest.jsonld`, then you can supply these
405
+ files or directories as arguments:
406
+
407
+ ```bash
408
+ # use: pytest --tests=TEST_PATH [--tests=TEST_PATH...]
409
+ pytest --tests=./specifications/json-ld-api/tests
410
+ ```
411
+
412
+ The test runner supports different document loaders by setting `--loader
413
+ requests` or `--loader aiohttp`. The default document loader is set to
414
+ [Requests](http://docs.python-requests.org/).
415
+
416
+ ```bash
417
+ pytest --loader=requests --tests=./specifications/json-ld-api/tests
418
+ ```
419
+
420
+ An EARL report can be generated using the `--earl` option.
421
+
422
+ ```bash
423
+ pytest --earl=./earl-report.json
424
+ ```
425
+
426
+ #### Running the sample test suites using the original test runner
427
+
428
+ You can also run the JSON-LD test suites using the original test runner script
429
+ provided:
430
+
431
+ ```bash
432
+ python tests/runtests.py
433
+ ```
434
+
435
+ If you wish to store the test suites in a different location than the default
436
+ `specifications/` folder, or you want to test individual manifest `.jsonld`
437
+ files or directories containing a `manifest.jsonld`, then you can supply these
438
+ files or directories as arguments:
439
+
440
+ ```bash
441
+ python tests/runtests.py TEST_PATH [TEST_PATH...]
442
+ ```
443
+
444
+ The test runner supports different document loaders by setting `-l requests` or
445
+ `-l aiohttp`. The default document loader is set to
446
+ [Requests](http://docs.python-requests.org/).
447
+
448
+ ```bash
449
+ python tests/runtests.py -l requests ./specifications/json-ld-api/tests
450
+ ```
451
+
452
+ An EARL report can be generated using the `-e` or `--earl` option.
453
+
454
+ ```bash
455
+ python tests/runtests.py -e ./earl-report.json
456
+ ```
457
+
458
+ ## License
459
+
460
+ BSD-3-Clause license
461
+ See [`LICENSE`](./LICENSE) file for details.
462
+
463
+ ## Maintainers
464
+
465
+ The PyLD library is maintained by [Miel Vander
466
+ Sande](https://github.com/mielvds), [Anatoly
467
+ Scherbakov](https://github.com/anatoly-scherbakov) and [Digital
468
+ Bazaar](https://github.com/digitalbazaar) (Original authors of `PyLD`).