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