- Migrate
canon.pytordflib- Added
rdflibdependency in all relevant config and code files. - Added
util.py:- Added the functions
from_legacy_dataset()andto_legacy_dataset()to convert anrdflib.Datasetto an RDFJS-likedictand back wherever needed. - Added unittests in
tests/test_util.pyfor these functions.
- Added the functions
- Added
- Implement RDFC1.0
- Added new class
RDFC10(subclass ofURDNA2015) incanon.py - Added the RDFC1.0 test-suite in
tests/runtests.py- Added support for testing blank-node identifier maps.
- Added support for testing with different hashing algorithms
- Added new class
- BREAKING: Removed the internal
pyld.nquadsparser/serializer module.
- Preserved RDF literal lexical forms when converting through RDFLib, including canonical double output, large numeric values, and compound literal handling.
- Fixed
iri_resolver.unresolve()query/fragment reconstruction while cleaning up the resolver docstring.
- BREAKING: Migrated
jsonld.to_rdf(),jsonld.from_rdf(), and N-Quads parsing/serialization to userdflib.Datasetand RDFLib terms directly.jsonld.to_rdf()now returns anrdflib.Datasetby default when no outputformatis requested.- Added
legacyModetojsonld.to_rdf()to return the previous RDF.js-like datasetdict. jsonld.from_rdf()now accepts bothrdflib.Datasetinputs and the previous legacy datasetdictshape.- Updated RDF-related tests for RDFLib dataset and N-Quads serialization behavior.
- BREAKING: nquads input/output now delegates to RDFLib instead of PyLD’s custom parser and serializer.
- Migrate
canon.pytordflib:- Now use
rdflibfor RDF term type checking (e.g., checking is something is a bnode), looping over triples/quads, nquads serialization and constructing RDF terms (custom deepcopy is no longer needed) - Move nquads parsing from
JsonLdProcessor.normalize()toURDNA2015.main()so all parsing and serialization is handled by the same class. - Move the main logic to
URDNA2015._canonicalize(self, dataset: Dataset)while keeping input and output inURDNA2015.main(). The methodURDNA2015._canonicalize(self, dataset: Dataset)accepts anrdflib.Datasetand returns a tuple with- the canonicalized result as a nquads
strand - the blank node identifier map as
dict.
- the canonicalized result as a nquads
- The method
URDNA2015 .main(self, dataset: str | dict | Dataset, options)now- accepts a
rdflib.Datasetobject in addition to an nquadsstror the original RDFJS-likedict. - returns
- a
str: the serialized nquads result, or - a
dict: the result as RDFJS-like dataset or the blank node identifier map when the new parameteroutputMapisTrue.
- a
- accepts a
- The hashing algorithm is now an class attribute
URDNA2015.hash_algorithmso it configurable (required for RDFC1.0) - The
permutations()function now usesitertools.permutationsinstead of a custom implementation. - Replacements for rdflib's
_nq_rowand_quoteLiteral(these should eventually move to a fix for rdflib's nquads serializer). - Re-enabled all skipped URDNA2015, URDNA2012 tests in
tests/runtests.py
- Now use
- If the result of a test is a dict and the expected value is a string, the expected value is now parsed as JSON (needed for testing blank-node identifier maps).
- BREAKING: Removed small Python 2-era compatibility code and simplified a few internal collection checks.
pyld.FileDocumentLoader: a document loader for localfile:URLs with optional root confinement.pyld.SchemeDirectedDocumentLoader: a document loader that dispatches URL strings to per-scheme loaders.
*OptionsTypedDict types and aContexttype alias inpyld.optionsfor JSON-LD API option dicts (typing and documentation).pyld.SqliteCacheRequestsDocumentLoader: a SQLite-backed HTTP cache document loader usingrequests-cache.
- If value objects contain array values for
@typeduring expansion, an error is now raised. Fixes expand#ter54 and toRdf#ter54. - Inline contexts that try to redefine @context now raise an error. Fixes expand#ter56 and toRdf#ter56.
- When using native types, values of
xsd:booleanandxsd:integerare now properly converted. Fixes fromRdf#t0027. - Numbers with 0 as fractional part now parse to an
xsd:integerinstead ofxsd:double. Fixes toRdf#ttn02. - Zeros are now truncated for numeric values with negative exponent.
- Blank node prefixes are now also used in IRI expansion.
- Numbers with no fractions but that are >= 1e21 are now represented as xsd:double in json-ld-1.1 processing mode.
- In
RequestsDocumentLoader, constructor-level headers are now removed from**kwargsand stored separately, avoiding duplicateheaders=when callingsession.get. Per-calloptions["headers"]still takes precedence.
- When compacting, expands the index mapping first, then compacts that expanded IRI, matching the JSON-LD API compaction correction for compact-IRI index mappings. Fixes testcases compact#t0112 and compact#t0113.
- Fixes
AttributeErrorwhen compacting with@none: the@typemap compaction path now only calls.pop()and inspects keys whencompacted_itemis actually an object. Fixes compact#tm023 - An empty property-scoped context no longer resets the active context in
_create_term_definition. Now only explicit null becomes False; empty contexts are preserved. Fixes compact#tc028, toRdf#tc036 and expand#tc036. - Options from the test manifest now override the options configured in
create_test_options(), instead of the other way around. This fixes tests not able to override default options in the test-setup such asextractAllScripts. Fixes html#tf004. - When
@typeis@jsonin a frame, it no longer raises an "Invalid JSON-LD syntax" error. Fixes frame#t0069. - Use safeguard for non-dict values of
options['link'] - Local and type-scoped contexts are now properly resolved for nested node
objects, so a scoped context on a
@nestterm is being applied to nested properties. Fixes toRdf#tc037, toRdf#tc038, expand#tc037 and expand#tc038.
requests_document_loader()andaiohttp_document_loader()now return class-basedDocumentLoaderinstances while preserving the existing callable factory API. The concreteRequestsDocumentLoaderandAioHttpDocumentLoaderclasses are also importable frompyld.- The
pytesttest runner now uses plain assert result == expect instead of printing EXPECTED / ACTUAL and raising a generic failure. This enablespytests's native result comparison. - Convert
./README.rstand./CONTRIBUTING.rst(reStructuredText) to./README.mdand./CONTRIBUTING.md(markdown). Also update their contents to reflect the current state of the repo. - Replace the old Sphinx documentation with a MkDocs Material site and add a GitHub Pages documentation workflow.
pyld.DocumentLoaderabstract base class for class-based document loaders, with aRemoteDocumentTypedDictdescribing the expected return shape.pyld.FrozenDocumentLoader: a class-based loader that serves only URLs in itsdocumentsallowlist and refuses everything else withJsonLdError(code='loading document failed'). Instantiating with no arguments serves the curatedpyld.BUNDLED_CONTEXTSset; instantiating withdict(BUNDLED_CONTEXTS, **extras)extends the bundle. Suitable for air-gapped, reproducible-build, and security-hardened deployments.pyld.BUNDLED_CONTEXTS: curated mapping of high-traffic public W3C / W3ID JSON-LD contexts (ActivityStreams, DID v1, VC v1/v2, Linked Data Security v1/v2, Ed25519-2020, JWS-2020) to vendored on-disk copies. Refresh withmake download-bundled-contexts.pyld.ContextResolver: added themax_context_urlsproperty that determines maximum number of times contexts can be recusively fetched, which replaces the role of the staticMAX_CONTEXT_URLS. The constructor now accepts amax_context_urlsparameter that sets the value ofmax_context_urlswhich defaults toMAX_CONTEXT_URLS.pyld.fromRdf()andpyld.toRdf()now support compound literals when serializing/deserializing RDF to/from JSON-LD. Therefore, both methods accept the value'compound-literal'for the'rdfDirection'option. Fixes fromRdf#tdi11, fromRdf#tdi12, toRdf#tdi11, and toRdf#tdi12.
- BREAKING: Compaction term selection now follows the JSON-LD 1.1 spec (Inverse Context Creation, section 4.3 step 3): terms are ordered by shortest first, with lexicographic tiebreak. Previously terms were ordered lexicographically first, then by length. This changes which term is selected when multiple context keys map to the same IRI. See #247.
- BREAKING: Require supported Python version >= 3.10.
- Update aiohttp document loader to work with Python 3.14.
- Minimize async related changes to library code in this release.
- In sync environment use
asyncio.run. - In async environment use background thread.
- The default test manifests or directories now default to the
./specificationsdirectory. - Add ability to run test suites using pytest and make pytest the default way for running (unit)tests.
- The functionality to resolve relative IRIs to absolute IRIs has been moved
from
context_resolver.pytoiri_resolver.pyso it can be maintained and tested separately.- Migrate the
prepend_base(base, iri)function to theresolve(iri, base)function. - Move the existing function
remove_dot_segments(path)and update the implementation. - Migrate the
remove_base(base, iri)function to theunresolve(iri, base)function and update the implementation to use stdliburllib.parseandurllib.unparseto replace the custom implementation. - Update code to use
resolve(iri, base)andunresolve(iri, base)instead. Invalid base IRIs (includingNone) are no longer allowed, hence missing base IRIs in the JSON-LD context are now handled outside the function call. - Add unittests
- Migrate the
- BREAKING: the custom
causeandtracebackattributes onJsonLdErrorare replaced by Python exception chaining and the built-in__cause__attribute. - BREAKING: The
IdentifierIssuerclass was moved toidentifier_issuer.py. It's now available atpyld.identifier_issuer. - BREAKING: The classes
URDNA2015andURGNA2012were moved tocanon.py. They are now available atpyld.canon. jsonld.expand()now accepts aon_property_droppedparameter which is a handler called on every ignored JSON property.- BREAKING: In cases where there is no document base (for instance, when
using a string as input), 'http://example.org/base/' is used as the base IRI
when
@baseis absent or explicitely set tonull. - BREAKING: Some internal parameters were renamed from camelCase to pythonic:
requestProfiletorequest_profileinload_document()rdfDirectiontordf_directionin_list_to_rdf()and_object_to_rdf()
- Use explicit
NoneorFalsefor context checks. Fixes an issue while framing with an empty context.
- Fix deprecation warnings due to invalid escape sequences.
- Fix inverse context cache indexing to use the uuid field.
- Improve EARL output.
- This release adds JSON-LD 1.1 support. Significant thanks goes to Gregg Kellogg!
- BREAKING: It is highly recommended to do proper testing when upgrading from the previous version. The framing API in particular now follows the 1.1 spec and some of the defaults changed.
- BREAKING: Versions of Python before 3.6 are no longer supported.
- Update conformance docs.
- Add all keywords and update options.
- Default
processingModetojson-ld-1.1. - Implement logic for marking tests as pending, so that it will fail if a pending test passes.
- Consolidate
documentLoaderoption and defaults into aload_documentmethod to also handle JSON (eventually HTML) parsing. - Add support for
rel=alternatefor non-JSON-LD docs. - Use
lxml.htmlto load HTML and parse inload_html.- For HTML, the API base option can be updated from base element.
- Context processing:
- Support
@propagatein context processing and propagate option. - Support for
@import. (Some issues confusing recursion errors for invalid contexts). - Make
override_protectedandpropagateoptional arguments to_create_term_definitionand_process_contextinstead of using option argument. - Improve management of previous contexts.
- Imported contexts must resolve to an object.
- Do remote context processing from within
_process_contexts, as logic is too complicated for pre-loading. Removes_find_context_urlsand_retrieve_context_urls. - Added a
ContextResolverwhich can use a shared LRU cache for storing externally retrieved contexts, and the result of processing them relative to a particular active context. - Return a
frozendictfrom context processing and reduce deepcopies. - Store inverse context in an LRU cache rather than trying to modify a frozen context.
- Don't set
@basein initial context and don't resolve a relative IRI when setting@basein a context, so that the document location can be kept separate from the context itself. - Use static initial contexts composed of just
mappingsandprocessingModeto enhance preprocessed context cachability.
- Support
- Create Term Definition:
- Allow
@typeas a term under certain circumstances. - Reject and warn on keyword-like terms.
- Support protected term definitions.
- Look for keyword patterns and warn/return.
- Look for terms that are compact IRIs that don't expand to the same thing.
- Basic support for
@jsonand@noneas values of@type. - If
@containerincludes@type,@typemust be@idor@vocab. - Support
@indexand@direction. - Corner-case checking for
@prefix. - Validate scoped contexts even if not used.
- Support relative vocabulary IRIs.
- Fix check that term has the form of an IRI.
- Delay adding mapping to end of
_create_term_definition. - If a scoped context is null, wrap it in an array so it doesn't seem to be undefined.
- Allow
- IRI Expansion:
- Find keyword patterns.
- Don't treat terms starting with a colon as IRIs.
- Only return a resulting IRI if it is absolute.
- Fix
_is_absolute_irito use a reasonable regular expression and some other_expand_iri issues. - Fix to detecting relative IRIs.
- Fix special case where relative path should not have a leading '/'
- Pass in document location (through 'base' option) and use when resolving document-relative IRIs.
- IRI Compaction:
- Pass in document location (through 'base' option) and use when compacting document-relative IRIs.
- Compaction:
- Compact
@direction. - Compact
@type:@none. - Compact
@included. - Honor
@container:@seton@type. - Lists of Lists.
- Improve handling of scoped contexts and propagate.
- Improve map compaction, including indexed properties.
- Catch Absolute IRI confused with prefix.
- Compact
- Expansion:
- Updates to expansion algorithm.
_expand_valueadds@directionfrom term definition.- JSON Literals.
- Support
@directionwhen expanding. - Support lists of lists.
- Support property indexes.
- Improve graph container expansion.
- Order types when applying scoped contexts.
- Use
type_scoped_ctxwhen expanding values of@type. - Use propagate and
override_protectedproperly when creating expansion contexts.
- Flattening:
- Rewrite
_create_node_mapbased on 1.1 algorithm. - Flatten
@included. - Flatten lists of lists.
- Update
merge_node_mapsfor@type.
- Rewrite
- Framing:
- Change default for
requireAllfrom True to False. - Change default for 'embed' from '@last' to '@once'.
- Add defaults for
omitGraphandpruneBlankNodeIdentifiersbased on processing mode. - Change
_remove_preserveto_cleanup_preservewhich happens before compaction. - Add
_cleanup_nullwhich happens after compaction. - Update frame matching to 1.1 spec.
- Support
@included.
- Change default for
- ToRdf:
- Support for I18N direction.
- Support for Lists of Lists.
- Partial support for JSON canonicalization of JSON literals.
- Includes local copy of JCS library, but doesn't load.
- Lists of Lists.
- Text Direction 'i18n-datatype'.
- Testing
- Switched to argparse.
- BREAKING: Removed
-dand-mtest runner options in favor of just listing as arguments. - If no test manifests or directories are specified, default to sibling directories for json-ld-api, json-ld-framing, and normalization.
- Use
returninstead ofraise StopIterationto terminate generator.
- Accept N-Quads upper case language tag.
- Reorder code to avoid undefined symbols.
- Missing error parameter.
- Include document loaders in distribution.
- 1.0.0!
- Semantic Versioning is now past the "initial development" 0.x.y stage (after 6+ years!).
- Conformance:
- JSON-LD 1.0 + JSON-LD 1.0 errata
- JSON-LD 1.1 drafts
- Thanks to the JSON-LD and related communities and the many many people over the years who contributed ideas, code, bug reports, and support!
- Don't always use arrays for
@graph. Fixes 1.0 compatibility issue. - Process @type term contexts before key iteration.
- BREAKING: A dependency of pyld will not pull in Requests anymore.
One needs to define a dependency to
pyld[requests]or create an explicit dependency onrequestsseperately. Usepyld[aiohttp]for aiohttp. - The default document loader is set to
request_document_loader. If Requests is not available,aiohttp_document_loaderis used. When aiohttp is not availabke, adummy_document_loaderis used. - Use the W3C standard MIME type for N-Quads of "application/n-quads". Accept "application/nquads" for compatibility.
- Support for asynchronous document loader library aiohttp.
- Added
dummy_document_loaderwhich allows libraries to depend on pyld without depending on Requests or aiohttp. - The test runner contains an additional parameter
-lto specify the default document loader. - Expansion and Compaction using scoped contexts on property and
@typeterms. - Expansion and Compaction of nested properties.
- Index graph containers using
@idand@index, with@setvariations. - Index node objects using
@idand@type, with@setvariations. - Framing default and named graphs in addition to merged graph.
- Value patterns when framing, allowing a subset of values to appear in the output.
- Use default document loader for older exposed
load_documentAPI.
- Use
__about__.pyto hold versioning and other meta data. Load file insetup.pyandjsonld.py. Fixes testing and installation issues.
- BREAKING: Default http (80) and https (443) ports removed from URLs. This matches test suite behavior and other processing libs such as jsonld.js.
- BREAKING: Fix path normalization to pass test suite RFC 3984 tests. This could change output for various relative URL edge cases.
- Allow empty lists to be compacted to any
@listcontainer term. (Port from jsonld.js)
- BREAKING: Remove older document loader code. SSL/SNI support wasn't working well with newer Pythons.
- BREAKING: Switch to Requests for document loading. Some behavior could slightly change. Better supported in Python 2 and Python 3.
- Support for test suite using http or https.
- Easier to create a custom Requests document loader with the
requests_document_loadercall. Adds asecureflag to always use HTTPS. Can pass in keywords that Requests understands.verifyto disable SSL verification or use custom cert bundles.certto use client certs.timeoutto fail on timeouts (important for production use!). See Requests docs for more info.
- See git history for changes.