diff --git a/.github/workflows/test-report.yml b/.github/workflows/test-report.yml index ad6a82883..386183ad1 100644 --- a/.github/workflows/test-report.yml +++ b/.github/workflows/test-report.yml @@ -11,14 +11,14 @@ jobs: checks: write statuses: write steps: - - uses: dorny/test-reporter@v1 + - uses: dorny/test-reporter@v2 with: artifact: /(.*)-mypy-junit-xml$/ name: mypy report path: "*.xml" reporter: java-junit fail-on-error: "false" - - uses: dorny/test-reporter@v1 + - uses: dorny/test-reporter@v2 with: artifact: /(.*)-pytest-junit-xml$/ name: pytest report diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8a74122cc..098305df0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # WARNING: Ruff version should be the same as in `pyproject.toml` - rev: v0.5.4 + rev: v0.11.0 hooks: - id: ruff args: ["--fix"] @@ -21,9 +21,8 @@ repos: require_serial: true args: ["."] - repo: https://github.com/python-poetry/poetry - rev: 1.8.3 + rev: 2.1.1 hooks: - id: poetry-check - - id: poetry-lock # sadly `--no-update` does not work on pre-commit.ci - args: ["--check"] + args: ["--lock"] diff --git a/.readthedocs.yaml b/.readthedocs.yaml index f5becb937..d847956c1 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,7 +1,7 @@ --- # https://docs.readthedocs.io/en/stable/config-file/v2.html version: 2 -# NOTE: not builing epub because epub does not know how to handle .ico files +# NOTE: not building epub because epub does not know how to handle .ico files # which results in a warning which causes the build to fail due to # `sphinx.fail_on_warning` # https://github.com/sphinx-doc/sphinx/issues/10350 @@ -27,4 +27,5 @@ build: - python -c "from rdflib import Graph; print(Graph)" sphinx: + configuration: docs/conf.py fail_on_warning: true diff --git a/CHANGELOG.md b/CHANGELOG.md index bb6d15999..047828f0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,181 @@ +## 2025-09-19 RELEASE 7.2.1 + +A tiny clean up release. + +Fixes: +- Previous RDFLib releases required all downstream projects to specify <4.0.0. This release relaxes this requirement to allow Python 3.8.1 and later. + +## 2025-09-19 RELEASE 7.2.0 + +This release contains a number of fixes and improvements to RDFLib. + +New features: +- Canonicalization is now optional in the longturtle serializer. When serializing with the `longturtle` format, set `canon=True` to enable canonicalization. +- General type hints enhancements + +Fixes: +- Fixed deskolemization of literals +- Fixed round-tripping of floats in N3 - floating point and scientific notation handling +- Fixed CI validation workflow, including regressions in tests +- Fixed `Literal.toPython` date conversion for gYear/gYearMonth +- Fixed namespace prefixes in longturtle serialization +- Fixed missing dot in RDF patch serialization + +PRs merged: + +* 2025-09-18 - [7.x] Fix incorrect deskolemization of literals + [PR #3223](https://github.com/RDFLib/rdflib/pull/3223) +* 2025-09-18 - Fix incorrect deskolemization of literals + [PR #3127](https://github.com/RDFLib/rdflib/pull/3127) +* 2025-09-18 - notation3.py: don't normalize float representation + [PR #3020](https://github.com/RDFLib/rdflib/pull/3020) +* 2025-09-18 - [7.x] notation3.py: don't normalize float representation + [PR #3221](https://github.com/RDFLib/rdflib/pull/3221) +* 2025-09-18 - Merge 7-maintenance branch into 7.x + [PR #3222](https://github.com/RDFLib/rdflib/pull/3222) +* 2025-09-17 - Allow lxml 6 + [PR #3219](https://github.com/RDFLib/rdflib/pull/3219) +* 2025-09-16 - ci: fix firejail command for poetry 2.1.0 + [PR #3218](https://github.com/RDFLib/rdflib/pull/3218) +* 2025-09-16 - chore: address dependabot security vulnerabilities + [PR #3210](https://github.com/RDFLib/rdflib/pull/3210) +* 2025-09-09 - Merge 7-maintenance changes into main + [PR #3202](https://github.com/RDFLib/rdflib/pull/3202) +* 2025-09-08 - feat: canonicalization with longturtle serializer now optional + [PR #3197](https://github.com/RDFLib/rdflib/pull/3197) +* 2025-09-03 - Specify `Optional` parameters in `Graph.triples_choices` + [PR #3075](https://github.com/RDFLib/rdflib/pull/3075) +* 2025-08-29 - Fix failing webtest + [PR #3194](https://github.com/RDFLib/rdflib/pull/3194) +* 2025-08-29 - Revert "remove old hacks against 2to3 (#3076)" + [PR #3195](https://github.com/RDFLib/rdflib/pull/3195) +* 2025-08-18 - Fix #3181 + [PR #3182](https://github.com/RDFLib/rdflib/pull/3182) +* 2025-08-18 - Fix contributing guide link in README.md + [PR #3158](https://github.com/RDFLib/rdflib/pull/3158) +* 2025-08-18 - Creation of an RDFLib Charter + [PR #3178](https://github.com/RDFLib/rdflib/pull/3178) +* 2025-08-11 - Feature: Add Tentris Plugin to docs + [PR #3177](https://github.com/RDFLib/rdflib/pull/3177) +* 2025-06-02 - Replacement for #3125 + [PR #3146](https://github.com/RDFLib/rdflib/pull/3146) +* 2025-06-01 - Cope with Namespace annotations in Python 3.14 + [PR #3132](https://github.com/RDFLib/rdflib/pull/3132) +* 2025-06-01 - replace PR 3109; improve plugins modules docs; change header colour t… + [PR #3145](https://github.com/RDFLib/rdflib/pull/3145) +* 2025-06-01 - Pr/3143 + [PR #3144](https://github.com/RDFLib/rdflib/pull/3144) +* 2025-05-31 - fix: remove Literal.toPython date conversion for gYear/gYearMonth + [PR #3115](https://github.com/RDFLib/rdflib/pull/3115) +* 2025-05-31 - fix: do not automatically generate header id in RDF patch generation and fix missing fullstop + [PR #3141](https://github.com/RDFLib/rdflib/pull/3141) +* 2025-05-31 - fix namespace prefixes in longturtle serialization + [PR #3106](https://github.com/RDFLib/rdflib/pull/3106) +* 2025-05-20 - [7.x] fix namespace prefixes in longturtle serialization + [PR #3134](https://github.com/RDFLib/rdflib/pull/3134) +* 2025-05-20 - List on docs the COTTAS store backend + [PR #3139](https://github.com/RDFLib/rdflib/pull/3139) +* 2025-03-29 - 7.1.4 pre-release + [PR #3098](https://github.com/RDFLib/rdflib/pull/3098) + + +* 2025-09-16 - build(deps): bump poetry from 2.0.0 to 2.1.4 in /devtools + [PR #3176](https://github.com/RDFLib/rdflib/pull/3176) +* 2025-09-16 - build(deps): bump library/python from `8220cce` to `58c30f5` in /docker/latest + [PR #3217](https://github.com/RDFLib/rdflib/pull/3217) +* 2025-09-16 - build(deps): bump library/python from `8220cce` to `58c30f5` in /docker/unstable + [PR #3216](https://github.com/RDFLib/rdflib/pull/3216) +* 2025-09-16 - build(deps-dev): bump ruff from 0.8.6 to 0.13.0 + [PR #3213](https://github.com/RDFLib/rdflib/pull/3213) +* 2025-09-16 - build(deps-dev): bump pip-tools from 7.4.1 to 7.5.0 + [PR #3211](https://github.com/RDFLib/rdflib/pull/3211) +* 2025-09-16 - build(deps-dev): bump mkdocstrings from 0.29.1 to 0.30.0 + [PR #3214](https://github.com/RDFLib/rdflib/pull/3214) +* 2025-09-12 - build(deps): bump library/python from 3.13.3-slim to 3.13.7-slim in /docker/unstable + [PR #3183](https://github.com/RDFLib/rdflib/pull/3183) +* 2025-09-12 - build(deps): bump actions/checkout from 4 to 5 + [PR #3184](https://github.com/RDFLib/rdflib/pull/3184) +* 2025-09-12 - build(deps): bump library/python from 3.13.3-slim to 3.13.7-slim in /docker/latest + [PR #3185](https://github.com/RDFLib/rdflib/pull/3185) +* 2025-09-12 - build(deps): bump actions/setup-java from 4 to 5 + [PR #3189](https://github.com/RDFLib/rdflib/pull/3189) +* 2025-09-12 - build(deps-dev): bump pytest-cov from 6.1.1 to 6.3.0 + [PR #3203](https://github.com/RDFLib/rdflib/pull/3203) +* 2025-09-12 - build(deps-dev): bump typing-extensions from 4.13.2 to 4.15.0 + [PR #3204](https://github.com/RDFLib/rdflib/pull/3204) +* 2025-09-12 - build(deps-dev): bump pytest from 8.3.5 to 8.4.2 + [PR #3205](https://github.com/RDFLib/rdflib/pull/3205) +* 2025-09-12 - build(deps-dev): bump mkdocs-include-markdown-plugin from 7.1.5 to 7.1.7 + [PR #3207](https://github.com/RDFLib/rdflib/pull/3207) +* 2025-09-12 - build(deps): bump actions/setup-python from 5 to 6 + [PR #3206](https://github.com/RDFLib/rdflib/pull/3206) +* 2025-09-12 - build(deps-dev): bump mkdocs-material from 9.6.14 to 9.6.19 + [PR #3208](https://github.com/RDFLib/rdflib/pull/3208) +* 2025-09-12 - build(deps-dev): bump coverage from 7.8.2 to 7.10.6 + [PR #3209](https://github.com/RDFLib/rdflib/pull/3209) +* 2025-05-31 - build(deps-dev): bump coverage from 7.7.1 to 7.8.2 + [PR #3142](https://github.com/RDFLib/rdflib/pull/3142) +* 2025-05-31 - build(deps-dev): bump typing-extensions from 4.13.0 to 4.13.2 + [PR #3121](https://github.com/RDFLib/rdflib/pull/3121) +* 2025-05-31 - build(deps): bump library/python from 3.13.1-slim@sha256:1127090f9fff0b8e7c3a1367855ef8a3299472d2c9ed122948a576c39addeaf1 to sha256:34dc8eb488136014caf530ec03a3a2403473a92d67a01a26256c365b5b2fc0d4 in /docker/unstable + [PR #3118](https://github.com/RDFLib/rdflib/pull/3118) +* 2025-05-31 - build(deps): bump library/python from 3.13.1-slim@sha256:1127090f9fff0b8e7c3a1367855ef8a3299472d2c9ed122948a576c39addeaf1 to sha256:34dc8eb488136014caf530ec03a3a2403473a92d67a01a26256c365b5b2fc0d4 in /docker/latest + [PR #3117](https://github.com/RDFLib/rdflib/pull/3117) +* 2025-05-27 - build(deps): bump rdflib from 7.1.2 to 7.1.4 in /docker/latest + [PR #3101](https://github.com/RDFLib/rdflib/pull/3101) + +## 2025-03-29 RELEASE 7.1.4 + +A tidy-up release with no major updates over 7.1.3. This may be the last 7.x +release as we move to a version 8 with breaking changes to Dataset and a few +APIs. + +Interesting PRs merged: + +* 2025-03-24 - remove old hacks against 2to3 + [PR #3095](https://github.com/RDFLib/rdflib/pull/3095) +* 2025-03-24 - Allow multi subjects & objects in graph funcs + [PR #3086](https://github.com/RDFLib/rdflib/pull/3086) +* 2025-03-24 - Reduce test warnings + [PR #3085](https://github.com/RDFLib/rdflib/pull/3085) +* 2025-03-22 - Downgrade log message about plugin + [PR #3063](https://github.com/RDFLib/rdflib/pull/3063) +* 2025-03-22 - remove old hacks against 2to3 + [PR #3076](https://github.com/RDFLib/rdflib/pull/3076) +* 2025-03-22 - Cope with Namespace annotations in Python 3.14 + [PR #3084](https://github.com/RDFLib/rdflib/pull/3084) +* 2025-01-18 - small docco update + [PR #3053](https://github.com/RDFLib/rdflib/pull/3053) + +... and lots of boring dependency bump PRs merged! + +## 2025-01-17 RELEASE 7.1.3 + +A fix-up release that re-adds support for Python 3.8 after it was accidentally +removed in Release 7.1.2. + +This release cherrypicks many additions to 7.1.2 added to 7.1.1 but leaves out +typing changes that are not compatible +with Python 3.8. + +Also not carried over from 7.1.2 is the change from Poetry 1.x to 2.0. + +Included are PRs such as _Defined Namespace warnings fix_, _sort longturtle +blank nodes_, _deterministic longturtle serialisation_ and _Dataset documentation +improvements_. + +For the full list of included PRs, see the preparatory PR: +. + +## 2025-01-10 RELEASE 7.1.2 + +A minor release that inadvertently removed support for Python 3.8. This release +how now been deleted. + +All the improved features initially made available in this release that were +compatible with Python 3.8 have been preserved in the 7.1.3 release. The main +additions to 7.1.2 not preserved in 7.1.3 are updated type hints. + ## 2024-10-17 RELEASE 7.1.1 This minor release removes the dependency on some only Python packages, in particular @@ -31,7 +209,6 @@ Merged PRs: * 2024-10-23 - build(deps-dev): bump ruff from 0.6.9 to 0.7.0 [PR #2942](https://github.com/RDFLib/rdflib/pull/2942) - ## 2024-10-17 RELEASE 7.1.0 This minor release incorporates just over 100 substantive PRs - interesting diff --git a/CITATION.cff b/CITATION.cff index c403aa383..ef4772952 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -69,7 +69,7 @@ authors: - family-names: "Stuart" given-names: "Veyndan" title: "RDFLib" -version: 7.1.1 -date-released: 2024-10-28 +version: 7.2.1 +date-released: 2025-09-19 url: "https://github.com/RDFLib/rdflib" doi: 10.5281/zenodo.6845245 diff --git a/LICENSE b/LICENSE index 6f2449678..75e852b7b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2002-2024, RDFLib Team +Copyright (c) 2002-2025, RDFLib Team All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index a5b9c9ff2..8ddb4eb72 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,10 @@ RDFLib RDFLib is a pure Python package for working with [RDF](http://www.w3.org/RDF/). RDFLib contains most things you need to work with RDF, including: -* parsers and serializers for RDF/XML, N3, NTriples, N-Quads, Turtle, TriX, Trig and JSON-LD +* parsers and serializers for RDF/XML, N3, NTriples, N-Quads, Turtle, TriX, Trig, JSON-LD and even HexTuples * a Graph interface which can be backed by any one of a number of Store implementations -* store implementations for in-memory, persistent on disk (Berkeley DB) and remote SPARQL endpoints +* Store implementations for in-memory, persistent on disk (Berkeley DB) and remote SPARQL endpoints + * additional Stores can be supplied via plugins * a SPARQL 1.1 implementation - supporting SPARQL 1.1 Queries and Update statements * SPARQL function extension mechanisms @@ -29,10 +30,8 @@ The RDFlib community maintains many RDF-related Python code repositories with di * [rdflib](https://github.com/RDFLib/rdflib) - the RDFLib core * [sparqlwrapper](https://github.com/RDFLib/sparqlwrapper) - a simple Python wrapper around a SPARQL service to remotely execute your queries -* [pyLODE](https://github.com/RDFLib/pyLODE) - An OWL ontology documentation tool using Python and templating, based on LODE. -* [pyrdfa3](https://github.com/RDFLib/pyrdfa3) - RDFa 1.1 distiller/parser library: can extract RDFa 1.1/1.0 from (X)HTML, SVG, or XML in general. -* [pymicrodata](https://github.com/RDFLib/pymicrodata) - A module to extract RDF from an HTML5 page annotated with microdata. -* [pySHACL](https://github.com/RDFLib/pySHACL) - A pure Python module which allows for the validation of RDF graphs against SHACL graphs. +* [pyLODE](https://github.com/RDFLib/pyLODE) - An OWL ontology documentation tool using Python and templating, based on LODE +* [pySHACL](https://github.com/RDFLib/pySHACL) - A pure Python module which allows for the validation of RDF graphs against SHACL graphs * [OWL-RL](https://github.com/RDFLib/OWL-RL) - A simple implementation of the OWL2 RL Profile which expands the graph with all possible triples that OWL RL defines. Please see the list for all packages/repositories here: @@ -43,8 +42,14 @@ Help with maintenance of all of the RDFLib family of packages is always welcome ## Versions & Releases -* `main` branch in this repository is the unstable release -* `7.1.1` current stable release, bugfixes to 7.1.0 +* `main` branch in this repository is the current unstable release - version 8 alpha +* `7.2.1` tiny clean up release, relaxes Python version requirement +* `7.2.0` general fixes and usability improvements, see changelog for details +* `7.1.4` tidy-up release, possibly last 7.x release +* `7.1.3` current stable release, small improvements to 7.1.1 +* `7.1.2` previously deleted release +* `7.1.1` previous stable release + * see * `7.0.0` previous stable release, supports Python 3.8.1+ only. * see [Releases](https://github.com/RDFLib/rdflib/releases) * `6.x.y` supports Python 3.7+ only. Many improvements over 5.0.0 @@ -68,8 +73,6 @@ Some features of RDFLib require optional dependencies which may be installed usi Alternatively manually download the package from the Python Package Index (PyPI) at https://pypi.python.org/pypi/rdflib -The current version of RDFLib is 7.1.1, see the ``CHANGELOG.md`` file for what's new in this release. - ### Installation of the current main branch (for developers) With *pip* you can also install rdflib from the git repository with one of the following options: diff --git a/Taskfile.yml b/Taskfile.yml index 2b9582f5f..1ae5947ec 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -272,7 +272,7 @@ tasks: pip-compile: cmds: - - cmd: "{{.PIP_COMPILE}} --quiet --annotate --emit-options --resolver=backtracking {{.CLI_ARGS}}" + - cmd: "{{.PIP_COMPILE}} --quiet --annotate --emit-options --resolver=backtracking --no-strip-extras {{.CLI_ARGS}}" docker:prepare: cmds: diff --git a/admin/get_merged_prs.py b/admin/get_merged_prs.py index 7e96d1d47..c4b904448 100644 --- a/admin/get_merged_prs.py +++ b/admin/get_merged_prs.py @@ -5,7 +5,7 @@ import urllib.request # https://api.github.com/search/issues?q=repo:rdflib/rdflib+is:pr+merged:%3E=2023-08-02&per_page=300&page=1 -LAST_RELEASE_DATE = "2024-10-17" +LAST_RELEASE_DATE = "2025-03-29" ISSUES_URL = "https://api.github.com/search/issues" ITEMS = [] PAGE = 1 @@ -23,7 +23,11 @@ print(f"Getting {url}") with urllib.request.urlopen(url) as response: response_text = response.read() - link_headers = response.info()["link"].split(",") if response.info()["link"] is not None else None + link_headers = ( + response.info()["link"].split(",") + if response.info()["link"] is not None + else None + ) json_data = json.loads(response_text) ITEMS.extend(json_data["items"]) diff --git a/devtools/requirements-poetry.in b/devtools/requirements-poetry.in index 1bf7b707a..7ba51be53 100644 --- a/devtools/requirements-poetry.in +++ b/devtools/requirements-poetry.in @@ -1,3 +1,3 @@ # Fixing this here as readthedocs can't use the compiled requirements-poetry.txt # due to conflicts. -poetry==1.8.4 +poetry==1.8.5 diff --git a/docker/latest/Dockerfile b/docker/latest/Dockerfile index fbaa97480..24a516c77 100644 --- a/docker/latest/Dockerfile +++ b/docker/latest/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/library/python:3.12.7-slim@sha256:af4e85f1cac90dd3771e47292ea7c8a9830abfabbe4faa5c53f158854c2e819d +FROM docker.io/library/python:3.13.2-slim@sha256:ae9f9ac89467077ed1efefb6d9042132d28134ba201b2820227d46c9effd3174 COPY docker/latest/requirements.txt /var/tmp/build/ diff --git a/docker/latest/requirements.in b/docker/latest/requirements.in index 42fb39ae7..acfcb2e19 100644 --- a/docker/latest/requirements.in +++ b/docker/latest/requirements.in @@ -1,6 +1,4 @@ # This file is used for building a docker image of the latest rdflib release. It # will be updated by dependabot when new releases are made. -rdflib==7.1.0 -html5rdf==1.2.0 -# html5lib-modern is required to allow the Dockerfile to build on with pre-RDFLib-7.1.1 releases. -html5lib-modern==1.2.0 +rdflib==7.2.1 +html5rdf==1.2.1 diff --git a/docker/latest/requirements.txt b/docker/latest/requirements.txt index 570502462..411657d7b 100644 --- a/docker/latest/requirements.txt +++ b/docker/latest/requirements.txt @@ -1,16 +1,12 @@ # -# This file is autogenerated by pip-compile with Python 3.12 +# This file is autogenerated by pip-compile with Python 3.13 # by the following command: # -# pip-compile docker/latest/requirements.in +# pip-compile --cert=None --client-cert=None --index-url=None --pip-args=None docker/latest/requirements.in # -html5rdf==1.2 - # via - # -r docker/latest/requirements.in - # rdflib -html5lib-modern==1.2 +html5rdf==1.2.1 # via -r docker/latest/requirements.in pyparsing==3.0.9 # via rdflib -rdflib==7.1.0 +rdflib==7.2.1 # via -r docker/latest/requirements.in diff --git a/docker/unstable/Dockerfile b/docker/unstable/Dockerfile index 85564a955..fc4c43c4d 100644 --- a/docker/unstable/Dockerfile +++ b/docker/unstable/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/library/python:3.12.7-slim@sha256:af4e85f1cac90dd3771e47292ea7c8a9830abfabbe4faa5c53f158854c2e819d +FROM docker.io/library/python:3.13.2-slim@sha256:8f3aba466a471c0ab903dbd7cb979abd4bda370b04789d25440cc90372b50e04 # This file is generated from docker:unstable in Taskfile.yml COPY var/requirements.txt /var/tmp/build/ diff --git a/docs/apidocs/examples.rst b/docs/apidocs/examples.rst index 43b92c137..a8c3429bd 100644 --- a/docs/apidocs/examples.rst +++ b/docs/apidocs/examples.rst @@ -3,10 +3,18 @@ examples Package These examples all live in ``./examples`` in the source-distribution of RDFLib. -:mod:`~examples.conjunctive_graphs` Module ------------------------------------------- +:mod:`~examples.datasets` Module +-------------------------------- + +.. automodule:: examples.datasets + :members: + :undoc-members: + :show-inheritance: + +:mod:`~examples.jsonld_serialization` Module +-------------------------------------------- -.. automodule:: examples.conjunctive_graphs +.. automodule:: examples.jsonld_serialization :members: :undoc-members: :show-inheritance: diff --git a/docs/conf.py b/docs/conf.py index 44b21a91b..b3c4a373b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -81,7 +81,7 @@ # General information about the project. project = "rdflib" -copyright = "2009 - 2024, RDFLib Team" +copyright = "2002 - 2025, RDFLib Team" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/developers.rst b/docs/developers.rst index 7ca914fca..80cd01bbc 100644 --- a/docs/developers.rst +++ b/docs/developers.rst @@ -231,20 +231,17 @@ our black.toml config file: poetry run black . -Check style and conventions with `flake8 `_: +Check style and conventions with `ruff `_: .. code-block:: bash - poetry run flake8 rdflib + poetry run ruff check -We also provide a `flakeheaven `_ -baseline that ignores existing flake8 errors and only reports on newly -introduced flake8 errors: +Any issues that are found can potentially be fixed automatically using: .. code-block:: bash - poetry run flakeheaven - + poetry run ruff check --fix Check types with `mypy `_: @@ -437,6 +434,8 @@ flag them as expecting to fail. Compatibility ------------- +RDFLib 8.x is likely to support only the Python versions in bugfix status at the time of its release, so perhaps 3.12+. + RDFlib 7.0.0 release and later only support Python 3.8.1 and newer. RDFlib 6.0.0 release and later only support Python 3.7 and newer. @@ -446,22 +445,46 @@ RDFLib 5.0.0 maintained compatibility with Python versions 2.7, 3.4, 3.5, 3.6, 3 Releasing --------- +These are the major steps for releasing new versions of RDFLib: + +#. Create a pre-release PR + + * that updates all the version numbers + * merge it with all tests passing + +#. Do the PyPI release +#. Do the GitHub release +#. Create a post-release PR + + * that updates all version numbers to next (alpha) release + * merge it with all tests passing + +#. Let the world know + + +1. Create a pre-release PR +~~~~~~~~~~~~~~~~~~~~~~~~~~ + Create a release-preparation pull request with the following changes: -* Updated version and date in ``CITATION.cff``. -* Updated copyright year in the ``LICENSE`` file. -* Updated copyright year in the ``docs/conf.py`` file. -* Updated main branch version and current version in the ``README.md`` file. -* Updated version in the ``pyproject.toml`` file. -* Updated ``__date__`` in the ``rdflib/__init__.py`` file. -* Accurate ``CHANGELOG.md`` entry for the release. +#. In ``pyproject.toml``, update the version number +#. In ``README.md``, update the *Versions & Releases* section +#. In ``rdflib/__init__.py``, update the ``__date__`` value +#. In ``docs/conf.py``, update copyright year +#. In ``CITATION.cff``, update the version and date +#. In ``LICENSE``, update the copyright year +#. In ``CHANGELOG.md``, write an entry for this release + #. You can use the tool ``admin/get_merged_prs.py`` to assist with compiling a log of PRs and commits since last release + +2. Do the PyPI release +~~~~~~~~~~~~~~~~~~~~~~ -Once the PR is merged, switch to the main branch, build the release and upload it to PyPI: +Once the pre-release PR is merged, switch to the main branch, build the release and upload it to PyPI: .. code-block:: bash # Clean up any previous builds - \rm -vf dist/* + rm -vf dist/* # Build artifacts poetry build @@ -490,24 +513,61 @@ Once the PR is merged, switch to the main branch, build the release and upload i ## poetry publish -u __token__ -p pypi- -Once this is done, create a release tag from `GitHub releases -`_. For a release of version -6.3.1 the tag should be ``6.3.1`` (without a "v" prefix), and the release title -should be "RDFLib 6.3.1". The release notes for the latest version be added to -the release description. The artifacts built with ``poetry build`` should be -uploaded to the release as release artifacts. +3. Do the GitHub release +~~~~~~~~~~~~~~~~~~~~~~~~ -The resulting release will be available at https://github.com/RDFLib/rdflib/releases/tag/6.3.1 +Once the PyPI release is done, tag the main branch with the version number of the release. For a release of version +6.3.1 the tag should be ``6.3.1`` (without a "v" prefix): + +.. code-block:: bash + + git tag 6.3.1 + + +Push this tag to GitHub: -Once this is done, announce the release at the following locations: +.. code-block:: bash + + git push --tags + + +Make a release from this tag at https://github.com/RDFLib/rdflib/releases/new + +The release title should be "{DATE} RELEASE {VERSION}". See previous releases at https://github.com/RDFLib/rdflib/releases -* Twitter: Just make a tweet from your own account linking to the latest release. -* RDFLib mailing list. -* RDFLib Gitter / matrix.org chat room. +The release notes should be just the same as the release info in ``CHANGELOG.md``, as authored in the first major step in this release process. + +The resulting release will be available at https://github.com/RDFLib/rdflib/releases/tag/6.3.1 + +4. Create a post-release PR +~~~~~~~~~~~~~~~~~~~~~~~~~~~ Once this is all done, create another post-release pull request with the following changes: -* Set the just released version in ``docker/latest/requirements.in`` and run - ``task docker:prepare`` to update the ``docker/latest/requirements.txt`` file. -* Set the version in the ``pyproject.toml`` file to the next minor release with - a ``a0`` suffix to indicate alpha 0. +#. In ``pyproject.toml``, update to the next minor release alpha + + * so a 6.3.1 release would have 6.1.4a0 as the next release alpha + +#. In ``docker/latest/requirements.in`` set the version to the just released version +#. Use ``task docker:prepare`` to update ``docker/latest/requirements.txt`` + +5. Port changes to the next major working branch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If maintaining multiple long-lived version branches, ensure changes from this release are ported to the next major working branch. + +For instance, releasing a ``7.x`` would require merging in changes to ``main`` for version ``8.x``. + +This ensures general fixes and enhancements are ported over and maintained in the next major working branch. + +6. Let the world know +~~~~~~~~~~~~~~~~~~~~~ + +Announce the release at the following locations: + +* RDFLib mailing list +* RDFLib Gitter / matrix.org chat room +* Twitter: Just make a tweet from your own account linking to the latest release +* related mailing lists + * Jena: users@jena.apache.org + * W3C (currently RDF-Star WG): public-rdf-star@w3.org diff --git a/examples/datasets.py b/examples/datasets.py index d550775a1..eab3aa384 100644 --- a/examples/datasets.py +++ b/examples/datasets.py @@ -1,13 +1,23 @@ """ -An RDFLib Dataset is a slight extension to ConjunctiveGraph: it uses simpler terminology -and has a few additional convenience methods, for example add() can be used to -add quads directly to a specific Graph within the Dataset. +This module contains a number of common tasks using the RDFLib Dataset class. -This example file shows how to declare a Dataset, add content to it, serialise it, query it -and remove things from it. +An RDFLib Dataset is an object that stores multiple Named Graphs - instances of RDFLib +Graph identified by IRI - within it and allows whole-of-dataset or single Graph use. + +Dataset extends Graph's Subject, Predicate, Object structure to include Graph - +archaically called Context - producing quads of s, p, o, g. + +There is an older implementation of a Dataset-like class in RDFLib < 7.x called +ConjunctiveGraph that is now deprecated. + +Sections in this module: + +1. Creating & Growing Datasets +2. Looping & Counting triples/quads in Datasets +3. Manipulating Graphs with Datasets """ -from rdflib import Dataset, Literal, Namespace, URIRef +from rdflib import Dataset, Graph, Literal, URIRef # Note regarding `mypy: ignore_errors=true`: # @@ -19,41 +29,48 @@ # mypy: ignore_errors=true -# -# Create & Add -# +####################################################################################### +# 1. Creating & Growing +####################################################################################### # Create an empty Dataset d = Dataset() + # Add a namespace prefix to it, just like for Graph -d.bind("ex", Namespace("http://example.com/")) +d.bind("ex", "http://example.com/") -# Declare a Graph URI to be used to identify a Graph -graph_1 = URIRef("http://example.com/graph-1") +# Declare a Graph identifier to be used to identify a Graph +# A string or a URIRef may be used, but safer to always use a URIRef for usage consistency +graph_1_id = URIRef("http://example.com/graph-1") -# Add an empty Graph, identified by graph_1, to the Dataset -d.graph(identifier=graph_1) +# Add an empty Graph, identified by graph_1_id, to the Dataset +d.graph(identifier=graph_1_id) -# Add two quads to Graph graph_1 in the Dataset +# Add two quads to the Dataset which are triples + graph ID +# These insert the triple into the GRaph specified by the ID d.add( ( URIRef("http://example.com/subject-x"), URIRef("http://example.com/predicate-x"), Literal("Triple X"), - graph_1, + graph_1_id, ) ) + d.add( ( URIRef("http://example.com/subject-z"), URIRef("http://example.com/predicate-z"), Literal("Triple Z"), - graph_1, + graph_1_id, ) ) -# Add another quad to the Dataset to a non-existent Graph: -# the Graph is created automatically +# We now have 2 distinct quads in the Dataset to the Dataset has a length of 2 +assert len(d) == 2 + +# Add another quad to the Dataset specifying a non-existent Graph. +# The Graph is created automatically d.add( ( URIRef("http://example.com/subject-y"), @@ -63,8 +80,15 @@ ) ) -# printing the Dataset like this: print(d.serialize(format="trig")) -# produces a result like this: +assert len(d) == 3 + + +# You can print the Dataset like you do a Graph but you must specify a quads format like +# 'trig' or 'trix', not 'turtle', unless the default_union parameter is set to True, and +# then you can print the entire Dataset in triples. +# print(d.serialize(format="trig").strip()) + +# you should see something like this: """ @prefix ex: . @@ -78,85 +102,278 @@ ex:subject-y ex:predicate-y "Triple Y" . } """ -print("Printing Serialised Dataset:") -print("---") -print(d.serialize(format="trig")) -print("---") -print() -print() -# -# Use & Query -# -# print the length of the Dataset, i.e. the count of all triples in all Graphs -# we should get +# Print out one graph in the Dataset, using a standard Graph serialization format - longturtle +print(d.get_graph(URIRef("http://example.com/graph-2")).serialize(format="longturtle")) + +# you should see something like this: """ -3 +PREFIX ex: + +ex:subject-y + ex:predicate-y "Triple Y" ; +. """ -print("Printing Dataset Length:") -print("---") -print(len(d)) -print("---") -print() -print() -# Query one graph in the Dataset for all its triples -# we should get + +####################################################################################### +# 2. Looping & Counting +####################################################################################### + +# Loop through all quads in the dataset +for s, p, o, g in d.quads((None, None, None, None)): # type: ignore[arg-type] + print(f"{s}, {p}, {o}, {g}") + +# you should see something like this: """ -(rdflib.term.URIRef('http://example.com/subject-z'), rdflib.term.URIRef('http://example.com/predicate-z'), rdflib.term.Literal('Triple Z')) -(rdflib.term.URIRef('http://example.com/subject-x'), rdflib.term.URIRef('http://example.com/predicate-x'), rdflib.term.Literal('Triple X')) +http://example.com/subject-z, http://example.com/predicate-z, Triple Z, http://example.com/graph-1 +http://example.com/subject-x, http://example.com/predicate-x, Triple X, http://example.com/graph-1 +http://example.com/subject-y, http://example.com/predicate-y, Triple Y, http://example.com/graph-2 """ -print("Printing all triple from one Graph in the Dataset:") -print("---") -for triple in d.triples((None, None, None, graph_1)): # type: ignore[arg-type] - print(triple) -print("---") -print() -print() -# Query the union of all graphs in the dataset for all triples -# we should get nothing: +# Loop through all the quads in one Graph - just constrain the Graph field +for s, p, o, g in d.quads((None, None, None, graph_1_id)): # type: ignore[arg-type] + print(f"{s}, {p}, {o}, {g}") + +# you should see something like this: """ +http://example.com/subject-x, http://example.com/predicate-x, Triple X, http://example.com/graph-1 +http://example.com/subject-z, http://example.com/predicate-z, Triple Z, http://example.com/graph-1 """ -# A Dataset's default union graph does not exist by default (default_union property is False) -print("Attempt #1 to print all triples in the Dataset:") -print("---") -for triple in d.triples((None, None, None, None)): - print(triple) -print("---") -print() -print() -# Set the Dataset's default_union property to True and re-query +# Looping through triples in one Graph still works too +for s, p, o in d.triples((None, None, None, graph_1_id)): # type: ignore[arg-type] + print(f"{s}, {p}, {o}") + +# you should see something like this: +""" +http://example.com/subject-x, http://example.com/predicate-x, Triple X +http://example.com/subject-z, http://example.com/predicate-z, Triple Z +""" + +# Looping through triples across the whole Dataset will produce nothing +# unless we set the default_union parameter to True, since each triple is in a Named Graph + +# Setting the default_union parameter to True essentially presents all triples in all +# Graphs as a single Graph d.default_union = True -print("Attempt #2 to print all triples in the Dataset:") -print("---") -for triple in d.triples((None, None, None, None)): - print(triple) -print("---") -print() -print() +for s, p, o in d.triples((None, None, None)): + print(f"{s}, {p}, {o}") +# you should see something like this: +""" +http://example.com/subject-x, http://example.com/predicate-x, Triple X +http://example.com/subject-z, http://example.com/predicate-z, Triple Z +http://example.com/subject-y, http://example.com/predicate-y, Triple Y +""" -# -# Remove -# +# You can still loop through all quads now with the default_union parameter to True +for s, p, o, g in d.quads((None, None, None)): + print(f"{s}, {p}, {o}, {g}") + +# you should see something like this: +""" +http://example.com/subject-z, http://example.com/predicate-z, Triple Z, http://example.com/graph-1 +http://example.com/subject-x, http://example.com/predicate-x, Triple X, http://example.com/graph-1 +http://example.com/subject-y, http://example.com/predicate-y, Triple Y, http://example.com/graph-2 +""" + +# Adding a triple in graph-1 to graph-2 increases the number of distinct of quads in +# the Dataset +d.add( + ( + URIRef("http://example.com/subject-z"), + URIRef("http://example.com/predicate-z"), + Literal("Triple Z"), + URIRef("http://example.com/graph-2"), + ) +) + +for s, p, o, g in d.quads((None, None, None, None)): + print(f"{s}, {p}, {o}, {g}") + +# you should see something like this, with the 'Z' triple in graph-1 and graph-2: +""" +http://example.com/subject-x, http://example.com/predicate-x, Triple X, http://example.com/graph-1 +http://example.com/subject-y, http://example.com/predicate-y, Triple Y, http://example.com/graph-2 +http://example.com/subject-z, http://example.com/predicate-z, Triple Z, http://example.com/graph-1 +http://example.com/subject-z, http://example.com/predicate-z, Triple Z, http://example.com/graph-2 +""" + +# but the 'length' of the Dataset is still only 3 as only distinct triples are counted +assert len(d) == 3 + + +# Looping through triples sees the 'Z' triple only once +for s, p, o in d.triples((None, None, None)): + print(f"{s}, {p}, {o}") + +# you should see something like this: +""" +http://example.com/subject-x, http://example.com/predicate-x, Triple X +http://example.com/subject-z, http://example.com/predicate-z, Triple Z +http://example.com/subject-y, http://example.com/predicate-y, Triple Y +""" + +####################################################################################### +# 3. Manipulating Graphs +####################################################################################### + +# List all the Graphs in the Dataset +for x in d.graphs(): + print(x) + +# this returns the graphs, something like: +""" + a rdfg:Graph;rdflib:storage [a rdflib:Store;rdfs:label 'Memory']. + a rdfg:Graph;rdflib:storage [a rdflib:Store;rdfs:label 'Memory']. + a rdfg:Graph;rdflib:storage [a rdflib:Store;rdfs:label 'Memory']. +""" + +# So try this +for x in d.graphs(): + print(x.identifier) + +# you should see something like this, noting the default, currently empty, graph: +""" +urn:x-rdflib:default +http://example.com/graph-2 +http://example.com/graph-1 +""" -# Remove Graph graph_1 from the Dataset -d.remove_graph(graph_1) +# To add to the default Graph, just add a triple, not a quad, to the Dataset directly +d.add( + ( + URIRef("http://example.com/subject-n"), + URIRef("http://example.com/predicate-n"), + Literal("Triple N"), + ) +) +for s, p, o, g in d.quads((None, None, None, None)): + print(f"{s}, {p}, {o}, {g}") + +# you should see something like this, noting the triple in the default Graph: +""" +http://example.com/subject-z, http://example.com/predicate-z, Triple Z, http://example.com/graph-1 +http://example.com/subject-z, http://example.com/predicate-z, Triple Z, http://example.com/graph-2 +http://example.com/subject-x, http://example.com/predicate-x, Triple X, http://example.com/graph-1 +http://example.com/subject-y, http://example.com/predicate-y, Triple Y, http://example.com/graph-2 +http://example.com/subject-n, http://example.com/predicate-n, Triple N, urn:x-rdflib:default +""" + +# Loop through triples per graph +for x in d.graphs(): + print(x.identifier) + for s, p, o in x.triples((None, None, None)): + print(f"\t{s}, {p}, {o}") -# printing the Dataset like this: print(d.serialize(format="trig")) -# now produces a result like this: +# you should see something like this: +""" +urn:x-rdflib:default + http://example.com/subject-n, http://example.com/predicate-n, Triple N +http://example.com/graph-1 + http://example.com/subject-x, http://example.com/predicate-x, Triple X + http://example.com/subject-z, http://example.com/predicate-z, Triple Z +http://example.com/graph-2 + http://example.com/subject-y, http://example.com/predicate-y, Triple Y + http://example.com/subject-z, http://example.com/predicate-z, Triple Z +""" +# The default_union parameter includes all triples in the Named Graphs and the Default Graph +for s, p, o in d.triples((None, None, None)): + print(f"{s}, {p}, {o}") + +# you should see something like this: +""" +http://example.com/subject-x, http://example.com/predicate-x, Triple X +http://example.com/subject-n, http://example.com/predicate-n, Triple N +http://example.com/subject-z, http://example.com/predicate-z, Triple Z +http://example.com/subject-y, http://example.com/predicate-y, Triple Y """ + +# To remove a graph +d.remove_graph(graph_1_id) + +# To remove the default graph +d.remove_graph(URIRef("urn:x-rdflib:default")) + +# print what's left - one graph, graph-2 +print(d.serialize(format="trig")) + +# you should see something like this: +""" +@prefix ex: . + ex:graph-2 { ex:subject-y ex:predicate-y "Triple Y" . + + ex:subject-z ex:predicate-z "Triple Z" . +} +""" + +# To add a Graph that already exists, you must give it an Identifier or else it will be assigned a Blank Node ID +g_with_id = Graph(identifier=URIRef("http://example.com/graph-3")) +g_with_id.bind("ex", "http://example.com/") + +# Add a distinct triple to the exiting Graph, using Namepspace IRI shortcuts +# g_with_id.bind("ex", "http://example.com/") +g_with_id.add( + ( + URIRef("http://example.com/subject-k"), + URIRef("http://example.com/predicate-k"), + Literal("Triple K"), + ) +) +d.add_graph(g_with_id) +print(d.serialize(format="trig")) + +# you should see something like this: +""" +@prefix ex: . + +ex:graph-3 { + ex:subject_k ex:predicate_k "Triple K" . +} + +ex:graph-2 { + ex:subject-y ex:predicate-y "Triple Y" . + + ex:subject-z ex:predicate-z "Triple Z" . +} +""" + +# If you add a Graph with no specified identifier... +g_no_id = Graph() +g_no_id.bind("ex", "http://example.com/") + +g_no_id.add( + ( + URIRef("http://example.com/subject-l"), + URIRef("http://example.com/predicate-l"), + Literal("Triple L"), + ) +) +d.add_graph(g_no_id) + +# now when we print it, we will see a Graph with a Blank Node id: +print(d.serialize(format="trig")) + +# you should see somthing like this, but with a different Blank Node ID , as this is rebuilt each code execution +""" +@prefix ex: . + +ex:graph-3 { + ex:subject-k ex:predicate-k "Triple K" . +} + +ex:graph-2 { + ex:subject-y ex:predicate-y "Triple Y" . + + ex:subject-z ex:predicate-z "Triple Z" . +} + +_:N9cc8b54c91724e31896da5ce41e0c937 { + ex:subject-l ex:predicate-l "Triple L" . } """ -print("Printing Serialised Dataset after graph_1 removal:") -print("---") -print(d.serialize(format="trig").strip()) -print("---") -print() -print() diff --git a/examples/jsonld_serialization.py b/examples/jsonld_serialization.py index 5bee1a614..dd83d6a5d 100644 --- a/examples/jsonld_serialization.py +++ b/examples/jsonld_serialization.py @@ -1,24 +1,35 @@ """ -JSON-LD is "A JSON-based Serialization for Linked Data" (https://www.w3.org/TR/json-ld/) that RDFLib implements for RDF serialization. +JSON-LD is "A JSON-based Serialization for Linked Data" (https://www.w3.org/TR/json-ld/) +that RDFLib implements for RDF serialization. -This file demonstrated some of the JSON-LD things you can do with RDFLib. Parsing & serializing so far. More to be added later. +This file demonstrated some of the JSON-LD things you can do with RDFLib. Parsing & +serializing so far. More to be added later. Parsing ------- -There are a number of "flavours" of JSON-LD - compact and verbose etc. RDFLib can parse all of these in a normal RDFLib way. + +There are a number of "flavours" of JSON-LD - compact and verbose etc. RDFLib can parse +all of these in a normal RDFLib way. Serialization ------------- -JSON-LD has a number of options for serialization - more than other RDF formats. For example, IRIs within JSON-LD can be compacted down to CURIES when a "context" statment is added to the JSON-LD data that maps identifiers - short codes - to IRIs and namespace IRIs like this: -# here the short code "dcterms" is mapped to the IRI http://purl.org/dc/terms/ and "schema" to https://schema.org/, as per RDFLib's in-build namespace prefixes +JSON-LD has a number of options for serialization - more than other RDF formats. For +example, IRIs within JSON-LD can be compacted down to CURIES when a "context" statement +is added to the JSON-LD data that maps identifiers - short codes - to IRIs and namespace +IRIs like this: -"@context": { - "dct": "http://purl.org/dc/terms/", - "schema": "https://schema.org/" -} +.. code-block:: json + + "@context": { + "dcterms": "http://purl.org/dc/terms/", + "schema": "https://schema.org/" + } + +Here the short code "dcterms" is mapped to the IRI http://purl.org/dc/terms/ and +"schema" to https://schema.org/, as per RDFLib's in-build namespace prefixes. """ # import RDFLib and other things diff --git a/examples/sparqlstore_example.py b/examples/sparqlstore_example.py index 12fe43301..bd1ca7bb1 100644 --- a/examples/sparqlstore_example.py +++ b/examples/sparqlstore_example.py @@ -2,16 +2,53 @@ Simple examples showing how to use the SPARQLStore """ +import sys +from urllib.request import urlopen + from rdflib import Graph, Namespace, URIRef -from rdflib.plugins.stores.sparqlstore import SPARQLStore -from rdflib.term import Identifier +from rdflib.namespace import RDF, SKOS +from rdflib.plugins.stores.sparqlstore import SPARQLStore, SPARQLUpdateStore +from rdflib.term import Identifier, Literal + +# Shows examples of the useage of SPARQLStore and SPARQLUpdateStore against local SPARQL1.1 endpoint if +# available. This assumes SPARQL1.1 query/update endpoints running locally at +# http://localhost:3030/db/ +# +# It uses the same endpoint as the test_dataset.py! +# +# For the tests here to run, you can for example start fuseki with: +# ./fuseki-server --mem --update /db + +# THIS WILL ADD DATA TO THE /db dataset + + +HOST = "http://localhost:3030/" if __name__ == "__main__": + try: + assert len(urlopen(HOST).read()) > 0 + except Exception: + print(f"{HOST} is unavailable.") + sys.exit(126) + dbo = Namespace("http://dbpedia.org/ontology/") + dbr = Namespace("http://dbpedia.org/resource/") + + # EXAMPLE Update Store: + update_store = SPARQLUpdateStore( + query_endpoint="http://localhost:3030/db/sparql", + update_endpoint="http://localhost:3030/db/update", + ) + graph = Graph(store=update_store, identifier="http://dbpedia.org/") + graph.add((dbr.Berlin, dbo.populationTotal, Literal(3))) + graph.add((dbr.Brisbane, dbo.populationTotal, Literal(2))) + graph.add((dbr["Category:Capitals_in_Europe"], RDF.type, SKOS.Concept)) + graph.add((dbr["Category:Holy_Grail"], RDF.type, SKOS.Concept)) + graph.add((dbr["Category:Hospital_ships_of_Japan"], RDF.type, SKOS.Concept)) - # EXAMPLE 1: using a Graph with the Store type string set to "SPARQLStore" + # EXAMPLE Store 1: using a Graph with the Store type string set to "SPARQLStore" graph = Graph("SPARQLStore", identifier="http://dbpedia.org/") - graph.open("http://dbpedia.org/sparql") + graph.open("http://localhost:3030/db/sparql") pop = graph.value(URIRef("http://dbpedia.org/resource/Berlin"), dbo.populationTotal) assert isinstance(pop, Identifier) @@ -23,25 +60,35 @@ ) print() - # EXAMPLE 2: using a SPARQLStore object directly - st = SPARQLStore(query_endpoint="http://dbpedia.org/sparql") + # EXAMPLE Query 2: using a SPARQLStore object directly + st = SPARQLStore(query_endpoint="http://localhost:3030/db/sparql") for p in st.objects( URIRef("http://dbpedia.org/resource/Brisbane"), dbo.populationTotal ): assert isinstance(p, Identifier) - print( - "According to DBPedia, Brisbane has a population of " "{0}".format(int(p)) - ) + print("According to DBPedia, Brisbane has a population of {0}".format(int(p))) print() - # EXAMPLE 3: doing RDFlib triple navigation using SPARQLStore as a Graph() + # EXAMPLE Query 3: doing RDFlib triple navigation using SPARQLStore as a Graph() print("Triple navigation using SPARQLStore as a Graph():") graph = Graph("SPARQLStore", identifier="http://dbpedia.org/") - graph.open("http://dbpedia.org/sparql") + graph.open("http://localhost:3030/db/sparql") + # we are asking DBPedia for 3 skos:Concept instances + count = 0 + + for s in graph.subjects(predicate=RDF.type, object=SKOS.Concept): + count += 1 + print(f"\t- {s}") + if count >= 3: + break + + # EXAMPLE Query 4: doing RDFlib triple navigation using a Graph() with a SPARQLStore backend + print("Triple navigation using a Graph() with a SPARQLStore backend:") + st = SPARQLStore(query_endpoint="http://localhost:3030/db/sparql") + graph = Graph(store=st) # we are asking DBPedia for 3 skos:Concept instances count = 0 - from rdflib.namespace import RDF, SKOS for s in graph.subjects(predicate=RDF.type, object=SKOS.Concept): count += 1 @@ -49,7 +96,7 @@ if count >= 3: break - # EXAMPLE 4: using a SPARQL endpoint that requires Basic HTTP authentication + # EXAMPLE Store 5: using a SPARQL endpoint that requires Basic HTTP authentication # NOTE: this example won't run since the endpoint isn't live (or real) sparql_store = SPARQLStore( query_endpoint="http://fake-sparql-endpoint.com/repository/x", diff --git a/merged_prs.json b/merged_prs.json new file mode 100644 index 000000000..3a59d972d --- /dev/null +++ b/merged_prs.json @@ -0,0 +1,3939 @@ +[ + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3223", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3223/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3223/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3223/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3223", + "id": 3428695947, + "node_id": "PR_kwDOADL-3s6pNAnb", + "number": 3223, + "title": "[7.x] Fix incorrect deskolemization of literals", + "user": { + "login": "edmondchuc", + "id": 37032744, + "node_id": "MDQ6VXNlcjM3MDMyNzQ0", + "avatar_url": "https://avatars.githubusercontent.com/u/37032744?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/edmondchuc", + "html_url": "https://github.com/edmondchuc", + "followers_url": "https://api.github.com/users/edmondchuc/followers", + "following_url": "https://api.github.com/users/edmondchuc/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/edmondchuc/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/edmondchuc/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/edmondchuc/subscriptions", + "organizations_url": "https://api.github.com/users/edmondchuc/orgs", + "repos_url": "https://api.github.com/users/edmondchuc/repos", + "events_url": "https://api.github.com/users/edmondchuc/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/edmondchuc/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-09-18T05:18:09Z", + "updated_at": "2025-09-18T05:30:22Z", + "closed_at": "2025-09-18T05:30:20Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3223", + "html_url": "https://github.com/RDFLib/rdflib/pull/3223", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3223.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3223.patch", + "merged_at": "2025-09-18T05:30:20Z" + }, + "body": "This is the v7 version of PR https://github.com/RDFLib/rdflib/pull/3127.\r\n\r\n* Fix issue 3126\r\n\r\n* [pre-commit.ci] auto fixes from pre-commit.com hooks\r\n\r\nfor more information, see https://pre-commit.ci\r\n\r\n---------\r\n\r\n\r\n\r\n# Summary of changes\r\n\r\n\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [ ] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [ ] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Created an issue to discuss the change and get in-principle agreement.\r\n - [ ] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [ ] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3223/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3223/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3222", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3222/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3222/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3222/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3222", + "id": 3428459459, + "node_id": "PR_kwDOADL-3s6pMNyn", + "number": 3222, + "title": "Merge 7-maintenance branch into 7.x", + "user": { + "login": "edmondchuc", + "id": 37032744, + "node_id": "MDQ6VXNlcjM3MDMyNzQ0", + "avatar_url": "https://avatars.githubusercontent.com/u/37032744?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/edmondchuc", + "html_url": "https://github.com/edmondchuc", + "followers_url": "https://api.github.com/users/edmondchuc/followers", + "following_url": "https://api.github.com/users/edmondchuc/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/edmondchuc/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/edmondchuc/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/edmondchuc/subscriptions", + "organizations_url": "https://api.github.com/users/edmondchuc/orgs", + "repos_url": "https://api.github.com/users/edmondchuc/repos", + "events_url": "https://api.github.com/users/edmondchuc/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/edmondchuc/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-09-18T03:00:50Z", + "updated_at": "2025-09-18T03:08:39Z", + "closed_at": "2025-09-18T03:08:37Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3222", + "html_url": "https://github.com/RDFLib/rdflib/pull/3222", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3222.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3222.patch", + "merged_at": "2025-09-18T03:08:37Z" + }, + "body": "# Summary of changes\r\n\r\nI am merging in the `7-maintenance` branch after reviewing the current set of v7 branches. The `7.x` branch has branch protection rules enabled and is intended to be long-lived for all future v7 related features and fixes.\r\n\r\n`7-maintenance` branch will be closed after this merge. All future v7 PRs should target `7.x` instead.\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [ ] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [ ] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Created an issue to discuss the change and get in-principle agreement.\r\n - [ ] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [ ] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3222/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3222/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3221", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3221/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3221/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3221/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3221", + "id": 3428294912, + "node_id": "PR_kwDOADL-3s6pLqU1", + "number": 3221, + "title": "[7.x] notation3.py: don't normalize float representation", + "user": { + "login": "edmondchuc", + "id": 37032744, + "node_id": "MDQ6VXNlcjM3MDMyNzQ0", + "avatar_url": "https://avatars.githubusercontent.com/u/37032744?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/edmondchuc", + "html_url": "https://github.com/edmondchuc", + "followers_url": "https://api.github.com/users/edmondchuc/followers", + "following_url": "https://api.github.com/users/edmondchuc/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/edmondchuc/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/edmondchuc/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/edmondchuc/subscriptions", + "organizations_url": "https://api.github.com/users/edmondchuc/orgs", + "repos_url": "https://api.github.com/users/edmondchuc/repos", + "events_url": "https://api.github.com/users/edmondchuc/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/edmondchuc/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 9291256166, + "node_id": "LA_kwDOADL-3s8AAAACKc1RZg", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/7.x", + "name": "7.x", + "color": "95113B", + "default": false, + "description": "" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-09-18T01:31:07Z", + "updated_at": "2025-09-18T04:18:53Z", + "closed_at": "2025-09-18T04:18:51Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3221", + "html_url": "https://github.com/RDFLib/rdflib/pull/3221", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3221.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3221.patch", + "merged_at": "2025-09-18T04:18:51Z" + }, + "body": "# Summary of changes\r\n\r\nCode from PR https://github.com/RDFLib/rdflib/pull/3020 into v7.x.\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [ ] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [ ] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Created an issue to discuss the change and get in-principle agreement.\r\n - [ ] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [ ] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3221/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3221/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3219", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3219/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3219/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3219/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3219", + "id": 3423885690, + "node_id": "PR_kwDOADL-3s6o8vSy", + "number": 3219, + "title": "Allow lxml 6", + "user": { + "login": "jhgit", + "id": 772518, + "node_id": "MDQ6VXNlcjc3MjUxOA==", + "avatar_url": "https://avatars.githubusercontent.com/u/772518?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/jhgit", + "html_url": "https://github.com/jhgit", + "followers_url": "https://api.github.com/users/jhgit/followers", + "following_url": "https://api.github.com/users/jhgit/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/jhgit/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/jhgit/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/jhgit/subscriptions", + "organizations_url": "https://api.github.com/users/jhgit/orgs", + "repos_url": "https://api.github.com/users/jhgit/repos", + "events_url": "https://api.github.com/users/jhgit/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/jhgit/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-09-16T22:06:35Z", + "updated_at": "2025-09-17T01:52:22Z", + "closed_at": "2025-09-17T01:52:22Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3219", + "html_url": "https://github.com/RDFLib/rdflib/pull/3219", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3219.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3219.patch", + "merged_at": "2025-09-17T01:52:22Z" + }, + "body": "rdflib builds with lxml 6.0.1 - the current latest release.\r\n\r\nFixes #3220\r\n\r\n\r\n\r\n# Summary of changes\r\n\r\nlxml is at 6.0.1. rdflib 7.1.4 builds with that version of lxml. Update pypproject.toml accordingly. Tested locally with python 3.9 and 3.11.\r\n\r\n# Checklist\r\n\r\n- [x] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [x] Checked that all tests and type checking passes (same pytest tests pass or fail with lxml5 as lxml6).\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [x] Considered adding additional documentation. (didn't see any documentation that needed updating)\r\n- [x] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3219/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3219/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3218", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3218/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3218/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3218/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3218", + "id": 3420409710, + "node_id": "PR_kwDOADL-3s6oxCzU", + "number": 3218, + "title": "ci: fix firejail command for poetry 2.1.0", + "user": { + "login": "edmondchuc", + "id": 37032744, + "node_id": "MDQ6VXNlcjM3MDMyNzQ0", + "avatar_url": "https://avatars.githubusercontent.com/u/37032744?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/edmondchuc", + "html_url": "https://github.com/edmondchuc", + "followers_url": "https://api.github.com/users/edmondchuc/followers", + "following_url": "https://api.github.com/users/edmondchuc/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/edmondchuc/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/edmondchuc/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/edmondchuc/subscriptions", + "organizations_url": "https://api.github.com/users/edmondchuc/orgs", + "repos_url": "https://api.github.com/users/edmondchuc/repos", + "events_url": "https://api.github.com/users/edmondchuc/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/edmondchuc/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-09-16T05:06:40Z", + "updated_at": "2025-09-16T05:44:53Z", + "closed_at": "2025-09-16T05:44:52Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3218", + "html_url": "https://github.com/RDFLib/rdflib/pull/3218", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3218.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3218.patch", + "merged_at": "2025-09-16T05:44:52Z" + }, + "body": "# Summary of changes\r\n\r\nIncrementally bumping poetry from v2.0.0 to see which patch/minor version breaks the CI.\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [ ] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [ ] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Created an issue to discuss the change and get in-principle agreement.\r\n - [ ] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [ ] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3218/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3218/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3217", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3217/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3217/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3217/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3217", + "id": 3416326911, + "node_id": "PR_kwDOADL-3s6ojScX", + "number": 3217, + "title": "build(deps): bump library/python from `8220cce` to `58c30f5` in /docker/latest", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4545133062, + "node_id": "LA_kwDOADL-3s8AAAABDuk6Bg", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/docker", + "name": "docker", + "color": "21ceff", + "default": false, + "description": "Pull requests that update Docker code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 3, + "created_at": "2025-09-15T05:14:09Z", + "updated_at": "2025-09-16T03:00:23Z", + "closed_at": "2025-09-16T02:59:34Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3217", + "html_url": "https://github.com/RDFLib/rdflib/pull/3217", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3217.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3217.patch", + "merged_at": "2025-09-16T02:59:34Z" + }, + "body": "Bumps library/python from `8220cce` to `58c30f5`.\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=library/python&package-manager=docker&previous-version=3.13.7-slim&new-version=3.13.7-slim)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once it's up-to-date and CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3217/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3217/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3216", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3216/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3216/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3216/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3216", + "id": 3416322658, + "node_id": "PR_kwDOADL-3s6ojRf8", + "number": 3216, + "title": "build(deps): bump library/python from `8220cce` to `58c30f5` in /docker/unstable", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4545133062, + "node_id": "LA_kwDOADL-3s8AAAABDuk6Bg", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/docker", + "name": "docker", + "color": "21ceff", + "default": false, + "description": "Pull requests that update Docker code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 3, + "created_at": "2025-09-15T05:12:27Z", + "updated_at": "2025-09-16T02:47:32Z", + "closed_at": "2025-09-16T02:46:16Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3216", + "html_url": "https://github.com/RDFLib/rdflib/pull/3216", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3216.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3216.patch", + "merged_at": "2025-09-16T02:46:15Z" + }, + "body": "Bumps library/python from `8220cce` to `58c30f5`.\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=library/python&package-manager=docker&previous-version=3.13.7-slim&new-version=3.13.7-slim)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once it's up-to-date and CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3216/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3216/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3214", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3214/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3214/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3214/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3214", + "id": 3416315331, + "node_id": "PR_kwDOADL-3s6ojP3g", + "number": 3214, + "title": "build(deps-dev): bump mkdocstrings from 0.29.1 to 0.30.0", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 1, + "created_at": "2025-09-15T05:09:22Z", + "updated_at": "2025-09-16T01:23:50Z", + "closed_at": "2025-09-16T01:23:49Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3214", + "html_url": "https://github.com/RDFLib/rdflib/pull/3214", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3214.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3214.patch", + "merged_at": "2025-09-16T01:23:49Z" + }, + "body": "Bumps [mkdocstrings](https://github.com/mkdocstrings/mkdocstrings) from 0.29.1 to 0.30.0.\n
\nRelease notes\n

Sourced from mkdocstrings's releases.

\n
\n

0.30.0

\n

0.30.0 - 2025-07-23

\n

Compare with 0.29.1

\n

Features

\n
    \n
  • Add data-skip-inventory boolean attribute for elements to skip registration in local inventory (f856160 by Bartosz S\u0142awecki). Issue-671, PR-774
  • \n
  • Add I18N support (translations) (2b4ed54 by Nyuan Zhang). PR-645, Co-authored-by: Timoth\u00e9e Mazzucotelli dev@pawamoy.fr
  • \n
\n
\n
\n
\nChangelog\n

Sourced from mkdocstrings's changelog.

\n
\n

0.30.0 - 2025-07-23

\n

Compare with 0.29.1

\n

Features

\n
    \n
  • Add data-skip-inventory boolean attribute for elements to skip registration in local inventory (f856160 by Bartosz S\u0142awecki). Issue-671, PR-774
  • \n
  • Add I18N support (translations) (2b4ed54 by Nyuan Zhang). PR-645, Co-authored-by: Timoth\u00e9e Mazzucotelli dev@pawamoy.fr
  • \n
\n
\n
\n
\nCommits\n
    \n
  • 2be445f chore: Prepare release 0.30.0
  • \n
  • f856160 feat: Add data-skip-inventory boolean attribute for elements to skip regist...
  • \n
  • 2b4ed54 feat: Add I18N support (translations)
  • \n
  • 51f217f chore: Template upgrade
  • \n
  • b1da3d0 ci: Ignore Ruff warnings
  • \n
  • d5bf4e1 docs: Update link to YAML idiosyncrasies
  • \n
  • See full diff in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mkdocstrings&package-manager=pip&previous-version=0.29.1&new-version=0.30.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3214/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3214/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3213", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3213/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3213/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3213/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3213", + "id": 3416314480, + "node_id": "PR_kwDOADL-3s6ojPr0", + "number": 3213, + "title": "build(deps-dev): bump ruff from 0.8.6 to 0.13.0", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-09-15T05:09:01Z", + "updated_at": "2025-09-16T02:11:02Z", + "closed_at": "2025-09-16T02:10:33Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3213", + "html_url": "https://github.com/RDFLib/rdflib/pull/3213", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3213.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3213.patch", + "merged_at": "2025-09-16T02:10:32Z" + }, + "body": "Bumps [ruff](https://github.com/astral-sh/ruff) from 0.8.6 to 0.13.0.\n
\nRelease notes\n

Sourced from ruff's releases.

\n
\n

0.13.0

\n

Release Notes

\n

Check out the blog post for a migration guide and overview of the changes!

\n

Breaking changes

\n
    \n
  • \n

    Several rules can now add from __future__ import annotations automatically

    \n

    TC001, TC002, TC003, RUF013, and UP037 now add from __future__ import annotations as part of their fixes when the lint.future-annotations setting is enabled. This allows the rules to move more imports into TYPE_CHECKING blocks (TC001, TC002, and TC003), use PEP 604 union syntax on Python versions before 3.10 (RUF013), and unquote more annotations (UP037).

    \n
  • \n
  • \n

    Full module paths are now used to verify first-party modules

    \n

    Ruff now checks that the full path to a module exists on disk before categorizing it as a first-party import. This change makes first-party import detection more accurate, helping to avoid false positives on local directories with the same name as a third-party dependency, for example. See the FAQ section on import categorization for more details.

    \n
  • \n
  • \n

    Deprecated rules must now be selected by exact rule code

    \n

    Ruff will no longer activate deprecated rules selected by their group name or prefix. As noted below, the two remaining deprecated rules were also removed in this release, so this won't affect any current rules, but it will still affect any deprecations in the future.

    \n
  • \n
  • \n

    The deprecated macOS configuration directory fallback has been removed

    \n

    Ruff will no longer look for a user-level configuration file at ~/Library/Application Support/ruff/ruff.toml on macOS. This feature was deprecated in v0.5 in favor of using the XDG specification (usually resolving to ~/.config/ruff/ruff.toml), like on Linux. The fallback and accompanying deprecation warning have now been removed.

    \n
  • \n
\n

Removed Rules

\n

The following rules have been removed:

\n\n

Stabilization

\n

The following rules have been stabilized and are no longer in preview:

\n\n

The following behaviors have been stabilized:

\n\n
\n

... (truncated)

\n
\n
\nChangelog\n

Sourced from ruff's changelog.

\n
\n

0.13.0

\n

Check out the blog post for a migration\nguide and overview of the changes!

\n

Breaking changes

\n
    \n
  • \n

    Several rules can now add from __future__ import annotations automatically

    \n

    TC001, TC002, TC003, RUF013, and UP037 now add from __future__ import annotations as part of their fixes when the\nlint.future-annotations setting is enabled. This allows the rules to move\nmore imports into TYPE_CHECKING blocks (TC001, TC002, and TC003),\nuse PEP 604 union syntax on Python versions before 3.10 (RUF013), and\nunquote more annotations (UP037).

    \n
  • \n
  • \n

    Full module paths are now used to verify first-party modules

    \n

    Ruff now checks that the full path to a module exists on disk before\ncategorizing it as a first-party import. This change makes first-party\nimport detection more accurate, helping to avoid false positives on local\ndirectories with the same name as a third-party dependency, for example. See\nthe FAQ\nsection on import categorization for more details.

    \n
  • \n
  • \n

    Deprecated rules must now be selected by exact rule code

    \n

    Ruff will no longer activate deprecated rules selected by their group name\nor prefix. As noted below, the two remaining deprecated rules were also\nremoved in this release, so this won't affect any current rules, but it will\nstill affect any deprecations in the future.

    \n
  • \n
  • \n

    The deprecated macOS configuration directory fallback has been removed

    \n

    Ruff will no longer look for a user-level configuration file at\n~/Library/Application Support/ruff/ruff.toml on macOS. This feature was\ndeprecated in v0.5 in favor of using the XDG\nspecification\n(usually resolving to ~/.config/ruff/ruff.toml), like on Linux. The\nfallback and accompanying deprecation warning have now been removed.

    \n
  • \n
\n

Removed Rules

\n

The following rules have been removed:

\n\n

Stabilization

\n

The following rules have been stabilized and are no longer in preview:

\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • a1fdd66 Bump 0.13.0 (#20336)
  • \n
  • 8770b95 [ty] introduce DivergentType (#20312)
  • \n
  • 65982a1 [ty] Use 'unknown' specialization for upper bound on Self (#20325)
  • \n
  • 57d1f71 [ty] Simplify unions of enum literals and subtypes thereof (#20324)
  • \n
  • 7a75702 Ignore deprecated rules unless selected by exact code (#20167)
  • \n
  • 9ca632c Stabilize adding future import via config option (#20277)
  • \n
  • 64fe7d3 [flake8-errmsg] Stabilize extending raw-string-in-exception (EM101) to ...
  • \n
  • beeeb8d Stabilize the remaining Airflow rules (#20250)
  • \n
  • b6fca52 [flake8-bugbear] Stabilize support for non-context-manager calls in `assert...
  • \n
  • ac7f882 [flake8-commas] Stabilize support for trailing comma checks in type paramet...
  • \n
  • Additional commits viewable in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ruff&package-manager=pip&previous-version=0.8.6&new-version=0.13.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3213/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3213/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3211", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3211/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3211/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3211/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3211", + "id": 3416312512, + "node_id": "PR_kwDOADL-3s6ojPQZ", + "number": 3211, + "title": "build(deps-dev): bump pip-tools from 7.4.1 to 7.5.0", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 3, + "created_at": "2025-09-15T05:08:08Z", + "updated_at": "2025-09-16T01:36:07Z", + "closed_at": "2025-09-16T01:35:09Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3211", + "html_url": "https://github.com/RDFLib/rdflib/pull/3211", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3211.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3211.patch", + "merged_at": "2025-09-16T01:35:09Z" + }, + "body": "Bumps [pip-tools](https://github.com/jazzband/pip-tools) from 7.4.1 to 7.5.0.\n
\nRelease notes\n

Sourced from pip-tools's releases.

\n
\n

v7.5.0

\n

2025-07-30

\n

Bug fixes

\n
    \n
  • \n

    Fixed the ordering of format controls to preserve underlying pip behavior -- by @\u200bsethmlarson.

    \n

    PRs and issues: #2082

    \n
  • \n
  • \n

    Fixed NoCandidateFound exception to be compatible with pip >= 24.1 -- by @\u200bchrysle.

    \n

    PRs and issues: #2083

    \n
  • \n
  • \n

    pip-compile now produces relative paths for editable dependencies -- by @\u200bmacro1.

    \n

    PRs and issues: #2087

    \n
  • \n
  • \n

    Fixed crash failures due to incompatibility with pip >= 25.1 -- by @\u200bgkreitz and @\u200bsirosen.

    \n

    PRs and issues: #2176, #2178

    \n
  • \n
\n

Features

\n
    \n
  • \n

    pip-compile now treats package versions requested on the command line as constraints for the underlying pip usage.\nThis applies to build deps in addition to normal package requirements.

    \n

    -- by @\u200bchrysle

    \n

    PRs and issues: #2106

    \n
  • \n
  • \n

    pip-tools now tests on and officially supports Python 3.12 -- by @\u200bsirosen.

    \n

    PRs and issues: #2188

    \n
  • \n
  • \n

    Requirements file paths in pip-compile output are now normalized to POSIX-style, even when pip-compile is run on Windows.\nThis provides more consistent output across various platforms.

    \n

    -- by @\u200bsirosen

    \n

    PRs and issues: #2195

    \n
  • \n
  • \n

    pip-tools now tests against and supports pip up to version 25.1 -- by @\u200bsirosen.

    \n

    PRs and issues: #2195

    \n
  • \n
\n

Removals and backward incompatible breaking changes

\n
    \n
  • pip-compile will now relativize the requirements paths which are recorded in its output.\nPaths are made relative to the working directory.\nThis provides more consistent results across pip versions.
  • \n
\n\n
\n

... (truncated)

\n
\n
\nChangelog\n

Sourced from pip-tools's changelog.

\n
\n

v7.5.0

\n

2025-07-30

\n

Bug fixes

\n
    \n
  • \n

    Fixed the ordering of format controls to preserve underlying pip behavior\n-- by {user}sethmlarson.

    \n

    PRs and issues: {issue}2082

    \n
  • \n
  • \n

    Fixed NoCandidateFound exception to be compatible with pip >= 24.1\n-- by {user}chrysle.

    \n

    PRs and issues: {issue}2083

    \n
  • \n
  • \n

    pip-compile now produces relative paths for editable dependencies\n-- by {user}macro1.

    \n

    PRs and issues: {issue}2087

    \n
  • \n
  • \n

    Fixed crash failures due to incompatibility with pip >= 25.1\n-- by {user}gkreitz and {user}sirosen.

    \n

    PRs and issues: {issue}2176, {issue}2178

    \n
  • \n
\n

Features

\n
    \n
  • \n

    pip-compile now treats package versions requested on the command line as\nconstraints for the underlying pip usage.\nThis applies to build deps in addition to normal package requirements.

    \n

    -- by {user}chrysle

    \n

    PRs and issues: {issue}2106

    \n
  • \n
  • \n

    pip-tools now tests on and officially supports Python 3.12\n-- by {user}sirosen.

    \n

    PRs and issues: {issue}2188

    \n
  • \n
  • \n

    Requirements file paths in pip-compile output are now normalized to\nPOSIX-style, even when pip-compile is run on Windows.\nThis provides more consistent output across various platforms.

    \n

    -- by {user}sirosen

    \n

    PRs and issues: {issue}2195

    \n
  • \n
  • \n

    pip-tools now tests against and supports pip up to version 25.1

    \n
  • \n
\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • debe5a4 Update changelog for version 7.5.0
  • \n
  • 1c7d9fb Merge pull request #2210 from webknjaz/bugfixes/release-env-context-access
  • \n
  • 96ed4d2 Merge pull request #2209 from webknjaz/maintenance/release-attestations-cleanup
  • \n
  • a180dd9 \ud83d\udcdd Link the PR #2209 change note to PR #2149
  • \n
  • 7f9512a \ud83d\udcdd Link the PR #2210 change note to PR #2149
  • \n
  • 396da33 Run the dist build job in PRs
  • \n
  • 7b1c22c Fix accessing repo id in the release workflow
  • \n
  • 05daad6 Drop release attestations for Jazzband upload
  • \n
  • b4ddd75 Merge pull request #2203 from sirosen/use-towncrier
  • \n
  • a136172 Add a run of 'changelog-draft' to QA CI jobs
  • \n
  • Additional commits viewable in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pip-tools&package-manager=pip&previous-version=7.4.1&new-version=7.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3211/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3211/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3210", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3210/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3210/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3210/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3210", + "id": 3415928342, + "node_id": "PR_kwDOADL-3s6oh7Eb", + "number": 3210, + "title": "chore: address dependabot security vulnerabilities", + "user": { + "login": "edmondchuc", + "id": 37032744, + "node_id": "MDQ6VXNlcjM3MDMyNzQ0", + "avatar_url": "https://avatars.githubusercontent.com/u/37032744?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/edmondchuc", + "html_url": "https://github.com/edmondchuc", + "followers_url": "https://api.github.com/users/edmondchuc/followers", + "following_url": "https://api.github.com/users/edmondchuc/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/edmondchuc/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/edmondchuc/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/edmondchuc/subscriptions", + "organizations_url": "https://api.github.com/users/edmondchuc/orgs", + "repos_url": "https://api.github.com/users/edmondchuc/repos", + "events_url": "https://api.github.com/users/edmondchuc/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/edmondchuc/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 1, + "created_at": "2025-09-15T01:24:49Z", + "updated_at": "2025-09-16T03:18:21Z", + "closed_at": "2025-09-16T03:18:19Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3210", + "html_url": "https://github.com/RDFLib/rdflib/pull/3210", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3210.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3210.patch", + "merged_at": "2025-09-16T03:18:19Z" + }, + "body": "# Summary of changes\r\n\r\n- Upgrade [urllib3](https://pypi.org/project/urllib3/) to `2.5.0`\r\n - https://github.com/RDFLib/rdflib/security/dependabot/25\r\n - https://github.com/RDFLib/rdflib/security/dependabot/27\r\n- Upgrade [requests](https://pypi.org/project/requests/) to `2.32.5`\r\n - https://github.com/RDFLib/rdflib/security/dependabot/24\r\n\r\n\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [ ] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [ ] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Created an issue to discuss the change and get in-principle agreement.\r\n - [ ] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [ ] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3210/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3210/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3209", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3209/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3209/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3209/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3209", + "id": 3392612128, + "node_id": "PR_kwDOADL-3s6nTQkG", + "number": 3209, + "title": "build(deps-dev): bump coverage from 7.8.2 to 7.10.6", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 1, + "created_at": "2025-09-08T05:03:55Z", + "updated_at": "2025-09-12T03:48:06Z", + "closed_at": "2025-09-12T03:48:04Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3209", + "html_url": "https://github.com/RDFLib/rdflib/pull/3209", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3209.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3209.patch", + "merged_at": "2025-09-12T03:48:04Z" + }, + "body": "Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.8.2 to 7.10.6.\n
\nChangelog\n

Sourced from coverage's changelog.

\n
\n

Version 7.10.6 \u2014 2025-08-29

\n
    \n
  • \n

    Fix: source directories were not properly communicated to subprocesses\nthat ran in different directories, as reported in issue 1499_. This is now\nfixed.

    \n
  • \n
  • \n

    Performance: Alex Gaynor continues fine-tuning <pull 2038_>_ the speed of\ncombination, especially with many contexts.

    \n
  • \n
\n

.. _issue 1499: nedbat/coveragepy#1499\n.. _pull 2038: nedbat/coveragepy#2038

\n

.. _changes_7-10-5:

\n

Version 7.10.5 \u2014 2025-08-23

\n
    \n
  • Big speed improvements for coverage combine: it's now about twice as\nfast! Huge thanks to Alex Gaynor for pull requests 2032 <pull 2032_>,\n2033 <pull 2033_>, and 2034 <pull 2034_>_.
  • \n
\n

.. _pull 2032: nedbat/coveragepy#2032\n.. _pull 2033: nedbat/coveragepy#2033\n.. _pull 2034: nedbat/coveragepy#2034

\n

.. _changes_7-10-4:

\n

Version 7.10.4 \u2014 2025-08-16

\n
    \n
  • \n

    Added patch = fork for times when the built-in forking support is\ninsufficient.

    \n
  • \n
  • \n

    Fix: patch = execv also inherits the entire coverage configuration now.

    \n
  • \n
\n

.. _changes_7-10-3:

\n

Version 7.10.3 \u2014 2025-08-10

\n
    \n
  • \n

    Fixes for patch = subprocess:

    \n
      \n
    • \n

      If subprocesses spawned yet more subprocesses simultaneously, some coverage\ncould be missed. This is now fixed, closing issue 2024_.

      \n
    • \n
    • \n

      If subprocesses were created in other directories, their data files were

      \n
    • \n
    \n
  • \n
\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • 88c55ff docs: sample HTML for 7.10.6
  • \n
  • 01d8995 docs: prep for 7.10.6
  • \n
  • 9b0c24f docs: thanks Alex #2038
  • \n
  • 66d6910 fix: make source paths absolute where they exist. #1499
  • \n
  • bb3382f build: no need for the combine/html times now
  • \n
  • 9ea349a lab: warn_executed.py
  • \n
  • 808c9b4 build: changing metacov.ini should trigger metacov
  • \n
  • 384f5f2 build: oops, some 'if's are really line pragmas
  • \n
  • a7224af perf: pre-compute the mapping between other_db.context and main.context (#2038)
  • \n
  • 5c00c5b chore: bump the action-dependencies group with 3 updates (#2039)
  • \n
  • Additional commits viewable in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coverage&package-manager=pip&previous-version=7.8.2&new-version=7.10.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3209/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3209/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3208", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3208/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3208/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3208/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3208", + "id": 3392611610, + "node_id": "PR_kwDOADL-3s6nTQc1", + "number": 3208, + "title": "build(deps-dev): bump mkdocs-material from 9.6.14 to 9.6.19", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-09-08T05:03:41Z", + "updated_at": "2025-09-12T04:00:23Z", + "closed_at": "2025-09-12T03:59:59Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3208", + "html_url": "https://github.com/RDFLib/rdflib/pull/3208", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3208.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3208.patch", + "merged_at": "2025-09-12T03:59:59Z" + }, + "body": "Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.6.14 to 9.6.19.\n
\nRelease notes\n

Sourced from mkdocs-material's releases.

\n
\n

mkdocs-material-9.6.19

\n
    \n
  • Added support for Python 3.14
  • \n
  • Updated Bahasa Malaysia translations
  • \n
\n

mkdocs-material-9.6.18

\n
    \n
  • Updated Azerbaijani translations
  • \n
  • Fixed last compat issues with minijinja, now 100% compatible
  • \n
\n

mkdocs-material-9.6.17

\n
    \n
  • Fixed #8396: Videos do not autoplay when inside a content tab
  • \n
  • Fixed #8394: Stroke width not effective in Mermaid.js diagrams
  • \n
  • Fixed disappearing version selector when hiding page title
  • \n
\n

mkdocs-material-9.6.16

\n
    \n
  • Fixed #8349: Info plugin doesn't correctly detect virtualenv in some cases
  • \n
  • Fixed #8334: Find-in-page detects matches in hidden search result list
  • \n
\n

mkdocs-material-9.6.15

\n
    \n
  • Updated Mongolian translations
  • \n
  • Improved semantic markup of "edit this page" button
  • \n
  • Improved info plugin virtual environment resolution
  • \n
  • Fixed #8291: Large font size setting throws of breakpoints in JavaScript
  • \n
\n
\n
\n
\nChangelog\n

Sourced from mkdocs-material's changelog.

\n
\n

mkdocs-material-9.6.19 (2025-09-07)

\n
    \n
  • Added support for Python 3.14
  • \n
  • Updated Bahasa Malaysia translations
  • \n
\n

mkdocs-material-9.6.18 (2025-08-22)

\n
    \n
  • Updated Azerbaijani translations
  • \n
  • Fixed last compat issues with [minijinja], now 100% compatible
  • \n
\n

mkdocs-material-9.6.17 (2025-08-15)

\n
    \n
  • Fixed #8396: Videos do not autoplay when inside a content tab
  • \n
  • Fixed #8394: Stroke width not effective in Mermaid.js diagrams
  • \n
  • Fixed disappearing version selector when hiding page title
  • \n
\n

mkdocs-material-9.6.16 (2025-07-26)

\n
    \n
  • Fixed #8349: Info plugin doesn't correctly detect virtualenv in some cases
  • \n
  • Fixed #8334: Find-in-page detects matches in hidden search result list
  • \n
\n

mkdocs-material-9.6.15 (2025-07-01)

\n
    \n
  • Updated Mongolian translations
  • \n
  • Improved semantic markup of "edit this page" button
  • \n
  • Improved info plugin virtual environment resolution
  • \n
  • Fixed #8291: Large font size setting throws of breakpoints in JavaScript
  • \n
\n

mkdocs-material-9.6.14 (2025-05-13)

\n
    \n
  • Fixed #8215: Social plugin crashes when CairoSVG is updated to 2.8
  • \n
\n

mkdocs-material-9.6.13 (2025-05-10)

\n
    \n
  • Fixed #8204: Annotations showing list markers in print view
  • \n
  • Fixed #8153: Improve style of cardinality symbols in Mermaid.js ER diagrams
  • \n
\n

mkdocs-material-9.6.12 (2025-04-17)

\n
    \n
  • Fixed #8158: Flip footnote back reference icon for right-to-left languages
  • \n
\n

mkdocs-material-9.6.11 (2025-04-01)

\n
    \n
  • Updated Docker image to latest Alpine Linux
  • \n
  • Bump required Jinja version to 3.1
  • \n
  • Fixed #8133: Jinja filter items not available (9.6.10 regression)
  • \n
  • Fixed #8128: Search plugin not entirely disabled via enabled setting
  • \n
\n

mkdocs-material-9.6.10 (2025-03-30)

\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • 2fe55ee Prepare 9.6.19 release
  • \n
  • c9d5303 Documentation
  • \n
  • 3a0cea1 Bump actions/upload-pages-artifact from 3 to 4
  • \n
  • 3026a57 Bump actions/checkout from 4 to 5
  • \n
  • cb1fc6f Updated dependencies
  • \n
  • 1f3c48e Fixed pillow version range
  • \n
  • 13c9c77 Added pillow 11 to supported version range
  • \n
  • 0d262ec Documentation
  • \n
  • 97ae22f Updated Premium sponsors
  • \n
  • ee6484e Updated Premium sponsors
  • \n
  • Additional commits viewable in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mkdocs-material&package-manager=pip&previous-version=9.6.14&new-version=9.6.19)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3208/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3208/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3207", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3207/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3207/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3207/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3207", + "id": 3392609945, + "node_id": "PR_kwDOADL-3s6nTQFT", + "number": 3207, + "title": "build(deps-dev): bump mkdocs-include-markdown-plugin from 7.1.5 to 7.1.7", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 3, + "created_at": "2025-09-08T05:02:56Z", + "updated_at": "2025-09-12T04:23:57Z", + "closed_at": "2025-09-12T04:23:40Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3207", + "html_url": "https://github.com/RDFLib/rdflib/pull/3207", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3207.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3207.patch", + "merged_at": "2025-09-12T04:23:40Z" + }, + "body": "Bumps [mkdocs-include-markdown-plugin](https://github.com/mondeja/mkdocs-include-markdown-plugin) from 7.1.5 to 7.1.7.\n
\nRelease notes\n

Sourced from mkdocs-include-markdown-plugin's releases.

\n
\n

v7.1.7

\n

Bug fixes

\n
    \n
  • Fix passing negative values to heading-offset argument of include-markdown directive.
  • \n
\n

v7.1.6

\n

Bug fixes

\n
    \n
  • Fix internal anchor in included file incorrectly rewritten.
  • \n
\n
\n
\n
\nCommits\n\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mkdocs-include-markdown-plugin&package-manager=pip&previous-version=7.1.5&new-version=7.1.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3207/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3207/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3206", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3206/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3206/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3206/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3206", + "id": 3392609909, + "node_id": "PR_kwDOADL-3s6nTQEx", + "number": 3206, + "title": "build(deps): bump actions/setup-python from 5 to 6", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4132956439, + "node_id": "LA_kwDOADL-3s72V-kX", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/github_actions", + "name": "github_actions", + "color": "000000", + "default": false, + "description": "Pull requests that update GitHub Actions code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 4, + "created_at": "2025-09-08T05:02:55Z", + "updated_at": "2025-09-12T04:12:29Z", + "closed_at": "2025-09-12T04:11:27Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3206", + "html_url": "https://github.com/RDFLib/rdflib/pull/3206", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3206.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3206.patch", + "merged_at": "2025-09-12T04:11:26Z" + }, + "body": "Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.\n
\nRelease notes\n

Sourced from actions/setup-python's releases.

\n
\n

v6.0.0

\n

What's Changed

\n

Breaking Changes

\n\n

Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. See Release Notes

\n

Enhancements:

\n\n

Bug fixes:

\n\n

Dependency updates:

\n\n

New Contributors

\n\n

Full Changelog: https://github.com/actions/setup-python/compare/v5...v6.0.0

\n

v5.6.0

\n

What's Changed

\n\n

Full Changelog: https://github.com/actions/setup-python/compare/v5...v5.6.0

\n

v5.5.0

\n

What's Changed

\n

Enhancements:

\n\n

Bug fixes:

\n\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • e797f83 Upgrade to node 24 (#1164)
  • \n
  • 3d1e2d2 Revert "Enhance cache-dependency-path handling to support files outside the w...
  • \n
  • 65b0712 Clarify pythonLocation behavior for PyPy and GraalPy in environment variables...
  • \n
  • 5b668cf Bump actions/checkout from 4 to 5 (#1181)
  • \n
  • f62a0e2 Change missing cache directory error to warning (#1182)
  • \n
  • 9322b3c Upgrade setuptools to 78.1.1 to fix path traversal vulnerability in PackageIn...
  • \n
  • fbeb884 Bump form-data to fix critical vulnerabilities #182 & #183 (#1163)
  • \n
  • 03bb615 Bump idna from 2.9 to 3.7 in /tests/data (#843)
  • \n
  • 36da51d Add version parsing from Pipfile (#1067)
  • \n
  • 3c6f142 update documentation (#1156)
  • \n
  • Additional commits viewable in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-python&package-manager=github_actions&previous-version=5&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3206/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3206/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3205", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3205/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3205/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3205/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3205", + "id": 3392609468, + "node_id": "PR_kwDOADL-3s6nTP-k", + "number": 3205, + "title": "build(deps-dev): bump pytest from 8.3.5 to 8.4.2", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-09-08T05:02:44Z", + "updated_at": "2025-09-12T04:35:58Z", + "closed_at": "2025-09-12T04:34:37Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3205", + "html_url": "https://github.com/RDFLib/rdflib/pull/3205", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3205.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3205.patch", + "merged_at": "2025-09-12T04:34:37Z" + }, + "body": "Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.5 to 8.4.2.\n
\nRelease notes\n

Sourced from pytest's releases.

\n
\n

8.4.2

\n

pytest 8.4.2 (2025-09-03)

\n

Bug fixes

\n
    \n
  • \n

    #13478: Fixed a crash when using console_output_style{.interpreted-text role="confval"} with times and a module is skipped.

    \n
  • \n
  • \n

    #13530: Fixed a crash when using pytest.approx{.interpreted-text role="func"} and decimal.Decimal{.interpreted-text role="class"} instances with the decimal.FloatOperation{.interpreted-text role="class"} trap set.

    \n
  • \n
  • \n

    #13549: No longer evaluate type annotations in Python 3.14 when inspecting function signatures.

    \n

    This prevents crashes during module collection when modules do not explicitly use from __future__ import annotations and import types for annotations within a if TYPE_CHECKING: block.

    \n
  • \n
  • \n

    #13559: Added missing [int]{.title-ref} and [float]{.title-ref} variants to the [Literal]{.title-ref} type annotation of the [type]{.title-ref} parameter in pytest.Parser.addini{.interpreted-text role="meth"}.

    \n
  • \n
  • \n

    #13563: pytest.approx{.interpreted-text role="func"} now only imports numpy if NumPy is already in sys.modules. This fixes unconditional import behavior introduced in [8.4.0]{.title-ref}.

    \n
  • \n
\n

Improved documentation

\n
    \n
  • #13577: Clarify that pytest_generate_tests is discovered in test modules/classes; other hooks must be in conftest.py or plugins.
  • \n
\n

Contributor-facing changes

\n
    \n
  • #13480: Self-testing: fixed a few test failures when run with -Wdefault or a similar override.
  • \n
  • #13547: Self-testing: corrected expected message for test_doctest_unexpected_exception in Python 3.14.
  • \n
  • #13684: Make pytest's own testsuite insensitive to the presence of the CI environment variable -- by ogrisel{.interpreted-text role="user"}.
  • \n
\n

8.4.1

\n

pytest 8.4.1 (2025-06-17)

\n

Bug fixes

\n
    \n
  • \n

    #13461: Corrected _pytest.terminal.TerminalReporter.isatty to support\nbeing called as a method. Before it was just a boolean which could\nbreak correct code when using -o log_cli=true).

    \n
  • \n
  • \n

    #13477: Reintroduced pytest.PytestReturnNotNoneWarning{.interpreted-text role="class"} which was removed by accident in pytest [8.4]{.title-ref}.

    \n

    This warning is raised when a test functions returns a value other than None, which is often a mistake made by beginners.

    \n

    See return-not-none{.interpreted-text role="ref"} for more information.

    \n
  • \n
  • \n

    #13497: Fixed compatibility with Twisted 25+.

    \n
  • \n
\n

Improved documentation

\n
    \n
  • #13492: Fixed outdated warning about faulthandler not working on Windows.
  • \n
\n

8.4.0

\n

pytest 8.4.0 (2025-06-02)

\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • bfae422 Prepare release version 8.4.2
  • \n
  • 8990538 Fix passenv CI in tox ini and make tests insensitive to the presence of the C...
  • \n
  • ca676bf Merge pull request #13687 from pytest-dev/patchback/backports/8.4.x/e63f6e51c...
  • \n
  • 975a60a Merge pull request #13686 from pytest-dev/patchback/backports/8.4.x/12bde8af6...
  • \n
  • 7723ce8 Merge pull request #13683 from even-even/fix_Exeption_to_Exception_in_errorMe...
  • \n
  • b7f0568 Merge pull request #13685 from CoretexShadow/fix/docs-pytest-generate-tests
  • \n
  • 2c94c4a add missing colon (#13640) (#13641)
  • \n
  • c3d7684 Merge pull request #13606 from pytest-dev/patchback/backports/8.4.x/5f9938563...
  • \n
  • dc6e3be Merge pull request #13605 from The-Compiler/training-update-2025-07
  • \n
  • f87289c Fix crash with times output style and skipped module (#13573) (#13579)
  • \n
  • Additional commits viewable in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pytest&package-manager=pip&previous-version=8.3.5&new-version=8.4.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3205/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3205/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3204", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3204/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3204/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3204/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3204", + "id": 3392609060, + "node_id": "PR_kwDOADL-3s6nTP41", + "number": 3204, + "title": "build(deps-dev): bump typing-extensions from 4.13.2 to 4.15.0", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 3, + "created_at": "2025-09-08T05:02:32Z", + "updated_at": "2025-09-12T05:00:39Z", + "closed_at": "2025-09-12T04:59:56Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3204", + "html_url": "https://github.com/RDFLib/rdflib/pull/3204", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3204.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3204.patch", + "merged_at": "2025-09-12T04:59:56Z" + }, + "body": "Bumps [typing-extensions](https://github.com/python/typing_extensions) from 4.13.2 to 4.15.0.\n
\nRelease notes\n

Sourced from typing-extensions's releases.

\n
\n

4.15.0

\n

No user-facing changes since 4.15.0rc1.

\n

New features since 4.14.1:

\n
    \n
  • Add the @typing_extensions.disjoint_base decorator, as specified\nin PEP 800. Patch by Jelle Zijlstra.
  • \n
  • Add typing_extensions.type_repr, a backport of\nannotationlib.type_repr,\nintroduced in Python 3.14 (CPython PR #124551,\noriginally by Jelle Zijlstra). Patch by Semyon Moroz.
  • \n
  • Fix behavior of type params in typing_extensions.evaluate_forward_ref. Backport of\nCPython PR #137227 by Jelle Zijlstra.
  • \n
\n

4.15.0rc1

\n
    \n
  • Add the @typing_extensions.disjoint_base decorator, as specified\nin PEP 800. Patch by Jelle Zijlstra.
  • \n
  • Add typing_extensions.type_repr, a backport of\nannotationlib.type_repr,\nintroduced in Python 3.14 (CPython PR #124551,\noriginally by Jelle Zijlstra). Patch by Semyon Moroz.
  • \n
  • Fix behavior of type params in typing_extensions.evaluate_forward_ref. Backport of\nCPython PR #137227 by Jelle Zijlstra.
  • \n
\n

4.14.1

\n

Release 4.14.1 (July 4, 2025)

\n
    \n
  • Fix usage of typing_extensions.TypedDict nested inside other types\n(e.g., typing.Type[typing_extensions.TypedDict]). This is not allowed by the\ntype system but worked on older versions, so we maintain support.
  • \n
\n

4.14.0

\n

This release adds several new features, including experimental support for inline typed dictionaries (PEP 764) and sentinels (PEP 661), and support for changes in Python 3.14. In addition, Python 3.8 is no longer supported.

\n

Changes since 4.14.0rc1:

\n
    \n
  • Remove __or__ and __ror__ methods from typing_extensions.Sentinel\non Python versions <3.10. PEP 604 was introduced in Python 3.10, and\ntyping_extensions does not generally attempt to backport PEP-604 methods\nto prior versions.
  • \n
  • Further update typing_extensions.evaluate_forward_ref with changes in Python 3.14.
  • \n
\n

Changes included in 4.14.0rc1:

\n
    \n
  • Drop support for Python 3.8 (including PyPy-3.8). Patch by Victorien Plot.
  • \n
  • Do not attempt to re-export names that have been removed from typing,\nanticipating the removal of typing.no_type_check_decorator in Python 3.15.\nPatch by Jelle Zijlstra.
  • \n
  • Update typing_extensions.Format, typing_extensions.evaluate_forward_ref, and\ntyping_extensions.TypedDict to align
  • \n
\n\n
\n

... (truncated)

\n
\n
\nChangelog\n

Sourced from typing-extensions's changelog.

\n
\n

Release 4.15.0 (August 25, 2025)

\n

No user-facing changes since 4.15.0rc1.

\n

Release 4.15.0rc1 (August 18, 2025)

\n
    \n
  • Add the @typing_extensions.disjoint_base decorator, as specified\nin PEP 800. Patch by Jelle Zijlstra.
  • \n
  • Add typing_extensions.type_repr, a backport of\nannotationlib.type_repr,\nintroduced in Python 3.14 (CPython PR #124551,\noriginally by Jelle Zijlstra). Patch by Semyon Moroz.
  • \n
  • Fix behavior of type params in typing_extensions.evaluate_forward_ref. Backport of\nCPython PR #137227 by Jelle Zijlstra.
  • \n
\n

Release 4.14.1 (July 4, 2025)

\n
    \n
  • Fix usage of typing_extensions.TypedDict nested inside other types\n(e.g., typing.Type[typing_extensions.TypedDict]). This is not allowed by the\ntype system but worked on older versions, so we maintain support.
  • \n
\n

Release 4.14.0 (June 2, 2025)

\n

Changes since 4.14.0rc1:

\n
    \n
  • Remove __or__ and __ror__ methods from typing_extensions.Sentinel\non Python versions <3.10. PEP 604 was introduced in Python 3.10, and\ntyping_extensions does not generally attempt to backport PEP-604 methods\nto prior versions.
  • \n
  • Further update typing_extensions.evaluate_forward_ref with changes in Python 3.14.
  • \n
\n

Release 4.14.0rc1 (May 24, 2025)

\n
    \n
  • Drop support for Python 3.8 (including PyPy-3.8). Patch by Victorien Plot.
  • \n
  • Do not attempt to re-export names that have been removed from typing,\nanticipating the removal of typing.no_type_check_decorator in Python 3.15.\nPatch by Jelle Zijlstra.
  • \n
  • Update typing_extensions.Format, typing_extensions.evaluate_forward_ref, and\ntyping_extensions.TypedDict to align\nwith changes in Python 3.14. Patches by Jelle Zijlstra.
  • \n
  • Fix tests for Python 3.14 and 3.15. Patches by Jelle Zijlstra.
  • \n
\n

New features:

\n
    \n
  • Add support for inline typed dictionaries (PEP 764).\nPatch by Victorien Plot.
  • \n
  • Add typing_extensions.Reader and typing_extensions.Writer. Patch by\nSebastian Rittau.
  • \n
  • Add support for sentinels (PEP 661). Patch by\nVictorien Plot.
  • \n
\n
\n
\n
\nCommits\n\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typing-extensions&package-manager=pip&previous-version=4.13.2&new-version=4.15.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3204/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3204/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3203", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3203/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3203/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3203/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3203", + "id": 3392607684, + "node_id": "PR_kwDOADL-3s6nTPlp", + "number": 3203, + "title": "build(deps-dev): bump pytest-cov from 6.1.1 to 6.3.0", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 3, + "created_at": "2025-09-08T05:01:54Z", + "updated_at": "2025-09-12T05:12:59Z", + "closed_at": "2025-09-12T05:12:15Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3203", + "html_url": "https://github.com/RDFLib/rdflib/pull/3203", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3203.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3203.patch", + "merged_at": "2025-09-12T05:12:15Z" + }, + "body": "Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 6.1.1 to 6.3.0.\n
\nChangelog\n

Sourced from pytest-cov's changelog.

\n
\n

6.3.0 (2025-09-06)

\n
    \n
  • Added support for markdown reports.\nContributed by Marcos Boger in [#712](https://github.com/pytest-dev/pytest-cov/issues/712) <https://github.com/pytest-dev/pytest-cov/pull/712>_\nand [#714](https://github.com/pytest-dev/pytest-cov/issues/714) <https://github.com/pytest-dev/pytest-cov/pull/714>_.
  • \n
  • Fixed some formatting issues in docs.\nAnonymous contribution in [#706](https://github.com/pytest-dev/pytest-cov/issues/706) <https://github.com/pytest-dev/pytest-cov/pull/706>_.
  • \n
\n

6.2.1 (2025-06-12)

\n
    \n
  • \n

    Added a version requirement for pytest's pluggy dependency (1.2.0, released 2023-06-21) that has the required new-style hookwrapper API.

    \n
  • \n
  • \n

    Removed deprecated license classifier (packaging).

    \n
  • \n
  • \n

    Disabled coverage warnings in two more situations where they have no value:

    \n
      \n
    • "module-not-measured" in workers
    • \n
    • "already-imported" in subprocesses
    • \n
    \n
  • \n
\n

6.2.0 (2025-06-11)

\n
    \n
  • \n

    The plugin now adds 3 rules in the filter warnings configuration to prevent common coverage warnings being raised as obscure errors::

    \n

    default:unclosed database in <sqlite3.Connection object at:ResourceWarning\nonce::PytestCovWarning\nonce::CoverageWarning

    \n

    This fixes most of the bad interactions that are occurring on pytest 8.4 with filterwarnings=error.

    \n

    The plugin will check if there already matching rules for the 3 categories\n(ResourceWarning, PytestCovWarning, CoverageWarning) and message (unclosed database in <sqlite3.Connection object at) before adding the filters.

    \n

    This means you can have this in your pytest configuration for complete oblivion (not recommended, if that is not clear)::

    \n

    filterwarnings = [\n"error",\n"ignore:unclosed database in <sqlite3.Connection object at:ResourceWarning",\n"ignore::PytestCovWarning",\n"ignore::CoverageWarning",\n]

    \n
  • \n
\n
\n
\n
\nCommits\n
    \n
  • a69d1ab Bump version: 6.2.1 \u2192 6.3.0
  • \n
  • 475bf32 Update changelog.
  • \n
  • 3834009 Add GitHub Actions example and fix example to not break with default markdown...
  • \n
  • 0824728 Small phrasing adustments in Markdown docs
  • \n
  • 474c1f4 Move markdown dest files check to StoreReport for earlier error and parser.er...
  • \n
  • 7b21833 Default markdown-append to coverage.md and raise warning if both markdown opt...
  • \n
  • 3a15312 Fix usage of Path.open() to write/append to files
  • \n
  • 4b79449 Change output file cov-append.md in md-append example
  • \n
  • 40e9e8e Add docs and update AUTHORS.rst
  • \n
  • f5ca33a Add tests for markdown and markdown-append
  • \n
  • Additional commits viewable in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pytest-cov&package-manager=pip&previous-version=6.1.1&new-version=6.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3203/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3203/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3202", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3202/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3202/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3202/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3202", + "id": 3382370163, + "node_id": "PR_kwDOADL-3s6myRLC", + "number": 3202, + "title": "Merge 7-maintenance changes into main", + "user": { + "login": "edmondchuc", + "id": 37032744, + "node_id": "MDQ6VXNlcjM3MDMyNzQ0", + "avatar_url": "https://avatars.githubusercontent.com/u/37032744?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/edmondchuc", + "html_url": "https://github.com/edmondchuc", + "followers_url": "https://api.github.com/users/edmondchuc/followers", + "following_url": "https://api.github.com/users/edmondchuc/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/edmondchuc/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/edmondchuc/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/edmondchuc/subscriptions", + "organizations_url": "https://api.github.com/users/edmondchuc/orgs", + "repos_url": "https://api.github.com/users/edmondchuc/repos", + "events_url": "https://api.github.com/users/edmondchuc/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/edmondchuc/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 1, + "created_at": "2025-09-04T06:37:03Z", + "updated_at": "2025-09-09T03:33:26Z", + "closed_at": "2025-09-09T03:33:25Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3202", + "html_url": "https://github.com/RDFLib/rdflib/pull/3202", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3202.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3202.patch", + "merged_at": "2025-09-09T03:33:25Z" + }, + "body": "# Summary of changes\r\n\r\nThis PR integrates the recent features and bug fixes from `7-maintenance` branch into `main`. This will be merged when the 7.2.0 version is released.\r\n\r\nMany merge conflicts were resolved and all tests and checks are passing.\r\n\r\nThis PR supersedes https://github.com/RDFLib/rdflib/pull/3199.\r\n\r\n\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [ ] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [ ] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Created an issue to discuss the change and get in-principle agreement.\r\n - [ ] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [ ] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3202/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3202/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3197", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3197/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3197/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3197/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3197", + "id": 3378517619, + "node_id": "PR_kwDOADL-3s6mlSqI", + "number": 3197, + "title": "feat: canonicalization with longturtle serializer now optional", + "user": { + "login": "edmondchuc", + "id": 37032744, + "node_id": "MDQ6VXNlcjM3MDMyNzQ0", + "avatar_url": "https://avatars.githubusercontent.com/u/37032744?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/edmondchuc", + "html_url": "https://github.com/edmondchuc", + "followers_url": "https://api.github.com/users/edmondchuc/followers", + "following_url": "https://api.github.com/users/edmondchuc/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/edmondchuc/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/edmondchuc/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/edmondchuc/subscriptions", + "organizations_url": "https://api.github.com/users/edmondchuc/orgs", + "repos_url": "https://api.github.com/users/edmondchuc/repos", + "events_url": "https://api.github.com/users/edmondchuc/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/edmondchuc/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-09-03T06:41:22Z", + "updated_at": "2025-09-08T01:31:53Z", + "closed_at": "2025-09-08T01:31:52Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3197", + "html_url": "https://github.com/RDFLib/rdflib/pull/3197", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3197.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3197.patch", + "merged_at": "2025-09-08T01:31:52Z" + }, + "body": "Fixes https://github.com/RDFLib/rdflib/issues/3196\r\n\r\n\r\n\r\n# Summary of changes\r\n\r\n\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [ ] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [ ] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Created an issue to discuss the change and get in-principle agreement.\r\n - [ ] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [ ] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3197/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3197/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3195", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3195/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3195/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3195/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3195", + "id": 3365279463, + "node_id": "PR_kwDOADL-3s6l6NCn", + "number": 3195, + "title": "Revert \"remove old hacks against 2to3 (#3076)\"", + "user": { + "login": "edmondchuc", + "id": 37032744, + "node_id": "MDQ6VXNlcjM3MDMyNzQ0", + "avatar_url": "https://avatars.githubusercontent.com/u/37032744?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/edmondchuc", + "html_url": "https://github.com/edmondchuc", + "followers_url": "https://api.github.com/users/edmondchuc/followers", + "following_url": "https://api.github.com/users/edmondchuc/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/edmondchuc/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/edmondchuc/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/edmondchuc/subscriptions", + "organizations_url": "https://api.github.com/users/edmondchuc/orgs", + "repos_url": "https://api.github.com/users/edmondchuc/repos", + "events_url": "https://api.github.com/users/edmondchuc/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/edmondchuc/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 7242799529, + "node_id": "LA_kwDOADL-3s8AAAABr7RZqQ", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/7.1", + "name": "7.1", + "color": "FC7848", + "default": false, + "description": "Issues planned to fix in v7.1" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 1, + "created_at": "2025-08-29T03:03:18Z", + "updated_at": "2025-08-29T03:50:11Z", + "closed_at": "2025-08-29T03:50:10Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3195", + "html_url": "https://github.com/RDFLib/rdflib/pull/3195", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3195.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3195.patch", + "merged_at": "2025-08-29T03:50:10Z" + }, + "body": "This reverts commit b74c6574fd982b410aed1aa43853eed37504bf15.\r\n\r\n\r\n\r\n# Summary of changes\r\n\r\nFixes https://github.com/RDFLib/rdflib/issues/3193\r\n\r\n\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [ ] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [ ] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Created an issue to discuss the change and get in-principle agreement.\r\n - [ ] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [ ] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3195/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3195/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3194", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3194/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3194/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3194/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3194", + "id": 3365240233, + "node_id": "PR_kwDOADL-3s6l6E02", + "number": 3194, + "title": "Fix failing webtest", + "user": { + "login": "edmondchuc", + "id": 37032744, + "node_id": "MDQ6VXNlcjM3MDMyNzQ0", + "avatar_url": "https://avatars.githubusercontent.com/u/37032744?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/edmondchuc", + "html_url": "https://github.com/edmondchuc", + "followers_url": "https://api.github.com/users/edmondchuc/followers", + "following_url": "https://api.github.com/users/edmondchuc/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/edmondchuc/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/edmondchuc/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/edmondchuc/subscriptions", + "organizations_url": "https://api.github.com/users/edmondchuc/orgs", + "repos_url": "https://api.github.com/users/edmondchuc/repos", + "events_url": "https://api.github.com/users/edmondchuc/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/edmondchuc/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 7242799529, + "node_id": "LA_kwDOADL-3s8AAAABr7RZqQ", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/7.1", + "name": "7.1", + "color": "FC7848", + "default": false, + "description": "Issues planned to fix in v7.1" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 1, + "created_at": "2025-08-29T02:35:40Z", + "updated_at": "2025-08-29T05:33:39Z", + "closed_at": "2025-08-29T05:33:36Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3194", + "html_url": "https://github.com/RDFLib/rdflib/pull/3194", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3194.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3194.patch", + "merged_at": "2025-08-29T05:33:36Z" + }, + "body": "\r\n\r\n# Summary of changes\r\n\r\nFixes https://github.com/RDFLib/rdflib/issues/3192\r\n\r\nNote: this is a cascading PR and includes https://github.com/RDFLib/rdflib/pull/3195 to ensure all fixes to tests are applied before merging into `7-maintenance` branch.\r\n\r\n\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [ ] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [ ] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Created an issue to discuss the change and get in-principle agreement.\r\n - [ ] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [ ] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3194/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3194/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3189", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3189/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3189/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3189/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3189", + "id": 3351175415, + "node_id": "PR_kwDOADL-3s6lLaSS", + "number": 3189, + "title": "build(deps): bump actions/setup-java from 4 to 5", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4132956439, + "node_id": "LA_kwDOADL-3s72V-kX", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/github_actions", + "name": "github_actions", + "color": "000000", + "default": false, + "description": "Pull requests that update GitHub Actions code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-08-25T09:48:26Z", + "updated_at": "2025-09-12T05:24:57Z", + "closed_at": "2025-09-12T05:24:16Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3189", + "html_url": "https://github.com/RDFLib/rdflib/pull/3189", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3189.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3189.patch", + "merged_at": "2025-09-12T05:24:16Z" + }, + "body": "Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4 to 5.\n
\nRelease notes\n

Sourced from actions/setup-java's releases.

\n
\n

v5.0.0

\n

What's Changed

\n

Breaking Changes

\n\n

Make sure your runner is updated to this version or newer to use this release. v2.327.1 Release Notes

\n

Dependency Upgrades

\n\n

Bug Fixes

\n\n

New Contributors

\n\n

Full Changelog: https://github.com/actions/setup-java/compare/v4...v5.0.0

\n

v4.7.1

\n

What's Changed

\n

Documentation changes

\n\n

Dependency updates:

\n\n

Full Changelog: https://github.com/actions/setup-java/compare/v4...v4.7.1

\n

v4.7.0

\n

What's Changed

\n\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • dded088 Bump actions/checkout from 4 to 5 (#896)
  • \n
  • 0913e9a Upgrade to node 24 (#888)
  • \n
  • e9343db Bumps form-data (#887)
  • \n
  • ae2b61d Bump undici from 5.28.5 to 5.29.0 (#833)
  • \n
  • c190c18 Bump eslint-plugin-jest from 27.9.0 to 29.0.1 (#730)
  • \n
  • 67aec00 Fix: prevent default installation of JetBrains pre-releases (#859)
  • \n
  • ebb356c Improve Error Handling for Setup-Java Action to Help Debug Intermittent Failu...
  • \n
  • f4f1212 Update publish-immutable-actions.yml (#798)
  • \n
  • See full diff in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-java&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3189/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3189/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3185", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3185/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3185/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3185/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3185", + "id": 3329618398, + "node_id": "PR_kwDOADL-3s6kDWYr", + "number": 3185, + "title": "build(deps): bump library/python from 3.13.3-slim to 3.13.7-slim in /docker/latest", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4545133062, + "node_id": "LA_kwDOADL-3s8AAAABDuk6Bg", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/docker", + "name": "docker", + "color": "21ceff", + "default": false, + "description": "Pull requests that update Docker code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-08-18T07:56:51Z", + "updated_at": "2025-09-12T05:36:21Z", + "closed_at": "2025-09-12T05:35:57Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3185", + "html_url": "https://github.com/RDFLib/rdflib/pull/3185", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3185.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3185.patch", + "merged_at": "2025-09-12T05:35:57Z" + }, + "body": "Bumps library/python from 3.13.3-slim to 3.13.7-slim.\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=library/python&package-manager=docker&previous-version=3.13.3-slim&new-version=3.13.7-slim)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3185/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3185/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3184", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3184/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3184/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3184/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3184", + "id": 3329609992, + "node_id": "PR_kwDOADL-3s6kDUnS", + "number": 3184, + "title": "build(deps): bump actions/checkout from 4 to 5", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4132956439, + "node_id": "LA_kwDOADL-3s72V-kX", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/github_actions", + "name": "github_actions", + "color": "000000", + "default": false, + "description": "Pull requests that update GitHub Actions code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-08-18T07:54:08Z", + "updated_at": "2025-09-12T05:46:47Z", + "closed_at": "2025-09-12T05:46:06Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3184", + "html_url": "https://github.com/RDFLib/rdflib/pull/3184", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3184.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3184.patch", + "merged_at": "2025-09-12T05:46:06Z" + }, + "body": "Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.\n
\nRelease notes\n

Sourced from actions/checkout's releases.

\n
\n

v5.0.0

\n

What's Changed

\n\n

\u26a0\ufe0f Minimum Compatible Runner Version

\n

v2.327.1
\nRelease Notes

\n

Make sure your runner is updated to this version or newer to use this release.

\n

Full Changelog: https://github.com/actions/checkout/compare/v4...v5.0.0

\n

v4.3.0

\n

What's Changed

\n\n

New Contributors

\n\n

Full Changelog: https://github.com/actions/checkout/compare/v4...v4.3.0

\n

v4.2.2

\n

What's Changed

\n\n

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

\n

v4.2.1

\n

What's Changed

\n\n

New Contributors

\n\n

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

\n\n
\n

... (truncated)

\n
\n
\nChangelog\n

Sourced from actions/checkout's changelog.

\n
\n

Changelog

\n

V5.0.0

\n\n

V4.3.0

\n\n

v4.2.2

\n\n

v4.2.1

\n\n

v4.2.0

\n\n

v4.1.7

\n\n

v4.1.6

\n\n

v4.1.5

\n\n

v4.1.4

\n\n

v4.1.3

\n\n
\n

... (truncated)

\n
\n
\nCommits\n\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3184/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3184/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3183", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3183/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3183/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3183/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3183", + "id": 3329595517, + "node_id": "PR_kwDOADL-3s6kDRhT", + "number": 3183, + "title": "build(deps): bump library/python from 3.13.3-slim to 3.13.7-slim in /docker/unstable", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4545133062, + "node_id": "LA_kwDOADL-3s8AAAABDuk6Bg", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/docker", + "name": "docker", + "color": "21ceff", + "default": false, + "description": "Pull requests that update Docker code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-08-18T07:49:17Z", + "updated_at": "2025-09-12T05:58:56Z", + "closed_at": "2025-09-12T05:57:58Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3183", + "html_url": "https://github.com/RDFLib/rdflib/pull/3183", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3183.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3183.patch", + "merged_at": "2025-09-12T05:57:58Z" + }, + "body": "Bumps library/python from 3.13.3-slim to 3.13.7-slim.\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=library/python&package-manager=docker&previous-version=3.13.3-slim&new-version=3.13.7-slim)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3183/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3183/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3182", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3182/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3182/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3182/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3182", + "id": 3328829189, + "node_id": "PR_kwDOADL-3s6kAyCB", + "number": 3182, + "title": "Fix #3181", + "user": { + "login": "nicholascar", + "id": 7321872, + "node_id": "MDQ6VXNlcjczMjE4NzI=", + "avatar_url": "https://avatars.githubusercontent.com/u/7321872?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nicholascar", + "html_url": "https://github.com/nicholascar", + "followers_url": "https://api.github.com/users/nicholascar/followers", + "following_url": "https://api.github.com/users/nicholascar/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/nicholascar/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/nicholascar/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/nicholascar/subscriptions", + "organizations_url": "https://api.github.com/users/nicholascar/orgs", + "repos_url": "https://api.github.com/users/nicholascar/repos", + "events_url": "https://api.github.com/users/nicholascar/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/nicholascar/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-08-18T00:52:09Z", + "updated_at": "2025-08-18T00:52:18Z", + "closed_at": "2025-08-18T00:52:17Z", + "author_association": "MEMBER", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3182", + "html_url": "https://github.com/RDFLib/rdflib/pull/3182", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3182.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3182.patch", + "merged_at": "2025-08-18T00:52:17Z" + }, + "body": "README link fix", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3182/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3182/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3178", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3178/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3178/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3178/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3178", + "id": 3311960710, + "node_id": "PR_kwDOADL-3s6jJe79", + "number": 3178, + "title": "Creation of an RDFLib Charter", + "user": { + "login": "nicholascar", + "id": 7321872, + "node_id": "MDQ6VXNlcjczMjE4NzI=", + "avatar_url": "https://avatars.githubusercontent.com/u/7321872?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nicholascar", + "html_url": "https://github.com/nicholascar", + "followers_url": "https://api.github.com/users/nicholascar/followers", + "following_url": "https://api.github.com/users/nicholascar/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/nicholascar/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/nicholascar/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/nicholascar/subscriptions", + "organizations_url": "https://api.github.com/users/nicholascar/orgs", + "repos_url": "https://api.github.com/users/nicholascar/repos", + "events_url": "https://api.github.com/users/nicholascar/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/nicholascar/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-08-11T23:35:05Z", + "updated_at": "2025-08-18T00:43:02Z", + "closed_at": "2025-08-18T00:43:00Z", + "author_association": "MEMBER", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3178", + "html_url": "https://github.com/RDFLib/rdflib/pull/3178", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3178.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3178.patch", + "merged_at": "2025-08-18T00:43:00Z" + }, + "body": "Edits of the Contributing guidelines to streamline their advice and to add a Charter that states RDFLib's community's principles.", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3178/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3178/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3177", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3177/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3177/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3177/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3177", + "id": 3309552816, + "node_id": "PR_kwDOADL-3s6jBhWX", + "number": 3177, + "title": "Feature: Add Tentris Plugin to docs", + "user": { + "login": "bigerl", + "id": 933146, + "node_id": "MDQ6VXNlcjkzMzE0Ng==", + "avatar_url": "https://avatars.githubusercontent.com/u/933146?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/bigerl", + "html_url": "https://github.com/bigerl", + "followers_url": "https://api.github.com/users/bigerl/followers", + "following_url": "https://api.github.com/users/bigerl/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/bigerl/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/bigerl/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/bigerl/subscriptions", + "organizations_url": "https://api.github.com/users/bigerl/orgs", + "repos_url": "https://api.github.com/users/bigerl/repos", + "events_url": "https://api.github.com/users/bigerl/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/bigerl/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 1, + "created_at": "2025-08-11T11:09:53Z", + "updated_at": "2025-08-11T23:43:05Z", + "closed_at": "2025-08-11T23:43:05Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3177", + "html_url": "https://github.com/RDFLib/rdflib/pull/3177", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3177.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3177.patch", + "merged_at": "2025-08-11T23:43:05Z" + }, + "body": "# Summary of changes\r\n\r\nAt Tentris, we developed a plugin that allows users to run their `rdflib.Graph` (1) with a native in-memory Tentris instance and (2) connect it to an Tentris SPARQL HTTP endpoint. \r\n\r\nI have added it to the list of Plugins. \r\n\r\n# Checklist\r\n\r\n- [x] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [x] Checked that all tests and type checking passes.\r\n- If the change has a potential impact on users of this project:\r\n - [x] Considered adding additional documentation.\r\n- [x] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n \r\n **Note: Some organization policy seems to prevent that. If anybody is aware how I can adjust that I am happy to change it.**\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3177/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3177/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3176", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3176/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3176/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3176/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3176", + "id": 3309030353, + "node_id": "PR_kwDOADL-3s6i_zhJ", + "number": 3176, + "title": "build(deps): bump poetry from 2.0.0 to 2.1.4 in /devtools", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 4, + "created_at": "2025-08-11T08:40:57Z", + "updated_at": "2025-09-16T06:01:05Z", + "closed_at": "2025-09-16T06:00:35Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3176", + "html_url": "https://github.com/RDFLib/rdflib/pull/3176", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3176.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3176.patch", + "merged_at": "2025-09-16T06:00:35Z" + }, + "body": "Bumps [poetry](https://github.com/python-poetry/poetry) from 2.0.0 to 2.1.4.\n
\nRelease notes\n

Sourced from poetry's releases.

\n
\n

2.1.4

\n

Changed

\n
    \n
  • Require virtualenv<20.33 to work around an issue where Poetry uses the wrong Python version (#10491).
  • \n
  • Improve the error messages for the validation of the pyproject.toml file (#10471).
  • \n
\n

Fixed

\n
    \n
  • Fix an issue where project plugins were installed even though poetry install was called with --no-plugins (#10405).
  • \n
  • Fix an issue where dependency resolution failed for self-referential extras with duplicate dependencies (#10488).
  • \n
\n

Docs

\n
    \n
  • Clarify how to include files that were automatically excluded via VCS ignore settings (#10442).
  • \n
  • Clarify the behavior of poetry add if no version constraint is explicitly specified (#10445).
  • \n
\n

2.1.3

\n

Changed

\n
    \n
  • Require importlib-metadata<8.7 for Python 3.9 because of a breaking change in importlib-metadata 8.7 (#10374).
  • \n
\n

Fixed

\n
    \n
  • Fix an issue where re-locking failed for incomplete multiple-constraints dependencies with explicit sources (#10324).
  • \n
  • Fix an issue where the --directory option did not work if a plugin, which accesses the poetry instance during its activation, was installed (#10352).
  • \n
  • Fix an issue where poetry env activate -v printed additional information to stdout instead of stderr so that the output could not be used as designed (#10353).
  • \n
  • Fix an issue where the original error was not printed if building a git dependency failed (#10366).
  • \n
  • Fix an issue where wheels for the wrong platform were installed in rare cases. (#10361).
  • \n
\n

poetry-core (2.1.3)

\n
    \n
  • Fix an issue where the union of specific inverse or partially inverse markers was not simplified (#858).
  • \n
  • Fix an issue where optional dependencies defined in the project section were treated as non-optional when a source was defined for them in the tool.poetry section (#857).
  • \n
  • Fix an issue where markers with === were not parsed correctly (#860).
  • \n
  • Fix an issue where local versions with upper case letters caused an error (#859).
  • \n
  • Fix an issue where extra markers with a value starting with "in" were not validated correctly (#862).
  • \n
\n

2.1.2

\n

Changed

\n
    \n
  • Improve performance of locking dependencies (#10275).
  • \n
\n

Fixed

\n
    \n
  • Fix an issue where markers were not locked correctly (#10240).
  • \n
  • Fix an issue where the result of poetry lock was not deterministic (#10276).
  • \n
  • Fix an issue where poetry env activate returned the wrong command for tcsh (#10243).
  • \n
  • Fix an issue where poetry env activate returned the wrong command for pwsh on Linux (#10256).
  • \n
\n

Docs

\n\n
\n

... (truncated)

\n
\n
\nChangelog\n

Sourced from poetry's changelog.

\n
\n

[2.1.4] - 2025-08-05

\n

Changed

\n
    \n
  • Require virtualenv<20.33 to work around an issue where Poetry uses the wrong Python version (#10491).
  • \n
  • Improve the error messages for the validation of the pyproject.toml file (#10471).
  • \n
\n

Fixed

\n
    \n
  • Fix an issue where project plugins were installed even though poetry install was called with --no-plugins (#10405).
  • \n
  • Fix an issue where dependency resolution failed for self-referential extras with duplicate dependencies (#10488).
  • \n
\n

Docs

\n
    \n
  • Clarify how to include files that were automatically excluded via VCS ignore settings (#10442).
  • \n
  • Clarify the behavior of poetry add if no version constraint is explicitly specified (#10445).
  • \n
\n

[2.1.3] - 2025-05-04

\n

Changed

\n
    \n
  • Require importlib-metadata<8.7 for Python 3.9 because of a breaking change in importlib-metadata 8.7 (#10374).
  • \n
\n

Fixed

\n
    \n
  • Fix an issue where re-locking failed for incomplete multiple-constraints dependencies with explicit sources (#10324).
  • \n
  • Fix an issue where the --directory option did not work if a plugin, which accesses the poetry instance during its activation, was installed (#10352).
  • \n
  • Fix an issue where poetry env activate -v printed additional information to stdout instead of stderr so that the output could not be used as designed (#10353).
  • \n
  • Fix an issue where the original error was not printed if building a git dependency failed (#10366).
  • \n
  • Fix an issue where wheels for the wrong platform were installed in rare cases. (#10361).
  • \n
\n

poetry-core (2.1.3)

\n
    \n
  • Fix an issue where the union of specific inverse or partially inverse markers was not simplified (#858).
  • \n
  • Fix an issue where optional dependencies defined in the project section were treated as non-optional when a source was defined for them in the tool.poetry section (#857).
  • \n
  • Fix an issue where markers with === were not parsed correctly (#860).
  • \n
  • Fix an issue where local versions with upper case letters caused an error (#859).
  • \n
  • Fix an issue where extra markers with a value starting with "in" were not validated correctly (#862).
  • \n
\n

[2.1.2] - 2025-03-29

\n

Changed

\n
    \n
  • Improve performance of locking dependencies (#10275).
  • \n
\n

Fixed

\n
    \n
  • Fix an issue where markers were not locked correctly (#10240).
  • \n
\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • a8f0889 release: bump version to 2.1.4
  • \n
  • 683fd83 fix: adjust virtualenv constraint in pyproject.toml to < 20.33.0 (#10491)
  • \n
  • 501346e solver: fix dependency resolution for self-referential extras with duplicate ...
  • \n
  • c9e8a4c fix deprecated parts in pyproject example in README (#10479)
  • \n
  • 2855b2e Fix test_python_get_preferred_default for rc Python releases (#10478)
  • \n
  • 9ee000a improve pyproject.toml validation error messages by replacing data with `to...
  • \n
  • 6d6c2f1 docs: update unspecified version docs for add (#10445)
  • \n
  • 5e58233 Documentation: Clarified negating VCS excluded files (#10442)
  • \n
  • ac51717 fix: typo in dependency-specification.md (#10427)
  • \n
  • c1220a7 Add missing tmp_venv mock to test_no_additional_output_in_verbose_mode (#10397)
  • \n
  • Additional commits viewable in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=poetry&package-manager=pip&previous-version=2.0.0&new-version=2.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nYou can trigger a rebase of this PR by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\nDependabot will merge this PR once it's up-to-date and CI passes on it, as requested by @edmondchuc.\n\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
\n\n> **Note**\n> Automatic rebases have been disabled on this pull request as it has been open for over 30 days.", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3176/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3176/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3158", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3158/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3158/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3158/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3158", + "id": 3166176394, + "node_id": "PR_kwDOADL-3s6bj-5z", + "number": 3158, + "title": "Fix contributing guide link in README.md", + "user": { + "login": "rodrigosetti", + "id": 99732, + "node_id": "MDQ6VXNlcjk5NzMy", + "avatar_url": "https://avatars.githubusercontent.com/u/99732?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/rodrigosetti", + "html_url": "https://github.com/rodrigosetti", + "followers_url": "https://api.github.com/users/rodrigosetti/followers", + "following_url": "https://api.github.com/users/rodrigosetti/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/rodrigosetti/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/rodrigosetti/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/rodrigosetti/subscriptions", + "organizations_url": "https://api.github.com/users/rodrigosetti/orgs", + "repos_url": "https://api.github.com/users/rodrigosetti/repos", + "events_url": "https://api.github.com/users/rodrigosetti/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/rodrigosetti/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-06-22T18:47:04Z", + "updated_at": "2025-08-18T03:28:21Z", + "closed_at": "2025-08-18T00:45:52Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3158", + "html_url": "https://github.com/RDFLib/rdflib/pull/3158", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3158.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3158.patch", + "merged_at": "2025-08-18T00:45:51Z" + }, + "body": "Previous link was broken", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3158/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3158/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3146", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3146/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3146/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3146/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3146", + "id": 3108065541, + "node_id": "PR_kwDOADL-3s6YhDye", + "number": 3146, + "title": "Replacement for #3125", + "user": { + "login": "nicholascar", + "id": 7321872, + "node_id": "MDQ6VXNlcjczMjE4NzI=", + "avatar_url": "https://avatars.githubusercontent.com/u/7321872?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nicholascar", + "html_url": "https://github.com/nicholascar", + "followers_url": "https://api.github.com/users/nicholascar/followers", + "following_url": "https://api.github.com/users/nicholascar/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/nicholascar/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/nicholascar/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/nicholascar/subscriptions", + "organizations_url": "https://api.github.com/users/nicholascar/orgs", + "repos_url": "https://api.github.com/users/nicholascar/repos", + "events_url": "https://api.github.com/users/nicholascar/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/nicholascar/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-06-01T23:59:34Z", + "updated_at": "2025-06-02T00:48:58Z", + "closed_at": "2025-06-02T00:48:56Z", + "author_association": "MEMBER", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3146", + "html_url": "https://github.com/RDFLib/rdflib/pull/3146", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3146.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3146.patch", + "merged_at": "2025-06-02T00:48:56Z" + }, + "body": "This PR replaces #3125 since a bunch of conflicts from subsequent PRs needed merging into it.\r\n\r\nCloses #3125", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3146/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3146/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3145", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3145/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3145/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3145/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3145", + "id": 3106545238, + "node_id": "PR_kwDOADL-3s6Ycf5X", + "number": 3145, + "title": "replace PR 3109; improve plugins modules docs; change header colour t\u2026", + "user": { + "login": "nicholascar", + "id": 7321872, + "node_id": "MDQ6VXNlcjczMjE4NzI=", + "avatar_url": "https://avatars.githubusercontent.com/u/7321872?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nicholascar", + "html_url": "https://github.com/nicholascar", + "followers_url": "https://api.github.com/users/nicholascar/followers", + "following_url": "https://api.github.com/users/nicholascar/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/nicholascar/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/nicholascar/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/nicholascar/subscriptions", + "organizations_url": "https://api.github.com/users/nicholascar/orgs", + "repos_url": "https://api.github.com/users/nicholascar/repos", + "events_url": "https://api.github.com/users/nicholascar/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/nicholascar/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-06-01T04:12:57Z", + "updated_at": "2025-06-01T04:25:26Z", + "closed_at": "2025-06-01T04:25:24Z", + "author_association": "MEMBER", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3145", + "html_url": "https://github.com/RDFLib/rdflib/pull/3145", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3145.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3145.patch", + "merged_at": "2025-06-01T04:25:24Z" + }, + "body": "Closes #3109", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3145/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3145/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3144", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3144/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3144/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3144/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3144", + "id": 3105339557, + "node_id": "PR_kwDOADL-3s6YYuTz", + "number": 3144, + "title": "Pr/3143", + "user": { + "login": "nicholascar", + "id": 7321872, + "node_id": "MDQ6VXNlcjczMjE4NzI=", + "avatar_url": "https://avatars.githubusercontent.com/u/7321872?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nicholascar", + "html_url": "https://github.com/nicholascar", + "followers_url": "https://api.github.com/users/nicholascar/followers", + "following_url": "https://api.github.com/users/nicholascar/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/nicholascar/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/nicholascar/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/nicholascar/subscriptions", + "organizations_url": "https://api.github.com/users/nicholascar/orgs", + "repos_url": "https://api.github.com/users/nicholascar/repos", + "events_url": "https://api.github.com/users/nicholascar/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/nicholascar/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-05-31T11:16:16Z", + "updated_at": "2025-06-01T02:23:59Z", + "closed_at": "2025-06-01T02:23:58Z", + "author_association": "MEMBER", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3144", + "html_url": "https://github.com/RDFLib/rdflib/pull/3144", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3144.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3144.patch", + "merged_at": "2025-06-01T02:23:58Z" + }, + "body": "Replacement for #3143 with some black & mypy additions\r\n\r\nCloses #3143", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3144/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3144/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3142", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3142/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3142/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3142/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3142", + "id": 3090061335, + "node_id": "PR_kwDOADL-3s6XlAuc", + "number": 3142, + "title": "build(deps-dev): bump coverage from 7.7.1 to 7.8.2", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-05-26T05:35:59Z", + "updated_at": "2025-05-31T10:00:27Z", + "closed_at": "2025-05-31T10:00:25Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3142", + "html_url": "https://github.com/RDFLib/rdflib/pull/3142", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3142.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3142.patch", + "merged_at": "2025-05-31T10:00:25Z" + }, + "body": "Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.7.1 to 7.8.2.\n
\nChangelog\n

Sourced from coverage's changelog.

\n
\n

Version 7.8.2 \u2014 2025-05-23

\n
    \n
  • Wheels are provided for Windows ARM64 on Python 3.11, 3.12, and 3.13.\nThanks, Finn Womack <pull 1972_>_.
  • \n
\n

.. _issue 1971: nedbat/coveragepy#1971\n.. _pull 1972: nedbat/coveragepy#1972

\n

.. _changes_7-8-1:

\n

Version 7.8.1 \u2014 2025-05-21

\n
    \n
  • \n

    A number of EncodingWarnings were fixed that could appear if you've enabled\nPYTHONWARNDEFAULTENCODING, fixing issue 1966. Thanks, Henry Schreiner <pull 1967_>.

    \n
  • \n
  • \n

    Fixed a race condition when using sys.monitoring with free-threading Python,\nclosing issue 1970_.

    \n
  • \n
\n

.. _issue 1966: nedbat/coveragepy#1966\n.. _pull 1967: nedbat/coveragepy#1967\n.. _issue 1970: nedbat/coveragepy#1970

\n

.. _changes_7-8-0:

\n

Version 7.8.0 \u2014 2025-03-30

\n
    \n
  • \n

    Added a new source_dirs setting for symmetry with the existing\nsource_pkgs setting. It's preferable to the existing source setting,\nbecause you'll get a clear error when directories don't exist. Fixes issue 1942. Thanks, Jeremy Fleischman <pull 1943_>.

    \n
  • \n
  • \n

    Fix: the PYTHONSAFEPATH environment variable new in Python 3.11 is properly\nsupported, closing issue 1696. Thanks, Philipp A. <pull 1700_>. This\nworks properly except for a detail when using the coverage command on\nWindows. There you can use python -m coverage instead if you need exact\nemulation.

    \n
  • \n
\n

.. _issue 1696: nedbat/coveragepy#1696\n.. _pull 1700: nedbat/coveragepy#1700\n.. _issue 1942: nedbat/coveragepy#1942\n.. _pull 1943: nedbat/coveragepy#1943

\n

.. _changes_7-7-1:

\n
\n
\n
\nCommits\n
    \n
  • 51ab2e5 build: have to keep expected dist counts in sync
  • \n
  • be7bbf2 docs: sample HTML for 7.8.2
  • \n
  • 3cee850 docs: prep for 7.8.2
  • \n
  • 39bc6b0 docs: provide more details if the kit matrix is edited.
  • \n
  • a608fb3 build: add support for Windows arm64 (#1972)
  • \n
  • 2fe6225 build: run tox lint if actions have changed
  • \n
  • 3d93a78 docs: docs need scriv for making github releases
  • \n
  • 0c443a2 build: bump version to 7.8.2
  • \n
  • ed98b87 docs: sample HTML for 7.8.1
  • \n
  • b98bc9b docs: prep for 7.8.1
  • \n
  • Additional commits viewable in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coverage&package-manager=pip&previous-version=7.7.1&new-version=7.8.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3142/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3142/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3141", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3141/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3141/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3141/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3141", + "id": 3089982425, + "node_id": "PR_kwDOADL-3s6Xkvpa", + "number": 3141, + "title": "fix: do not automatically generate header id in RDF patch generation and fix missing fullstop", + "user": { + "login": "recalcitrantsupplant", + "id": 10570038, + "node_id": "MDQ6VXNlcjEwNTcwMDM4", + "avatar_url": "https://avatars.githubusercontent.com/u/10570038?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/recalcitrantsupplant", + "html_url": "https://github.com/recalcitrantsupplant", + "followers_url": "https://api.github.com/users/recalcitrantsupplant/followers", + "following_url": "https://api.github.com/users/recalcitrantsupplant/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/recalcitrantsupplant/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/recalcitrantsupplant/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/recalcitrantsupplant/subscriptions", + "organizations_url": "https://api.github.com/users/recalcitrantsupplant/orgs", + "repos_url": "https://api.github.com/users/recalcitrantsupplant/repos", + "events_url": "https://api.github.com/users/recalcitrantsupplant/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/recalcitrantsupplant/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-05-26T04:42:48Z", + "updated_at": "2025-05-31T09:48:58Z", + "closed_at": "2025-05-31T09:48:58Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3141", + "html_url": "https://github.com/RDFLib/rdflib/pull/3141", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3141.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3141.patch", + "merged_at": "2025-05-31T09:48:58Z" + }, + "body": "# Summary of changes\r\n\r\nFixes a bug in `PatchSerializer` where the `H prev` header line missed a trailing period. Also, `header_id` is now treated as optional; the `H id` line is only written if `header_id` is provided, removing the previous default UUID generation. This change is backwards compatible and primarily addresses a formatting issue and refines header generation.\r\n\r\n# Checklist\r\n\r\n- [x] Checked that there aren't other open pull requests for the same change.\r\n- [x] Checked that all tests and type checking passes. \r\n- If the change has a potential impact on users of this project:\r\n - [x] Added or updated tests that fail without the change.\r\n - [N/A] Updated relevant documentation to avoid inaccuracies.\r\n- [x] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3141/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3141/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3139", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3139/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3139/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3139/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3139", + "id": 3074399060, + "node_id": "PR_kwDOADL-3s6WwPrJ", + "number": 3139, + "title": "List on docs the COTTAS store backend", + "user": { + "login": "arenas-guerrero-julian", + "id": 18464038, + "node_id": "MDQ6VXNlcjE4NDY0MDM4", + "avatar_url": "https://avatars.githubusercontent.com/u/18464038?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/arenas-guerrero-julian", + "html_url": "https://github.com/arenas-guerrero-julian", + "followers_url": "https://api.github.com/users/arenas-guerrero-julian/followers", + "following_url": "https://api.github.com/users/arenas-guerrero-julian/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/arenas-guerrero-julian/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/arenas-guerrero-julian/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/arenas-guerrero-julian/subscriptions", + "organizations_url": "https://api.github.com/users/arenas-guerrero-julian/orgs", + "repos_url": "https://api.github.com/users/arenas-guerrero-julian/repos", + "events_url": "https://api.github.com/users/arenas-guerrero-julian/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/arenas-guerrero-julian/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-05-19T16:25:00Z", + "updated_at": "2025-05-20T01:49:26Z", + "closed_at": "2025-05-20T01:49:26Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3139", + "html_url": "https://github.com/RDFLib/rdflib/pull/3139", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3139.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3139.patch", + "merged_at": "2025-05-20T01:49:26Z" + }, + "body": "# Summary of changes\r\n\r\nAdded [COTTAS](https://github.com/arenas-guerrero-julian/pycottas) store backend to the docs.\r\n\r\n# Checklist\r\n\r\n- [x] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3139/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3139/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3134", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3134/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3134/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3134/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3134", + "id": 3044690733, + "node_id": "PR_kwDOADL-3s6VNJb_", + "number": 3134, + "title": "[7.x] fix namespace prefixes in longturtle serialization", + "user": { + "login": "edmondchuc", + "id": 37032744, + "node_id": "MDQ6VXNlcjM3MDMyNzQ0", + "avatar_url": "https://avatars.githubusercontent.com/u/37032744?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/edmondchuc", + "html_url": "https://github.com/edmondchuc", + "followers_url": "https://api.github.com/users/edmondchuc/followers", + "following_url": "https://api.github.com/users/edmondchuc/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/edmondchuc/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/edmondchuc/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/edmondchuc/subscriptions", + "organizations_url": "https://api.github.com/users/edmondchuc/orgs", + "repos_url": "https://api.github.com/users/edmondchuc/repos", + "events_url": "https://api.github.com/users/edmondchuc/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/edmondchuc/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-05-07T05:00:00Z", + "updated_at": "2025-05-20T01:50:14Z", + "closed_at": "2025-05-20T01:50:13Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3134", + "html_url": "https://github.com/RDFLib/rdflib/pull/3134", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3134.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3134.patch", + "merged_at": "2025-05-20T01:50:13Z" + }, + "body": "7.x PR of https://github.com/RDFLib/rdflib/pull/3106.\r\n\r\n- [ ] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [ ] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [ ] Created an issue to discuss the change and get in-principle agreement.\r\n - [ ] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [ ] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [ ] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3134/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3134/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3132", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3132/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3132/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3132/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3132", + "id": 3039033122, + "node_id": "PR_kwDOADL-3s6U52DB", + "number": 3132, + "title": "Cope with Namespace annotations in Python 3.14", + "user": { + "login": "nphilipp", + "id": 820624, + "node_id": "MDQ6VXNlcjgyMDYyNA==", + "avatar_url": "https://avatars.githubusercontent.com/u/820624?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nphilipp", + "html_url": "https://github.com/nphilipp", + "followers_url": "https://api.github.com/users/nphilipp/followers", + "following_url": "https://api.github.com/users/nphilipp/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/nphilipp/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/nphilipp/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/nphilipp/subscriptions", + "organizations_url": "https://api.github.com/users/nphilipp/orgs", + "repos_url": "https://api.github.com/users/nphilipp/repos", + "events_url": "https://api.github.com/users/nphilipp/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/nphilipp/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-05-05T08:57:17Z", + "updated_at": "2025-06-01T06:50:30Z", + "closed_at": "2025-06-01T06:50:30Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3132", + "html_url": "https://github.com/RDFLib/rdflib/pull/3132", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3132.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3132.patch", + "merged_at": "2025-06-01T06:50:30Z" + }, + "body": "I submitted this already in #3084 which got merged, but the change is missing from the main branch. So here we go again:\r\n\r\n-----------------------\r\n\r\nThe __annotations__ member can be incomplete, use the get_annotations() helper from annotationlib (Python >= 3.14) or inspect (Python >= 3.10) if available.\r\n\r\nRelated: #3083\r\n\r\n\r\n\r\n# Summary of changes\r\n\r\nThis fixes accessing Namespace annotations on Python 3.14, which makes `import rdflib` fail on this Python version. This should be backwards-compatible.\r\n\r\n\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [x] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [x] Checked that all tests and type checking passes. \u21d2 Other tests (sparql) fail on Python 3.14, see #3083 \r\n- If the change adds new features or changes the RDFLib public API: n/a\r\n- If the change has a potential impact on users of this project: n/a (covered by existing tests)\r\n- [x] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3132/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3132/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3127", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3127/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3127/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3127/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3127", + "id": 3033489921, + "node_id": "PR_kwDOADL-3s6Uny5a", + "number": 3127, + "title": "Fix incorrect deskolemization of literals", + "user": { + "login": "ddeschepper", + "id": 1130183, + "node_id": "MDQ6VXNlcjExMzAxODM=", + "avatar_url": "https://avatars.githubusercontent.com/u/1130183?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/ddeschepper", + "html_url": "https://github.com/ddeschepper", + "followers_url": "https://api.github.com/users/ddeschepper/followers", + "following_url": "https://api.github.com/users/ddeschepper/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/ddeschepper/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/ddeschepper/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/ddeschepper/subscriptions", + "organizations_url": "https://api.github.com/users/ddeschepper/orgs", + "repos_url": "https://api.github.com/users/ddeschepper/repos", + "events_url": "https://api.github.com/users/ddeschepper/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/ddeschepper/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-05-01T09:16:35Z", + "updated_at": "2025-09-18T05:02:33Z", + "closed_at": "2025-09-18T05:02:33Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3127", + "html_url": "https://github.com/RDFLib/rdflib/pull/3127", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3127.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3127.patch", + "merged_at": "2025-09-18T05:02:33Z" + }, + "body": "Fixes issue https://github.com/RDFLib/rdflib/issues/3126.\r\n\r\nGraph.de_skolemize() incorrectly tries to deskolemize literals, which fails in some edge cases. Limiting deskolemization of objects to `URIRef`s only fixes this behaviour.", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3127/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3127/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3121", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3121/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3121/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3121/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3121", + "id": 3023781553, + "node_id": "PR_kwDOADL-3s6UGzEk", + "number": 3121, + "title": "build(deps-dev): bump typing-extensions from 4.13.0 to 4.13.2", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-04-28T05:53:17Z", + "updated_at": "2025-05-31T09:46:31Z", + "closed_at": "2025-05-31T09:46:29Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3121", + "html_url": "https://github.com/RDFLib/rdflib/pull/3121", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3121.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3121.patch", + "merged_at": "2025-05-31T09:46:29Z" + }, + "body": "Bumps [typing-extensions](https://github.com/python/typing_extensions) from 4.13.0 to 4.13.2.\n
\nRelease notes\n

Sourced from typing-extensions's releases.

\n
\n

4.13.2

\n
    \n
  • Fix TypeError when taking the union of typing_extensions.TypeAliasType and a\ntyping.TypeAliasType on Python 3.12 and 3.13.\nPatch by Joren Hammudoglu.
  • \n
  • Backport from CPython PR #132160\nto avoid having user arguments shadowed in generated __new__ by\n@typing_extensions.deprecated.\nPatch by Victorien Plot.
  • \n
\n

4.13.1

\n

This is a bugfix release fixing two edge cases that appear on old bugfix releases of CPython.

\n

Bugfixes:

\n
    \n
  • Fix regression in 4.13.0 on Python 3.10.2 causing a TypeError when using Concatenate.\nPatch by Daraan.
  • \n
  • Fix TypeError when using evaluate_forward_ref on Python 3.10.1-2 and 3.9.8-10.\nPatch by Daraan.
  • \n
\n
\n
\n
\nChangelog\n

Sourced from typing-extensions's changelog.

\n
\n

Release 4.13.2 (April 10, 2025)

\n
    \n
  • Fix TypeError when taking the union of typing_extensions.TypeAliasType and a\ntyping.TypeAliasType on Python 3.12 and 3.13.\nPatch by Joren Hammudoglu.
  • \n
  • Backport from CPython PR #132160\nto avoid having user arguments shadowed in generated __new__ by\n@typing_extensions.deprecated.\nPatch by Victorien Plot.
  • \n
\n

Release 4.13.1 (April 3, 2025)

\n

Bugfixes:

\n
    \n
  • Fix regression in 4.13.0 on Python 3.10.2 causing a TypeError when using Concatenate.\nPatch by Daraan.
  • \n
  • Fix TypeError when using evaluate_forward_ref on Python 3.10.1-2 and 3.9.8-10.\nPatch by Daraan.
  • \n
\n
\n
\n
\nCommits\n
    \n
  • 4525e9d Prepare release 4.13.2 (#583)
  • \n
  • 88a0c20 Do not shadow user arguments in generated __new__ by @deprecated (#581)
  • \n
  • 281d7b0 Add 3rd party tests for litestar (#578)
  • \n
  • 8092c39 fix TypeAliasType union with typing.TypeAliasType (#575)
  • \n
  • 45a8847 Prepare release 4.13.1 (#573)
  • \n
  • f264e58 Move CI to "ubuntu-latest" (round 2) (#570)
  • \n
  • 5ce0e69 Fix TypeError with evaluate_forward_ref on some 3.10 and 3.9 versions (#558)
  • \n
  • 304f5cb Add SQLAlchemy to third-party daily tests (#561)
  • \n
  • ebe2b94 Fix duplicated keywords for typing._ConcatenateGenericAlias in 3.10.2 (#557)
  • \n
  • 9f93d6f Add intersphinx links for 3.13 typing features (#550)
  • \n
  • See full diff in compare view
  • \n
\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typing-extensions&package-manager=pip&previous-version=4.13.0&new-version=4.13.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3121/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3121/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3118", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3118/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3118/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3118/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3118", + "id": 3007735442, + "node_id": "PR_kwDOADL-3s6TQzkU", + "number": 3118, + "title": "build(deps): bump library/python from 3.13.1-slim@sha256:1127090f9fff0b8e7c3a1367855ef8a3299472d2c9ed122948a576c39addeaf1 to sha256:34dc8eb488136014caf530ec03a3a2403473a92d67a01a26256c365b5b2fc0d4 in /docker/unstable", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4545133062, + "node_id": "LA_kwDOADL-3s8AAAABDuk6Bg", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/docker", + "name": "docker", + "color": "21ceff", + "default": false, + "description": "Pull requests that update Docker code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-04-21T06:55:35Z", + "updated_at": "2025-05-31T09:43:35Z", + "closed_at": "2025-05-31T09:43:28Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3118", + "html_url": "https://github.com/RDFLib/rdflib/pull/3118", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3118.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3118.patch", + "merged_at": "2025-05-31T09:43:28Z" + }, + "body": "Bumps library/python from 3.13.1-slim@sha256:1127090f9fff0b8e7c3a1367855ef8a3299472d2c9ed122948a576c39addeaf1 to sha256:34dc8eb488136014caf530ec03a3a2403473a92d67a01a26256c365b5b2fc0d4.\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=library/python&package-manager=docker&previous-version=3.13.1-slim@sha256:1127090f9fff0b8e7c3a1367855ef8a3299472d2c9ed122948a576c39addeaf1&new-version=sha256:34dc8eb488136014caf530ec03a3a2403473a92d67a01a26256c365b5b2fc0d4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nYou can trigger a rebase of this PR by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
\n\n> **Note**\n> Automatic rebases have been disabled on this pull request as it has been open for over 30 days.\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3118/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3118/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3117", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3117/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3117/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3117/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3117", + "id": 3007648012, + "node_id": "PR_kwDOADL-3s6TQgTc", + "number": 3117, + "title": "build(deps): bump library/python from 3.13.1-slim@sha256:1127090f9fff0b8e7c3a1367855ef8a3299472d2c9ed122948a576c39addeaf1 to sha256:34dc8eb488136014caf530ec03a3a2403473a92d67a01a26256c365b5b2fc0d4 in /docker/latest", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4545133062, + "node_id": "LA_kwDOADL-3s8AAAABDuk6Bg", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/docker", + "name": "docker", + "color": "21ceff", + "default": false, + "description": "Pull requests that update Docker code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-04-21T06:06:30Z", + "updated_at": "2025-05-31T09:42:54Z", + "closed_at": "2025-05-31T09:42:52Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3117", + "html_url": "https://github.com/RDFLib/rdflib/pull/3117", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3117.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3117.patch", + "merged_at": "2025-05-31T09:42:52Z" + }, + "body": "Bumps library/python from 3.13.1-slim@sha256:1127090f9fff0b8e7c3a1367855ef8a3299472d2c9ed122948a576c39addeaf1 to sha256:34dc8eb488136014caf530ec03a3a2403473a92d67a01a26256c365b5b2fc0d4.\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=library/python&package-manager=docker&previous-version=3.13.1-slim@sha256:1127090f9fff0b8e7c3a1367855ef8a3299472d2c9ed122948a576c39addeaf1&new-version=sha256:34dc8eb488136014caf530ec03a3a2403473a92d67a01a26256c365b5b2fc0d4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3117/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3117/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3115", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3115/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3115/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3115/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3115", + "id": 2999054664, + "node_id": "PR_kwDOADL-3s6Szxae", + "number": 3115, + "title": "fix: remove Literal.toPython date conversion for gYear/gYearMonth", + "user": { + "login": "lu-pl", + "id": 128675670, + "node_id": "U_kgDOB6tvVg", + "avatar_url": "https://avatars.githubusercontent.com/u/128675670?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/lu-pl", + "html_url": "https://github.com/lu-pl", + "followers_url": "https://api.github.com/users/lu-pl/followers", + "following_url": "https://api.github.com/users/lu-pl/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/lu-pl/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/lu-pl/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/lu-pl/subscriptions", + "organizations_url": "https://api.github.com/users/lu-pl/orgs", + "repos_url": "https://api.github.com/users/lu-pl/repos", + "events_url": "https://api.github.com/users/lu-pl/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/lu-pl/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 1, + "created_at": "2025-04-16T09:34:25Z", + "updated_at": "2025-05-31T09:51:02Z", + "closed_at": "2025-05-31T09:51:02Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3115", + "html_url": "https://github.com/RDFLib/rdflib/pull/3115", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3115.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3115.patch", + "merged_at": "2025-05-31T09:51:02Z" + }, + "body": "\r\n\r\n# Summary of changes\r\n\r\nIssue #3078 reports, that `rdflib.Literal.toPython`-casting of `xsd:gYear` and `xsd:gYearMonth` to datetime objects should not be possible, as there is no appropriate Python equivalence for those types. \r\n\r\nThe current implementation casts `xsd:gYear` and `xsd:gYearMonth` to datetime objects assuming January 1st for `xsd:gYear` and the 1st day of the given month for `xsd:gYearMonth`. This is plain wrong.\r\n\r\nThe change removes datetime casting for `xsd:gYear` and `xsd:gYearMonth` for `rdflib.Literal.toPython` and adapts the `rdflib.Literal` tests accordingly.\r\n\r\nNote that validation of `xsd:gYear` and `xsd:gYearMonth` is lost as a result, but could be easily implemented using regex checks. As I understand it, XSD types without an entry in the `rdflib.term.XSDToPython` mapping are never typed-checked though; at least for `xsd:gYear` and `xsd:gYearMonth` the xsd-type checks ran as part of `rdflib.xsd_datetime.parse_xsd_gyear` and `rdflib.xsd_datetime.parse_xsd_gyearmonth`. \r\n\r\n\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [x] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [x] Checked that all tests and type checking passes.\r\n- If the change adds new features or changes the RDFLib public API:\r\n \r\n - [x] Created an issue to discuss the change and get in-principle agreement.\r\n - [] Considered adding an example in `./examples`.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [x] Added or updated tests that fail without the change.\r\n - [x] Updated relevant documentation to avoid inaccuracies.\r\n - [x] Considered adding additional documentation.\r\n- [x] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\nNote: I looked through the docs and couldn't find a place where `xsd:gYear` or `xsd:gYearMonth` casting was mentioned (apart from the generated references).", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3115/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3115/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3106", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3106/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3106/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3106/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3106", + "id": 2961384878, + "node_id": "PR_kwDOADL-3s6Q0v6d", + "number": 3106, + "title": "fix namespace prefixes in longturtle serialization", + "user": { + "login": "ddeschepper", + "id": 1130183, + "node_id": "MDQ6VXNlcjExMzAxODM=", + "avatar_url": "https://avatars.githubusercontent.com/u/1130183?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/ddeschepper", + "html_url": "https://github.com/ddeschepper", + "followers_url": "https://api.github.com/users/ddeschepper/followers", + "following_url": "https://api.github.com/users/ddeschepper/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/ddeschepper/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/ddeschepper/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/ddeschepper/subscriptions", + "organizations_url": "https://api.github.com/users/ddeschepper/orgs", + "repos_url": "https://api.github.com/users/ddeschepper/repos", + "events_url": "https://api.github.com/users/ddeschepper/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/ddeschepper/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 3, + "created_at": "2025-03-31T19:28:56Z", + "updated_at": "2025-05-31T09:47:31Z", + "closed_at": "2025-05-31T09:47:31Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3106", + "html_url": "https://github.com/RDFLib/rdflib/pull/3106", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3106.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3106.patch", + "merged_at": "2025-05-31T09:47:31Z" + }, + "body": "\r\n\r\n# Summary of changes\r\n\r\n\r\n\r\nSolves https://github.com/RDFLib/rdflib/issues/3105 by storing the namespace manager of the graph that is to be serialized temporarily and reapplying it to the graph that is actually serialized by the implementation of the longturtle serializer.\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [x] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [x] Checked that all tests and type checking passes.\r\n- If the change has a potential impact on users of this project:\r\n \r\n - [x] Added or updated tests that fail without the change.\r\n - [ ] Updated relevant documentation to avoid inaccuracies.\r\n - [ ] Considered adding additional documentation.\r\n- [x] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3106/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3106/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3101", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3101/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3101/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3101/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3101", + "id": 2957748383, + "node_id": "PR_kwDOADL-3s6QpJbk", + "number": 3101, + "title": "build(deps): bump rdflib from 7.1.2 to 7.1.4 in /docker/latest", + "user": { + "login": "dependabot[bot]", + "id": 49699333, + "node_id": "MDM6Qm90NDk2OTkzMzM=", + "avatar_url": "https://avatars.githubusercontent.com/in/29110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/dependabot%5Bbot%5D", + "html_url": "https://github.com/apps/dependabot", + "followers_url": "https://api.github.com/users/dependabot%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/dependabot%5Bbot%5D/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/dependabot%5Bbot%5D/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/dependabot%5Bbot%5D/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/dependabot%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/dependabot%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/dependabot%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/dependabot%5Bbot%5D/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/dependabot%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 1999840232, + "node_id": "MDU6TGFiZWwxOTk5ODQwMjMy", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/dependencies", + "name": "dependencies", + "color": "0366d6", + "default": false, + "description": "Pull requests that update a dependency file" + }, + { + "id": 4181259078, + "node_id": "LA_kwDOADL-3s75OPNG", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/python", + "name": "python", + "color": "2b67c6", + "default": false, + "description": "Pull requests that update Python code" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-03-29T04:48:39Z", + "updated_at": "2025-05-27T03:04:02Z", + "closed_at": "2025-05-27T03:04:01Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3101", + "html_url": "https://github.com/RDFLib/rdflib/pull/3101", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3101.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3101.patch", + "merged_at": "2025-05-27T03:04:01Z" + }, + "body": "Bumps [rdflib](https://github.com/RDFLib/rdflib) from 7.1.2 to 7.1.4.\n
\nRelease notes\n

Sourced from rdflib's releases.

\n
\n

2025-03-29 RELEASE 7.1.4

\n

A tidy-up release with no major updates over 7.1.3. This may be the last 7.x release as we move to a version 8 with breaking changes to Dataset and a few APIs.

\n

Interesting PRs merged:

\n\n

... and lots of boring dependency bump PRs merged!

\n

2025-01-18 RELEASE 7.1.3

\n

A fix-up release that re-adds support for Python 3.8 after it was accidentally\nremoved in Release 7.1.2.

\n

This release cherrypicks many additions to 7.1.2 added to 7.1.1 but leaves out\ntyping changes that are not compatible\nwith Python 3.8.

\n

Also not carried over from 7.1.2 is the change from Poetry 1.x to 2.0.

\n

Included are PRs such as Defined Namespace warnings fix, sort longturtle\nblank nodes, deterministic longturtle serialisation and Dataset documentation\nimprovements.

\n
\n
\n
\nChangelog\n

Sourced from rdflib's changelog.

\n
\n

2025-03-29 RELEASE 7.1.4

\n

A tidy-up release with no major updates over 7.1.3. This may be the last 7.x\nrelease as we move to a version 8 with breaking changes to Dataset and a few\nAPIs.

\n

Interesting PRs merged:

\n\n

... and lots of boring dependency bump PRs merged!

\n

2025-01-17 RELEASE 7.1.3

\n

A fix-up release that re-adds support for Python 3.8 after it was accidentally\nremoved in Release 7.1.2.

\n

This release cherrypicks many additions to 7.1.2 added to 7.1.1 but leaves out\ntyping changes that are not compatible\nwith Python 3.8.

\n

Also not carried over from 7.1.2 is the change from Poetry 1.x to 2.0.

\n

Included are PRs such as Defined Namespace warnings fix, sort longturtle\nblank nodes, deterministic longturtle serialisation and Dataset documentation\nimprovements.

\n

For the full list of included PRs, see the preparatory PR:\nRDFLib/rdflib#3036.

\n
\n
\n
\nCommits\n\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rdflib&package-manager=pip&previous-version=7.1.2&new-version=7.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3101/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3101/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3098", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3098/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3098/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3098/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3098", + "id": 2957658627, + "node_id": "PR_kwDOADL-3s6Qo2lb", + "number": 3098, + "title": "7.1.4 pre-release", + "user": { + "login": "nicholascar", + "id": 7321872, + "node_id": "MDQ6VXNlcjczMjE4NzI=", + "avatar_url": "https://avatars.githubusercontent.com/u/7321872?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/nicholascar", + "html_url": "https://github.com/nicholascar", + "followers_url": "https://api.github.com/users/nicholascar/followers", + "following_url": "https://api.github.com/users/nicholascar/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/nicholascar/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/nicholascar/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/nicholascar/subscriptions", + "organizations_url": "https://api.github.com/users/nicholascar/orgs", + "repos_url": "https://api.github.com/users/nicholascar/repos", + "events_url": "https://api.github.com/users/nicholascar/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/nicholascar/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2025-03-29T02:09:03Z", + "updated_at": "2025-03-29T02:19:06Z", + "closed_at": "2025-03-29T02:19:05Z", + "author_association": "MEMBER", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3098", + "html_url": "https://github.com/RDFLib/rdflib/pull/3098", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3098.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3098.patch", + "merged_at": "2025-03-29T02:19:05Z" + }, + "body": "A tidy-up release with no major updates over 7.1.3. This may be the last 7.x release as we move to a version 8 with breaking changes to Dataset and a few APIs.\r\n\r\nFixed some small pre-commit issues too", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3098/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3098/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3075", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3075/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3075/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3075/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3075", + "id": 2869027589, + "node_id": "PR_kwDOADL-3s6MDLLC", + "number": 3075, + "title": "Specify `Optional` parameters in `Graph.triples_choices`", + "user": { + "login": "slahn", + "id": 3298124, + "node_id": "MDQ6VXNlcjMyOTgxMjQ=", + "avatar_url": "https://avatars.githubusercontent.com/u/3298124?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/slahn", + "html_url": "https://github.com/slahn", + "followers_url": "https://api.github.com/users/slahn/followers", + "following_url": "https://api.github.com/users/slahn/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/slahn/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/slahn/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/slahn/subscriptions", + "organizations_url": "https://api.github.com/users/slahn/orgs", + "repos_url": "https://api.github.com/users/slahn/repos", + "events_url": "https://api.github.com/users/slahn/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/slahn/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [ + { + "id": 7242799529, + "node_id": "LA_kwDOADL-3s8AAAABr7RZqQ", + "url": "https://api.github.com/repos/RDFLib/rdflib/labels/7.1", + "name": "7.1", + "color": "FC7848", + "default": false, + "description": "Issues planned to fix in v7.1" + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 2, + "created_at": "2025-02-21T13:26:01Z", + "updated_at": "2025-09-03T04:59:58Z", + "closed_at": "2025-09-03T04:59:58Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3075", + "html_url": "https://github.com/RDFLib/rdflib/pull/3075", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3075.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3075.patch", + "merged_at": "2025-09-03T04:59:58Z" + }, + "body": "\r\n\r\n# Summary of changes\r\n\r\nChange the typing of `Graph.triples_choices` and `Store.triples_choises`\r\nto match the actual types allowed by the code.\r\n\r\nThe two non-list parameters can be `None`, but this is not reflected in\r\nthe type hint today.\r\n\r\nIntroduce a type alias to simplify method signatures, and update all\r\noverloads of `triples_choises` to use this alias.\r\n\r\n\r\n\r\n# Checklist\r\n\r\n\r\n\r\n- [\u2713] Checked that there aren't other open pull requests for\r\n the same change.\r\n- [\u2713] Checked that all tests and type checking passes.\r\n - Did not run webtests (`pytest -m \"not webtest\"`), since I could not get them working at all.\r\n `7266 passed, 61 skipped, 333 deselected, 330 xfailed, 36 xpassed, 6925 warnings`\r\n- [\u2713] Considered granting [push permissions to the PR branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork),\r\n so maintainers can fix minor issues and keep your PR up to date.\r\n\r\n", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3075/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3075/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + }, + { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3020", + "repository_url": "https://api.github.com/repos/RDFLib/rdflib", + "labels_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3020/labels%7B/name%7D", + "comments_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3020/comments", + "events_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3020/events", + "html_url": "https://github.com/RDFLib/rdflib/pull/3020", + "id": 2769455166, + "node_id": "PR_kwDOADL-3s6GwndC", + "number": 3020, + "title": "notation3.py: don't normalize float representation", + "user": { + "login": "tgbugs", + "id": 4299776, + "node_id": "MDQ6VXNlcjQyOTk3NzY=", + "avatar_url": "https://avatars.githubusercontent.com/u/4299776?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/tgbugs", + "html_url": "https://github.com/tgbugs", + "followers_url": "https://api.github.com/users/tgbugs/followers", + "following_url": "https://api.github.com/users/tgbugs/following%7B/other_user%7D", + "gists_url": "https://api.github.com/users/tgbugs/gists%7B/gist_id%7D", + "starred_url": "https://api.github.com/users/tgbugs/starred%7B/owner%7D%7B/repo%7D", + "subscriptions_url": "https://api.github.com/users/tgbugs/subscriptions", + "organizations_url": "https://api.github.com/users/tgbugs/orgs", + "repos_url": "https://api.github.com/users/tgbugs/repos", + "events_url": "https://api.github.com/users/tgbugs/events%7B/privacy%7D", + "received_events_url": "https://api.github.com/users/tgbugs/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "labels": [], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 5, + "created_at": "2025-01-05T21:21:48Z", + "updated_at": "2025-09-18T04:19:43Z", + "closed_at": "2025-09-18T04:19:43Z", + "author_association": "CONTRIBUTOR", + "type": null, + "active_lock_reason": null, + "draft": false, + "pull_request": { + "url": "https://api.github.com/repos/RDFLib/rdflib/pulls/3020", + "html_url": "https://github.com/RDFLib/rdflib/pull/3020", + "diff_url": "https://github.com/RDFLib/rdflib/pull/3020.diff", + "patch_url": "https://github.com/RDFLib/rdflib/pull/3020.patch", + "merged_at": "2025-09-18T04:19:43Z" + }, + "body": "fix behavior of the n3 parser family to avoid normalizing raw float string representation which makes it impossible to roundtrip the exact original string representation of e.g. `1e10`", + "reactions": { + "url": "https://api.github.com/repos/RDFLib/rdflib/issues/3020/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "timeline_url": "https://api.github.com/repos/RDFLib/rdflib/issues/3020/timeline", + "performed_via_github_app": null, + "state_reason": null, + "score": 1.0 + } +] \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index c2d3eb897..8622bb56c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "alabaster" @@ -340,21 +340,15 @@ test = ["pytest (>=6)"] [[package]] name = "html5rdf" -version = "1.2" +version = "1.2.1" description = "HTML parser based on the WHATWG HTML specification" optional = true python-versions = ">=3.8" files = [ - {file = "html5rdf-1.2-py2.py3-none-any.whl", hash = "sha256:08169aa52a98ee3a6d3456d83feb36211fb5edcbcf3e05f6d19e0136f581638c"}, - {file = "html5rdf-1.2.tar.gz", hash = "sha256:08378cbbbb63993ba7bb5eb1eac44bf9ca7b1a23dbee3d2afef5376597fb00a5"}, + {file = "html5rdf-1.2.1-py2.py3-none-any.whl", hash = "sha256:1f519121bc366af3e485310dc8041d2e86e5173c1a320fac3dc9d2604069b83e"}, + {file = "html5rdf-1.2.1.tar.gz", hash = "sha256:ace9b420ce52995bb4f05e7425eedf19e433c981dfe7a831ab391e2fa2e1a195"}, ] -[package.extras] -all = ["chardet (>=2.2.1)", "genshi (>=0.7.1)", "lxml (>=3.4.0)"] -chardet = ["chardet (>=2.2.1)"] -genshi = ["genshi (>=0.7.1)"] -lxml = ["lxml (>=3.4.0)"] - [[package]] name = "idna" version = "3.4" @@ -437,157 +431,157 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "lxml" -version = "5.3.0" +version = "5.3.1" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = true python-versions = ">=3.6" files = [ - {file = "lxml-5.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:dd36439be765e2dde7660212b5275641edbc813e7b24668831a5c8ac91180656"}, - {file = "lxml-5.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ae5fe5c4b525aa82b8076c1a59d642c17b6e8739ecf852522c6321852178119d"}, - {file = "lxml-5.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:501d0d7e26b4d261fca8132854d845e4988097611ba2531408ec91cf3fd9d20a"}, - {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66442c2546446944437df74379e9cf9e9db353e61301d1a0e26482f43f0dd8"}, - {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e41506fec7a7f9405b14aa2d5c8abbb4dbbd09d88f9496958b6d00cb4d45330"}, - {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f7d4a670107d75dfe5ad080bed6c341d18c4442f9378c9f58e5851e86eb79965"}, - {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41ce1f1e2c7755abfc7e759dc34d7d05fd221723ff822947132dc934d122fe22"}, - {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:44264ecae91b30e5633013fb66f6ddd05c006d3e0e884f75ce0b4755b3e3847b"}, - {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:3c174dc350d3ec52deb77f2faf05c439331d6ed5e702fc247ccb4e6b62d884b7"}, - {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:2dfab5fa6a28a0b60a20638dc48e6343c02ea9933e3279ccb132f555a62323d8"}, - {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b1c8c20847b9f34e98080da785bb2336ea982e7f913eed5809e5a3c872900f32"}, - {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2c86bf781b12ba417f64f3422cfc302523ac9cd1d8ae8c0f92a1c66e56ef2e86"}, - {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c162b216070f280fa7da844531169be0baf9ccb17263cf5a8bf876fcd3117fa5"}, - {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:36aef61a1678cb778097b4a6eeae96a69875d51d1e8f4d4b491ab3cfb54b5a03"}, - {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f65e5120863c2b266dbcc927b306c5b78e502c71edf3295dfcb9501ec96e5fc7"}, - {file = "lxml-5.3.0-cp310-cp310-win32.whl", hash = "sha256:ef0c1fe22171dd7c7c27147f2e9c3e86f8bdf473fed75f16b0c2e84a5030ce80"}, - {file = "lxml-5.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:052d99051e77a4f3e8482c65014cf6372e61b0a6f4fe9edb98503bb5364cfee3"}, - {file = "lxml-5.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74bcb423462233bc5d6066e4e98b0264e7c1bed7541fff2f4e34fe6b21563c8b"}, - {file = "lxml-5.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a3d819eb6f9b8677f57f9664265d0a10dd6551d227afb4af2b9cd7bdc2ccbf18"}, - {file = "lxml-5.3.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b8f5db71b28b8c404956ddf79575ea77aa8b1538e8b2ef9ec877945b3f46442"}, - {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3406b63232fc7e9b8783ab0b765d7c59e7c59ff96759d8ef9632fca27c7ee4"}, - {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ecdd78ab768f844c7a1d4a03595038c166b609f6395e25af9b0f3f26ae1230f"}, - {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168f2dfcfdedf611eb285efac1516c8454c8c99caf271dccda8943576b67552e"}, - {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa617107a410245b8660028a7483b68e7914304a6d4882b5ff3d2d3eb5948d8c"}, - {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:69959bd3167b993e6e710b99051265654133a98f20cec1d9b493b931942e9c16"}, - {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:bd96517ef76c8654446fc3db9242d019a1bb5fe8b751ba414765d59f99210b79"}, - {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:ab6dd83b970dc97c2d10bc71aa925b84788c7c05de30241b9e96f9b6d9ea3080"}, - {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eec1bb8cdbba2925bedc887bc0609a80e599c75b12d87ae42ac23fd199445654"}, - {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a7095eeec6f89111d03dabfe5883a1fd54da319c94e0fb104ee8f23616b572d"}, - {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6f651ebd0b21ec65dfca93aa629610a0dbc13dbc13554f19b0113da2e61a4763"}, - {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:f422a209d2455c56849442ae42f25dbaaba1c6c3f501d58761c619c7836642ec"}, - {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:62f7fdb0d1ed2065451f086519865b4c90aa19aed51081979ecd05a21eb4d1be"}, - {file = "lxml-5.3.0-cp311-cp311-win32.whl", hash = "sha256:c6379f35350b655fd817cd0d6cbeef7f265f3ae5fedb1caae2eb442bbeae9ab9"}, - {file = "lxml-5.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c52100e2c2dbb0649b90467935c4b0de5528833c76a35ea1a2691ec9f1ee7a1"}, - {file = "lxml-5.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e99f5507401436fdcc85036a2e7dc2e28d962550afe1cbfc07c40e454256a859"}, - {file = "lxml-5.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:384aacddf2e5813a36495233b64cb96b1949da72bef933918ba5c84e06af8f0e"}, - {file = "lxml-5.3.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a216bf6afaf97c263b56371434e47e2c652d215788396f60477540298218f"}, - {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65ab5685d56914b9a2a34d67dd5488b83213d680b0c5d10b47f81da5a16b0b0e"}, - {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aac0bbd3e8dd2d9c45ceb82249e8bdd3ac99131a32b4d35c8af3cc9db1657179"}, - {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b369d3db3c22ed14c75ccd5af429086f166a19627e84a8fdade3f8f31426e52a"}, - {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c24037349665434f375645fa9d1f5304800cec574d0310f618490c871fd902b3"}, - {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:62d172f358f33a26d6b41b28c170c63886742f5b6772a42b59b4f0fa10526cb1"}, - {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:c1f794c02903c2824fccce5b20c339a1a14b114e83b306ff11b597c5f71a1c8d"}, - {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:5d6a6972b93c426ace71e0be9a6f4b2cfae9b1baed2eed2006076a746692288c"}, - {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:3879cc6ce938ff4eb4900d901ed63555c778731a96365e53fadb36437a131a99"}, - {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:74068c601baff6ff021c70f0935b0c7bc528baa8ea210c202e03757c68c5a4ff"}, - {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ecd4ad8453ac17bc7ba3868371bffb46f628161ad0eefbd0a855d2c8c32dd81a"}, - {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7e2f58095acc211eb9d8b5771bf04df9ff37d6b87618d1cbf85f92399c98dae8"}, - {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e63601ad5cd8f860aa99d109889b5ac34de571c7ee902d6812d5d9ddcc77fa7d"}, - {file = "lxml-5.3.0-cp312-cp312-win32.whl", hash = "sha256:17e8d968d04a37c50ad9c456a286b525d78c4a1c15dd53aa46c1d8e06bf6fa30"}, - {file = "lxml-5.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:c1a69e58a6bb2de65902051d57fde951febad631a20a64572677a1052690482f"}, - {file = "lxml-5.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c72e9563347c7395910de6a3100a4840a75a6f60e05af5e58566868d5eb2d6a"}, - {file = "lxml-5.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e92ce66cd919d18d14b3856906a61d3f6b6a8500e0794142338da644260595cd"}, - {file = "lxml-5.3.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d04f064bebdfef9240478f7a779e8c5dc32b8b7b0b2fc6a62e39b928d428e51"}, - {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c2fb570d7823c2bbaf8b419ba6e5662137f8166e364a8b2b91051a1fb40ab8b"}, - {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c120f43553ec759f8de1fee2f4794452b0946773299d44c36bfe18e83caf002"}, - {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:562e7494778a69086f0312ec9689f6b6ac1c6b65670ed7d0267e49f57ffa08c4"}, - {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:423b121f7e6fa514ba0c7918e56955a1d4470ed35faa03e3d9f0e3baa4c7e492"}, - {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c00f323cc00576df6165cc9d21a4c21285fa6b9989c5c39830c3903dc4303ef3"}, - {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:1fdc9fae8dd4c763e8a31e7630afef517eab9f5d5d31a278df087f307bf601f4"}, - {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:658f2aa69d31e09699705949b5fc4719cbecbd4a97f9656a232e7d6c7be1a367"}, - {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1473427aff3d66a3fa2199004c3e601e6c4500ab86696edffdbc84954c72d832"}, - {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a87de7dd873bf9a792bf1e58b1c3887b9264036629a5bf2d2e6579fe8e73edff"}, - {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0d7b36afa46c97875303a94e8f3ad932bf78bace9e18e603f2085b652422edcd"}, - {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:cf120cce539453ae086eacc0130a324e7026113510efa83ab42ef3fcfccac7fb"}, - {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:df5c7333167b9674aa8ae1d4008fa4bc17a313cc490b2cca27838bbdcc6bb15b"}, - {file = "lxml-5.3.0-cp313-cp313-win32.whl", hash = "sha256:c802e1c2ed9f0c06a65bc4ed0189d000ada8049312cfeab6ca635e39c9608957"}, - {file = "lxml-5.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:406246b96d552e0503e17a1006fd27edac678b3fcc9f1be71a2f94b4ff61528d"}, - {file = "lxml-5.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8f0de2d390af441fe8b2c12626d103540b5d850d585b18fcada58d972b74a74e"}, - {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1afe0a8c353746e610bd9031a630a95bcfb1a720684c3f2b36c4710a0a96528f"}, - {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56b9861a71575f5795bde89256e7467ece3d339c9b43141dbdd54544566b3b94"}, - {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:9fb81d2824dff4f2e297a276297e9031f46d2682cafc484f49de182aa5e5df99"}, - {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2c226a06ecb8cdef28845ae976da407917542c5e6e75dcac7cc33eb04aaeb237"}, - {file = "lxml-5.3.0-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:7d3d1ca42870cdb6d0d29939630dbe48fa511c203724820fc0fd507b2fb46577"}, - {file = "lxml-5.3.0-cp36-cp36m-win32.whl", hash = "sha256:094cb601ba9f55296774c2d57ad68730daa0b13dc260e1f941b4d13678239e70"}, - {file = "lxml-5.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:eafa2c8658f4e560b098fe9fc54539f86528651f61849b22111a9b107d18910c"}, - {file = "lxml-5.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cb83f8a875b3d9b458cada4f880fa498646874ba4011dc974e071a0a84a1b033"}, - {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25f1b69d41656b05885aa185f5fdf822cb01a586d1b32739633679699f220391"}, - {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23e0553b8055600b3bf4a00b255ec5c92e1e4aebf8c2c09334f8368e8bd174d6"}, - {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ada35dd21dc6c039259596b358caab6b13f4db4d4a7f8665764d616daf9cc1d"}, - {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:81b4e48da4c69313192d8c8d4311e5d818b8be1afe68ee20f6385d0e96fc9512"}, - {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:2bc9fd5ca4729af796f9f59cd8ff160fe06a474da40aca03fcc79655ddee1a8b"}, - {file = "lxml-5.3.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:07da23d7ee08577760f0a71d67a861019103e4812c87e2fab26b039054594cc5"}, - {file = "lxml-5.3.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:ea2e2f6f801696ad7de8aec061044d6c8c0dd4037608c7cab38a9a4d316bfb11"}, - {file = "lxml-5.3.0-cp37-cp37m-win32.whl", hash = "sha256:5c54afdcbb0182d06836cc3d1be921e540be3ebdf8b8a51ee3ef987537455f84"}, - {file = "lxml-5.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f2901429da1e645ce548bf9171784c0f74f0718c3f6150ce166be39e4dd66c3e"}, - {file = "lxml-5.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c56a1d43b2f9ee4786e4658c7903f05da35b923fb53c11025712562d5cc02753"}, - {file = "lxml-5.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ee8c39582d2652dcd516d1b879451500f8db3fe3607ce45d7c5957ab2596040"}, - {file = "lxml-5.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdf3a3059611f7585a78ee10399a15566356116a4288380921a4b598d807a22"}, - {file = "lxml-5.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:146173654d79eb1fc97498b4280c1d3e1e5d58c398fa530905c9ea50ea849b22"}, - {file = "lxml-5.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:0a7056921edbdd7560746f4221dca89bb7a3fe457d3d74267995253f46343f15"}, - {file = "lxml-5.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:9e4b47ac0f5e749cfc618efdf4726269441014ae1d5583e047b452a32e221920"}, - {file = "lxml-5.3.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f914c03e6a31deb632e2daa881fe198461f4d06e57ac3d0e05bbcab8eae01945"}, - {file = "lxml-5.3.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:213261f168c5e1d9b7535a67e68b1f59f92398dd17a56d934550837143f79c42"}, - {file = "lxml-5.3.0-cp38-cp38-win32.whl", hash = "sha256:218c1b2e17a710e363855594230f44060e2025b05c80d1f0661258142b2add2e"}, - {file = "lxml-5.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:315f9542011b2c4e1d280e4a20ddcca1761993dda3afc7a73b01235f8641e903"}, - {file = "lxml-5.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1ffc23010330c2ab67fac02781df60998ca8fe759e8efde6f8b756a20599c5de"}, - {file = "lxml-5.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2b3778cb38212f52fac9fe913017deea2fdf4eb1a4f8e4cfc6b009a13a6d3fcc"}, - {file = "lxml-5.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b0c7a688944891086ba192e21c5229dea54382f4836a209ff8d0a660fac06be"}, - {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:747a3d3e98e24597981ca0be0fd922aebd471fa99d0043a3842d00cdcad7ad6a"}, - {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86a6b24b19eaebc448dc56b87c4865527855145d851f9fc3891673ff97950540"}, - {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b11a5d918a6216e521c715b02749240fb07ae5a1fefd4b7bf12f833bc8b4fe70"}, - {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68b87753c784d6acb8a25b05cb526c3406913c9d988d51f80adecc2b0775d6aa"}, - {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:109fa6fede314cc50eed29e6e56c540075e63d922455346f11e4d7a036d2b8cf"}, - {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:02ced472497b8362c8e902ade23e3300479f4f43e45f4105c85ef43b8db85229"}, - {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:6b038cc86b285e4f9fea2ba5ee76e89f21ed1ea898e287dc277a25884f3a7dfe"}, - {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:7437237c6a66b7ca341e868cda48be24b8701862757426852c9b3186de1da8a2"}, - {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7f41026c1d64043a36fda21d64c5026762d53a77043e73e94b71f0521939cc71"}, - {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:482c2f67761868f0108b1743098640fbb2a28a8e15bf3f47ada9fa59d9fe08c3"}, - {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:1483fd3358963cc5c1c9b122c80606a3a79ee0875bcac0204149fa09d6ff2727"}, - {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2dec2d1130a9cda5b904696cec33b2cfb451304ba9081eeda7f90f724097300a"}, - {file = "lxml-5.3.0-cp39-cp39-win32.whl", hash = "sha256:a0eabd0a81625049c5df745209dc7fcef6e2aea7793e5f003ba363610aa0a3ff"}, - {file = "lxml-5.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:89e043f1d9d341c52bf2af6d02e6adde62e0a46e6755d5eb60dc6e4f0b8aeca2"}, - {file = "lxml-5.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7b1cd427cb0d5f7393c31b7496419da594fe600e6fdc4b105a54f82405e6626c"}, - {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51806cfe0279e06ed8500ce19479d757db42a30fd509940b1701be9c86a5ff9a"}, - {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee70d08fd60c9565ba8190f41a46a54096afa0eeb8f76bd66f2c25d3b1b83005"}, - {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:8dc2c0395bea8254d8daebc76dcf8eb3a95ec2a46fa6fae5eaccee366bfe02ce"}, - {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6ba0d3dcac281aad8a0e5b14c7ed6f9fa89c8612b47939fc94f80b16e2e9bc83"}, - {file = "lxml-5.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:6e91cf736959057f7aac7adfc83481e03615a8e8dd5758aa1d95ea69e8931dba"}, - {file = "lxml-5.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:94d6c3782907b5e40e21cadf94b13b0842ac421192f26b84c45f13f3c9d5dc27"}, - {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c300306673aa0f3ed5ed9372b21867690a17dba38c68c44b287437c362ce486b"}, - {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d9b952e07aed35fe2e1a7ad26e929595412db48535921c5013edc8aa4a35ce"}, - {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:01220dca0d066d1349bd6a1726856a78f7929f3878f7e2ee83c296c69495309e"}, - {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2d9b8d9177afaef80c53c0a9e30fa252ff3036fb1c6494d427c066a4ce6a282f"}, - {file = "lxml-5.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:20094fc3f21ea0a8669dc4c61ed7fa8263bd37d97d93b90f28fc613371e7a875"}, - {file = "lxml-5.3.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ace2c2326a319a0bb8a8b0e5b570c764962e95818de9f259ce814ee666603f19"}, - {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92e67a0be1639c251d21e35fe74df6bcc40cba445c2cda7c4a967656733249e2"}, - {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd5350b55f9fecddc51385463a4f67a5da829bc741e38cf689f38ec9023f54ab"}, - {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c1fefd7e3d00921c44dc9ca80a775af49698bbfd92ea84498e56acffd4c5469"}, - {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:71a8dd38fbd2f2319136d4ae855a7078c69c9a38ae06e0c17c73fd70fc6caad8"}, - {file = "lxml-5.3.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:97acf1e1fd66ab53dacd2c35b319d7e548380c2e9e8c54525c6e76d21b1ae3b1"}, - {file = "lxml-5.3.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:68934b242c51eb02907c5b81d138cb977b2129a0a75a8f8b60b01cb8586c7b21"}, - {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b710bc2b8292966b23a6a0121f7a6c51d45d2347edcc75f016ac123b8054d3f2"}, - {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18feb4b93302091b1541221196a2155aa296c363fd233814fa11e181adebc52f"}, - {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3eb44520c4724c2e1a57c0af33a379eee41792595023f367ba3952a2d96c2aab"}, - {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:609251a0ca4770e5a8768ff902aa02bf636339c5a93f9349b48eb1f606f7f3e9"}, - {file = "lxml-5.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:516f491c834eb320d6c843156440fe7fc0d50b33e44387fcec5b02f0bc118a4c"}, - {file = "lxml-5.3.0.tar.gz", hash = "sha256:4e109ca30d1edec1ac60cdbe341905dc3b8f55b16855e03a54aaf59e51ec8c6f"}, + {file = "lxml-5.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a4058f16cee694577f7e4dd410263cd0ef75644b43802a689c2b3c2a7e69453b"}, + {file = "lxml-5.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:364de8f57d6eda0c16dcfb999af902da31396949efa0e583e12675d09709881b"}, + {file = "lxml-5.3.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:528f3a0498a8edc69af0559bdcf8a9f5a8bf7c00051a6ef3141fdcf27017bbf5"}, + {file = "lxml-5.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db4743e30d6f5f92b6d2b7c86b3ad250e0bad8dee4b7ad8a0c44bfb276af89a3"}, + {file = "lxml-5.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:17b5d7f8acf809465086d498d62a981fa6a56d2718135bb0e4aa48c502055f5c"}, + {file = "lxml-5.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:928e75a7200a4c09e6efc7482a1337919cc61fe1ba289f297827a5b76d8969c2"}, + {file = "lxml-5.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a997b784a639e05b9d4053ef3b20c7e447ea80814a762f25b8ed5a89d261eac"}, + {file = "lxml-5.3.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:7b82e67c5feb682dbb559c3e6b78355f234943053af61606af126df2183b9ef9"}, + {file = "lxml-5.3.1-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:f1de541a9893cf8a1b1db9bf0bf670a2decab42e3e82233d36a74eda7822b4c9"}, + {file = "lxml-5.3.1-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:de1fc314c3ad6bc2f6bd5b5a5b9357b8c6896333d27fdbb7049aea8bd5af2d79"}, + {file = "lxml-5.3.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:7c0536bd9178f754b277a3e53f90f9c9454a3bd108b1531ffff720e082d824f2"}, + {file = "lxml-5.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:68018c4c67d7e89951a91fbd371e2e34cd8cfc71f0bb43b5332db38497025d51"}, + {file = "lxml-5.3.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aa826340a609d0c954ba52fd831f0fba2a4165659ab0ee1a15e4aac21f302406"}, + {file = "lxml-5.3.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:796520afa499732191e39fc95b56a3b07f95256f2d22b1c26e217fb69a9db5b5"}, + {file = "lxml-5.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3effe081b3135237da6e4c4530ff2a868d3f80be0bda027e118a5971285d42d0"}, + {file = "lxml-5.3.1-cp310-cp310-win32.whl", hash = "sha256:a22f66270bd6d0804b02cd49dae2b33d4341015545d17f8426f2c4e22f557a23"}, + {file = "lxml-5.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:0bcfadea3cdc68e678d2b20cb16a16716887dd00a881e16f7d806c2138b8ff0c"}, + {file = "lxml-5.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e220f7b3e8656ab063d2eb0cd536fafef396829cafe04cb314e734f87649058f"}, + {file = "lxml-5.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f2cfae0688fd01f7056a17367e3b84f37c545fb447d7282cf2c242b16262607"}, + {file = "lxml-5.3.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67d2f8ad9dcc3a9e826bdc7802ed541a44e124c29b7d95a679eeb58c1c14ade8"}, + {file = "lxml-5.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db0c742aad702fd5d0c6611a73f9602f20aec2007c102630c06d7633d9c8f09a"}, + {file = "lxml-5.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:198bb4b4dd888e8390afa4f170d4fa28467a7eaf857f1952589f16cfbb67af27"}, + {file = "lxml-5.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2a3e412ce1849be34b45922bfef03df32d1410a06d1cdeb793a343c2f1fd666"}, + {file = "lxml-5.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b8969dbc8d09d9cd2ae06362c3bad27d03f433252601ef658a49bd9f2b22d79"}, + {file = "lxml-5.3.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:5be8f5e4044146a69c96077c7e08f0709c13a314aa5315981185c1f00235fe65"}, + {file = "lxml-5.3.1-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:133f3493253a00db2c870d3740bc458ebb7d937bd0a6a4f9328373e0db305709"}, + {file = "lxml-5.3.1-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:52d82b0d436edd6a1d22d94a344b9a58abd6c68c357ed44f22d4ba8179b37629"}, + {file = "lxml-5.3.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b6f92e35e2658a5ed51c6634ceb5ddae32053182851d8cad2a5bc102a359b33"}, + {file = "lxml-5.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:203b1d3eaebd34277be06a3eb880050f18a4e4d60861efba4fb946e31071a295"}, + {file = "lxml-5.3.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:155e1a5693cf4b55af652f5c0f78ef36596c7f680ff3ec6eb4d7d85367259b2c"}, + {file = "lxml-5.3.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:22ec2b3c191f43ed21f9545e9df94c37c6b49a5af0a874008ddc9132d49a2d9c"}, + {file = "lxml-5.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7eda194dd46e40ec745bf76795a7cccb02a6a41f445ad49d3cf66518b0bd9cff"}, + {file = "lxml-5.3.1-cp311-cp311-win32.whl", hash = "sha256:fb7c61d4be18e930f75948705e9718618862e6fc2ed0d7159b2262be73f167a2"}, + {file = "lxml-5.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:c809eef167bf4a57af4b03007004896f5c60bd38dc3852fcd97a26eae3d4c9e6"}, + {file = "lxml-5.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e69add9b6b7b08c60d7ff0152c7c9a6c45b4a71a919be5abde6f98f1ea16421c"}, + {file = "lxml-5.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4e52e1b148867b01c05e21837586ee307a01e793b94072d7c7b91d2c2da02ffe"}, + {file = "lxml-5.3.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4b382e0e636ed54cd278791d93fe2c4f370772743f02bcbe431a160089025c9"}, + {file = "lxml-5.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2e49dc23a10a1296b04ca9db200c44d3eb32c8d8ec532e8c1fd24792276522a"}, + {file = "lxml-5.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4399b4226c4785575fb20998dc571bc48125dc92c367ce2602d0d70e0c455eb0"}, + {file = "lxml-5.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5412500e0dc5481b1ee9cf6b38bb3b473f6e411eb62b83dc9b62699c3b7b79f7"}, + {file = "lxml-5.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c93ed3c998ea8472be98fb55aed65b5198740bfceaec07b2eba551e55b7b9ae"}, + {file = "lxml-5.3.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:63d57fc94eb0bbb4735e45517afc21ef262991d8758a8f2f05dd6e4174944519"}, + {file = "lxml-5.3.1-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:b450d7cabcd49aa7ab46a3c6aa3ac7e1593600a1a0605ba536ec0f1b99a04322"}, + {file = "lxml-5.3.1-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:4df0ec814b50275ad6a99bc82a38b59f90e10e47714ac9871e1b223895825468"}, + {file = "lxml-5.3.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d184f85ad2bb1f261eac55cddfcf62a70dee89982c978e92b9a74a1bfef2e367"}, + {file = "lxml-5.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b725e70d15906d24615201e650d5b0388b08a5187a55f119f25874d0103f90dd"}, + {file = "lxml-5.3.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a31fa7536ec1fb7155a0cd3a4e3d956c835ad0a43e3610ca32384d01f079ea1c"}, + {file = "lxml-5.3.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3c3c8b55c7fc7b7e8877b9366568cc73d68b82da7fe33d8b98527b73857a225f"}, + {file = "lxml-5.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d61ec60945d694df806a9aec88e8f29a27293c6e424f8ff91c80416e3c617645"}, + {file = "lxml-5.3.1-cp312-cp312-win32.whl", hash = "sha256:f4eac0584cdc3285ef2e74eee1513a6001681fd9753b259e8159421ed28a72e5"}, + {file = "lxml-5.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:29bfc8d3d88e56ea0a27e7c4897b642706840247f59f4377d81be8f32aa0cfbf"}, + {file = "lxml-5.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c093c7088b40d8266f57ed71d93112bd64c6724d31f0794c1e52cc4857c28e0e"}, + {file = "lxml-5.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0884e3f22d87c30694e625b1e62e6f30d39782c806287450d9dc2fdf07692fd"}, + {file = "lxml-5.3.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1637fa31ec682cd5760092adfabe86d9b718a75d43e65e211d5931809bc111e7"}, + {file = "lxml-5.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a364e8e944d92dcbf33b6b494d4e0fb3499dcc3bd9485beb701aa4b4201fa414"}, + {file = "lxml-5.3.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:779e851fd0e19795ccc8a9bb4d705d6baa0ef475329fe44a13cf1e962f18ff1e"}, + {file = "lxml-5.3.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c4393600915c308e546dc7003d74371744234e8444a28622d76fe19b98fa59d1"}, + {file = "lxml-5.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:673b9d8e780f455091200bba8534d5f4f465944cbdd61f31dc832d70e29064a5"}, + {file = "lxml-5.3.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:2e4a570f6a99e96c457f7bec5ad459c9c420ee80b99eb04cbfcfe3fc18ec6423"}, + {file = "lxml-5.3.1-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:71f31eda4e370f46af42fc9f264fafa1b09f46ba07bdbee98f25689a04b81c20"}, + {file = "lxml-5.3.1-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:42978a68d3825eaac55399eb37a4d52012a205c0c6262199b8b44fcc6fd686e8"}, + {file = "lxml-5.3.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:8b1942b3e4ed9ed551ed3083a2e6e0772de1e5e3aca872d955e2e86385fb7ff9"}, + {file = "lxml-5.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:85c4f11be9cf08917ac2a5a8b6e1ef63b2f8e3799cec194417e76826e5f1de9c"}, + {file = "lxml-5.3.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:231cf4d140b22a923b1d0a0a4e0b4f972e5893efcdec188934cc65888fd0227b"}, + {file = "lxml-5.3.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5865b270b420eda7b68928d70bb517ccbe045e53b1a428129bb44372bf3d7dd5"}, + {file = "lxml-5.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7bebc2275016cddf3c997bf8a0f7044160714c64a9b83975670a04e6d2252"}, + {file = "lxml-5.3.1-cp313-cp313-win32.whl", hash = "sha256:d0751528b97d2b19a388b302be2a0ee05817097bab46ff0ed76feeec24951f78"}, + {file = "lxml-5.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:91fb6a43d72b4f8863d21f347a9163eecbf36e76e2f51068d59cd004c506f332"}, + {file = "lxml-5.3.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:016b96c58e9a4528219bb563acf1aaaa8bc5452e7651004894a973f03b84ba81"}, + {file = "lxml-5.3.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82a4bb10b0beef1434fb23a09f001ab5ca87895596b4581fd53f1e5145a8934a"}, + {file = "lxml-5.3.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d68eeef7b4d08a25e51897dac29bcb62aba830e9ac6c4e3297ee7c6a0cf6439"}, + {file = "lxml-5.3.1-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:f12582b8d3b4c6be1d298c49cb7ae64a3a73efaf4c2ab4e37db182e3545815ac"}, + {file = "lxml-5.3.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2df7ed5edeb6bd5590914cd61df76eb6cce9d590ed04ec7c183cf5509f73530d"}, + {file = "lxml-5.3.1-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:585c4dc429deebc4307187d2b71ebe914843185ae16a4d582ee030e6cfbb4d8a"}, + {file = "lxml-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:06a20d607a86fccab2fc15a77aa445f2bdef7b49ec0520a842c5c5afd8381576"}, + {file = "lxml-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:057e30d0012439bc54ca427a83d458752ccda725c1c161cc283db07bcad43cf9"}, + {file = "lxml-5.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4867361c049761a56bd21de507cab2c2a608c55102311d142ade7dab67b34f32"}, + {file = "lxml-5.3.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3dddf0fb832486cc1ea71d189cb92eb887826e8deebe128884e15020bb6e3f61"}, + {file = "lxml-5.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bcc211542f7af6f2dfb705f5f8b74e865592778e6cafdfd19c792c244ccce19"}, + {file = "lxml-5.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaca5a812f050ab55426c32177091130b1e49329b3f002a32934cd0245571307"}, + {file = "lxml-5.3.1-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:236610b77589faf462337b3305a1be91756c8abc5a45ff7ca8f245a71c5dab70"}, + {file = "lxml-5.3.1-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:aed57b541b589fa05ac248f4cb1c46cbb432ab82cbd467d1c4f6a2bdc18aecf9"}, + {file = "lxml-5.3.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:75fa3d6946d317ffc7016a6fcc44f42db6d514b7fdb8b4b28cbe058303cb6e53"}, + {file = "lxml-5.3.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:96eef5b9f336f623ffc555ab47a775495e7e8846dde88de5f941e2906453a1ce"}, + {file = "lxml-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:ef45f31aec9be01379fc6c10f1d9c677f032f2bac9383c827d44f620e8a88407"}, + {file = "lxml-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0611da6b07dd3720f492db1b463a4d1175b096b49438761cc9f35f0d9eaaef5"}, + {file = "lxml-5.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b2aca14c235c7a08558fe0a4786a1a05873a01e86b474dfa8f6df49101853a4e"}, + {file = "lxml-5.3.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae82fce1d964f065c32c9517309f0c7be588772352d2f40b1574a214bd6e6098"}, + {file = "lxml-5.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7aae7a3d63b935babfdc6864b31196afd5145878ddd22f5200729006366bc4d5"}, + {file = "lxml-5.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8e0d177b1fe251c3b1b914ab64135475c5273c8cfd2857964b2e3bb0fe196a7"}, + {file = "lxml-5.3.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:6c4dd3bfd0c82400060896717dd261137398edb7e524527438c54a8c34f736bf"}, + {file = "lxml-5.3.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f1208c1c67ec9e151d78aa3435aa9b08a488b53d9cfac9b699f15255a3461ef2"}, + {file = "lxml-5.3.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:c6aacf00d05b38a5069826e50ae72751cb5bc27bdc4d5746203988e429b385bb"}, + {file = "lxml-5.3.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5881aaa4bf3a2d086c5f20371d3a5856199a0d8ac72dd8d0dbd7a2ecfc26ab73"}, + {file = "lxml-5.3.1-cp38-cp38-win32.whl", hash = "sha256:45fbb70ccbc8683f2fb58bea89498a7274af1d9ec7995e9f4af5604e028233fc"}, + {file = "lxml-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:7512b4d0fc5339d5abbb14d1843f70499cab90d0b864f790e73f780f041615d7"}, + {file = "lxml-5.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5885bc586f1edb48e5d68e7a4b4757b5feb2a496b64f462b4d65950f5af3364f"}, + {file = "lxml-5.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1b92fe86e04f680b848fff594a908edfa72b31bfc3499ef7433790c11d4c8cd8"}, + {file = "lxml-5.3.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a091026c3bf7519ab1e64655a3f52a59ad4a4e019a6f830c24d6430695b1cf6a"}, + {file = "lxml-5.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ffb141361108e864ab5f1813f66e4e1164181227f9b1f105b042729b6c15125"}, + {file = "lxml-5.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3715cdf0dd31b836433af9ee9197af10e3df41d273c19bb249230043667a5dfd"}, + {file = "lxml-5.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88b72eb7222d918c967202024812c2bfb4048deeb69ca328363fb8e15254c549"}, + {file = "lxml-5.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa59974880ab5ad8ef3afaa26f9bda148c5f39e06b11a8ada4660ecc9fb2feb3"}, + {file = "lxml-5.3.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:3bb8149840daf2c3f97cebf00e4ed4a65a0baff888bf2605a8d0135ff5cf764e"}, + {file = "lxml-5.3.1-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:0d6b2fa86becfa81f0a0271ccb9eb127ad45fb597733a77b92e8a35e53414914"}, + {file = "lxml-5.3.1-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:136bf638d92848a939fd8f0e06fcf92d9f2e4b57969d94faae27c55f3d85c05b"}, + {file = "lxml-5.3.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:89934f9f791566e54c1d92cdc8f8fd0009447a5ecdb1ec6b810d5f8c4955f6be"}, + {file = "lxml-5.3.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a8ade0363f776f87f982572c2860cc43c65ace208db49c76df0a21dde4ddd16e"}, + {file = "lxml-5.3.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:bfbbab9316330cf81656fed435311386610f78b6c93cc5db4bebbce8dd146675"}, + {file = "lxml-5.3.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:172d65f7c72a35a6879217bcdb4bb11bc88d55fb4879e7569f55616062d387c2"}, + {file = "lxml-5.3.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e3c623923967f3e5961d272718655946e5322b8d058e094764180cdee7bab1af"}, + {file = "lxml-5.3.1-cp39-cp39-win32.whl", hash = "sha256:ce0930a963ff593e8bb6fda49a503911accc67dee7e5445eec972668e672a0f0"}, + {file = "lxml-5.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:f7b64fcd670bca8800bc10ced36620c6bbb321e7bc1214b9c0c0df269c1dddc2"}, + {file = "lxml-5.3.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:afa578b6524ff85fb365f454cf61683771d0170470c48ad9d170c48075f86725"}, + {file = "lxml-5.3.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67f5e80adf0aafc7b5454f2c1cb0cde920c9b1f2cbd0485f07cc1d0497c35c5d"}, + {file = "lxml-5.3.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dd0b80ac2d8f13ffc906123a6f20b459cb50a99222d0da492360512f3e50f84"}, + {file = "lxml-5.3.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:422c179022ecdedbe58b0e242607198580804253da220e9454ffe848daa1cfd2"}, + {file = "lxml-5.3.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:524ccfded8989a6595dbdda80d779fb977dbc9a7bc458864fc9a0c2fc15dc877"}, + {file = "lxml-5.3.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:48fd46bf7155def2e15287c6f2b133a2f78e2d22cdf55647269977b873c65499"}, + {file = "lxml-5.3.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:05123fad495a429f123307ac6d8fd6f977b71e9a0b6d9aeeb8f80c017cb17131"}, + {file = "lxml-5.3.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a243132767150a44e6a93cd1dde41010036e1cbc63cc3e9fe1712b277d926ce3"}, + {file = "lxml-5.3.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c92ea6d9dd84a750b2bae72ff5e8cf5fdd13e58dda79c33e057862c29a8d5b50"}, + {file = "lxml-5.3.1-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2f1be45d4c15f237209bbf123a0e05b5d630c8717c42f59f31ea9eae2ad89394"}, + {file = "lxml-5.3.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:a83d3adea1e0ee36dac34627f78ddd7f093bb9cfc0a8e97f1572a949b695cb98"}, + {file = "lxml-5.3.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3edbb9c9130bac05d8c3fe150c51c337a471cc7fdb6d2a0a7d3a88e88a829314"}, + {file = "lxml-5.3.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2f23cf50eccb3255b6e913188291af0150d89dab44137a69e14e4dcb7be981f1"}, + {file = "lxml-5.3.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df7e5edac4778127f2bf452e0721a58a1cfa4d1d9eac63bdd650535eb8543615"}, + {file = "lxml-5.3.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:094b28ed8a8a072b9e9e2113a81fda668d2053f2ca9f2d202c2c8c7c2d6516b1"}, + {file = "lxml-5.3.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:514fe78fc4b87e7a7601c92492210b20a1b0c6ab20e71e81307d9c2e377c64de"}, + {file = "lxml-5.3.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8fffc08de02071c37865a155e5ea5fce0282e1546fd5bde7f6149fcaa32558ac"}, + {file = "lxml-5.3.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4b0d5cdba1b655d5b18042ac9c9ff50bda33568eb80feaaca4fc237b9c4fbfde"}, + {file = "lxml-5.3.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3031e4c16b59424e8d78522c69b062d301d951dc55ad8685736c3335a97fc270"}, + {file = "lxml-5.3.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb659702a45136c743bc130760c6f137870d4df3a9e14386478b8a0511abcfca"}, + {file = "lxml-5.3.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a11b16a33656ffc43c92a5343a28dc71eefe460bcc2a4923a96f292692709f6"}, + {file = "lxml-5.3.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c5ae125276f254b01daa73e2c103363d3e99e3e10505686ac7d9d2442dd4627a"}, + {file = "lxml-5.3.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c76722b5ed4a31ba103e0dc77ab869222ec36efe1a614e42e9bcea88a36186fe"}, + {file = "lxml-5.3.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:33e06717c00c788ab4e79bc4726ecc50c54b9bfb55355eae21473c145d83c2d2"}, + {file = "lxml-5.3.1.tar.gz", hash = "sha256:106b7b5d2977b339f1e97efe2778e2ab20e99994cbb0ec5e55771ed0795920c8"}, ] [package.extras] cssselect = ["cssselect (>=0.7)"] -html-clean = ["lxml-html-clean"] +html-clean = ["lxml_html_clean"] html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=3.0.11)"] +source = ["Cython (>=3.0.11,<3.1.0)"] [[package]] name = "lxml-stubs" @@ -830,69 +824,90 @@ test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] [[package]] name = "orjson" -version = "3.10.10" +version = "3.10.15" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = true python-versions = ">=3.8" files = [ - {file = "orjson-3.10.10-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b788a579b113acf1c57e0a68e558be71d5d09aa67f62ca1f68e01117e550a998"}, - {file = "orjson-3.10.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:804b18e2b88022c8905bb79bd2cbe59c0cd014b9328f43da8d3b28441995cda4"}, - {file = "orjson-3.10.10-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9972572a1d042ec9ee421b6da69f7cc823da5962237563fa548ab17f152f0b9b"}, - {file = "orjson-3.10.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc6993ab1c2ae7dd0711161e303f1db69062955ac2668181bfdf2dd410e65258"}, - {file = "orjson-3.10.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d78e4cacced5781b01d9bc0f0cd8b70b906a0e109825cb41c1b03f9c41e4ce86"}, - {file = "orjson-3.10.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6eb2598df518281ba0cbc30d24c5b06124ccf7e19169e883c14e0831217a0bc"}, - {file = "orjson-3.10.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:23776265c5215ec532de6238a52707048401a568f0fa0d938008e92a147fe2c7"}, - {file = "orjson-3.10.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8cc2a654c08755cef90b468ff17c102e2def0edd62898b2486767204a7f5cc9c"}, - {file = "orjson-3.10.10-cp310-none-win32.whl", hash = "sha256:081b3fc6a86d72efeb67c13d0ea7c030017bd95f9868b1e329a376edc456153b"}, - {file = "orjson-3.10.10-cp310-none-win_amd64.whl", hash = "sha256:ff38c5fb749347768a603be1fb8a31856458af839f31f064c5aa74aca5be9efe"}, - {file = "orjson-3.10.10-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:879e99486c0fbb256266c7c6a67ff84f46035e4f8749ac6317cc83dacd7f993a"}, - {file = "orjson-3.10.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:019481fa9ea5ff13b5d5d95e6fd5ab25ded0810c80b150c2c7b1cc8660b662a7"}, - {file = "orjson-3.10.10-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0dd57eff09894938b4c86d4b871a479260f9e156fa7f12f8cad4b39ea8028bb5"}, - {file = "orjson-3.10.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dbde6d70cd95ab4d11ea8ac5e738e30764e510fc54d777336eec09bb93b8576c"}, - {file = "orjson-3.10.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2625cb37b8fb42e2147404e5ff7ef08712099197a9cd38895006d7053e69d6"}, - {file = "orjson-3.10.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbf3c20c6a7db69df58672a0d5815647ecf78c8e62a4d9bd284e8621c1fe5ccb"}, - {file = "orjson-3.10.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:75c38f5647e02d423807d252ce4528bf6a95bd776af999cb1fb48867ed01d1f6"}, - {file = "orjson-3.10.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:23458d31fa50ec18e0ec4b0b4343730928296b11111df5f547c75913714116b2"}, - {file = "orjson-3.10.10-cp311-none-win32.whl", hash = "sha256:2787cd9dedc591c989f3facd7e3e86508eafdc9536a26ec277699c0aa63c685b"}, - {file = "orjson-3.10.10-cp311-none-win_amd64.whl", hash = "sha256:6514449d2c202a75183f807bc755167713297c69f1db57a89a1ef4a0170ee269"}, - {file = "orjson-3.10.10-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:8564f48f3620861f5ef1e080ce7cd122ee89d7d6dacf25fcae675ff63b4d6e05"}, - {file = "orjson-3.10.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5bf161a32b479034098c5b81f2608f09167ad2fa1c06abd4e527ea6bf4837a9"}, - {file = "orjson-3.10.10-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68b65c93617bcafa7f04b74ae8bc2cc214bd5cb45168a953256ff83015c6747d"}, - {file = "orjson-3.10.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8e28406f97fc2ea0c6150f4c1b6e8261453318930b334abc419214c82314f85"}, - {file = "orjson-3.10.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4d0d9fe174cc7a5bdce2e6c378bcdb4c49b2bf522a8f996aa586020e1b96cee"}, - {file = "orjson-3.10.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3be81c42f1242cbed03cbb3973501fcaa2675a0af638f8be494eaf37143d999"}, - {file = "orjson-3.10.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:65f9886d3bae65be026219c0a5f32dbbe91a9e6272f56d092ab22561ad0ea33b"}, - {file = "orjson-3.10.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:730ed5350147db7beb23ddaf072f490329e90a1d059711d364b49fe352ec987b"}, - {file = "orjson-3.10.10-cp312-none-win32.whl", hash = "sha256:a8f4bf5f1c85bea2170800020d53a8877812892697f9c2de73d576c9307a8a5f"}, - {file = "orjson-3.10.10-cp312-none-win_amd64.whl", hash = "sha256:384cd13579a1b4cd689d218e329f459eb9ddc504fa48c5a83ef4889db7fd7a4f"}, - {file = "orjson-3.10.10-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44bffae68c291f94ff5a9b4149fe9d1bdd4cd0ff0fb575bcea8351d48db629a1"}, - {file = "orjson-3.10.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e27b4c6437315df3024f0835887127dac2a0a3ff643500ec27088d2588fa5ae1"}, - {file = "orjson-3.10.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca84df16d6b49325a4084fd8b2fe2229cb415e15c46c529f868c3387bb1339d"}, - {file = "orjson-3.10.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c14ce70e8f39bd71f9f80423801b5d10bf93d1dceffdecd04df0f64d2c69bc01"}, - {file = "orjson-3.10.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:24ac62336da9bda1bd93c0491eff0613003b48d3cb5d01470842e7b52a40d5b4"}, - {file = "orjson-3.10.10-cp313-none-win32.whl", hash = "sha256:eb0a42831372ec2b05acc9ee45af77bcaccbd91257345f93780a8e654efc75db"}, - {file = "orjson-3.10.10-cp313-none-win_amd64.whl", hash = "sha256:f0c4f37f8bf3f1075c6cc8dd8a9f843689a4b618628f8812d0a71e6968b95ffd"}, - {file = "orjson-3.10.10-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:829700cc18503efc0cf502d630f612884258020d98a317679cd2054af0259568"}, - {file = "orjson-3.10.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0ceb5e0e8c4f010ac787d29ae6299846935044686509e2f0f06ed441c1ca949"}, - {file = "orjson-3.10.10-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0c25908eb86968613216f3db4d3003f1c45d78eb9046b71056ca327ff92bdbd4"}, - {file = "orjson-3.10.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:218cb0bc03340144b6328a9ff78f0932e642199ac184dd74b01ad691f42f93ff"}, - {file = "orjson-3.10.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e2277ec2cea3775640dc81ab5195bb5b2ada2fe0ea6eee4677474edc75ea6785"}, - {file = "orjson-3.10.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:848ea3b55ab5ccc9d7bbd420d69432628b691fba3ca8ae3148c35156cbd282aa"}, - {file = "orjson-3.10.10-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e3e67b537ac0c835b25b5f7d40d83816abd2d3f4c0b0866ee981a045287a54f3"}, - {file = "orjson-3.10.10-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:7948cfb909353fce2135dcdbe4521a5e7e1159484e0bb024c1722f272488f2b8"}, - {file = "orjson-3.10.10-cp38-none-win32.whl", hash = "sha256:78bee66a988f1a333dc0b6257503d63553b1957889c17b2c4ed72385cd1b96ae"}, - {file = "orjson-3.10.10-cp38-none-win_amd64.whl", hash = "sha256:f1d647ca8d62afeb774340a343c7fc023efacfd3a39f70c798991063f0c681dd"}, - {file = "orjson-3.10.10-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:5a059afddbaa6dd733b5a2d76a90dbc8af790b993b1b5cb97a1176ca713b5df8"}, - {file = "orjson-3.10.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f9b5c59f7e2a1a410f971c5ebc68f1995822837cd10905ee255f96074537ee6"}, - {file = "orjson-3.10.10-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d5ef198bafdef4aa9d49a4165ba53ffdc0a9e1c7b6f76178572ab33118afea25"}, - {file = "orjson-3.10.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf29ce0bb5d3320824ec3d1508652421000ba466abd63bdd52c64bcce9eb1fa"}, - {file = "orjson-3.10.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dddd5516bcc93e723d029c1633ae79c4417477b4f57dad9bfeeb6bc0315e654a"}, - {file = "orjson-3.10.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12f2003695b10817f0fa8b8fca982ed7f5761dcb0d93cff4f2f9f6709903fd7"}, - {file = "orjson-3.10.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:672f9874a8a8fb9bb1b771331d31ba27f57702c8106cdbadad8bda5d10bc1019"}, - {file = "orjson-3.10.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1dcbb0ca5fafb2b378b2c74419480ab2486326974826bbf6588f4dc62137570a"}, - {file = "orjson-3.10.10-cp39-none-win32.whl", hash = "sha256:d9bbd3a4b92256875cb058c3381b782649b9a3c68a4aa9a2fff020c2f9cfc1be"}, - {file = "orjson-3.10.10-cp39-none-win_amd64.whl", hash = "sha256:766f21487a53aee8524b97ca9582d5c6541b03ab6210fbaf10142ae2f3ced2aa"}, - {file = "orjson-3.10.10.tar.gz", hash = "sha256:37949383c4df7b4337ce82ee35b6d7471e55195efa7dcb45ab8226ceadb0fe3b"}, + {file = "orjson-3.10.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:552c883d03ad185f720d0c09583ebde257e41b9521b74ff40e08b7dec4559c04"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e3e8d438d02e4854f70bfdc03a6bcdb697358dbaa6bcd19cbe24d24ece1f8"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c2c79fa308e6edb0ffab0a31fd75a7841bf2a79a20ef08a3c6e3b26814c8ca8"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cb85490aa6bf98abd20607ab5c8324c0acb48d6da7863a51be48505646c814"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763dadac05e4e9d2bc14938a45a2d0560549561287d41c465d3c58aec818b164"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a330b9b4734f09a623f74a7490db713695e13b67c959713b78369f26b3dee6bf"}, + {file = "orjson-3.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a61a4622b7ff861f019974f73d8165be1bd9a0855e1cad18ee167acacabeb061"}, + {file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acd271247691574416b3228db667b84775c497b245fa275c6ab90dc1ffbbd2b3"}, + {file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4759b109c37f635aa5c5cc93a1b26927bfde24b254bcc0e1149a9fada253d2d"}, + {file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e992fd5cfb8b9f00bfad2fd7a05a4299db2bbe92e6440d9dd2fab27655b3182"}, + {file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f95fb363d79366af56c3f26b71df40b9a583b07bbaaf5b317407c4d58497852e"}, + {file = "orjson-3.10.15-cp310-cp310-win32.whl", hash = "sha256:f9875f5fea7492da8ec2444839dcc439b0ef298978f311103d0b7dfd775898ab"}, + {file = "orjson-3.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:17085a6aa91e1cd70ca8533989a18b5433e15d29c574582f76f821737c8d5806"}, + {file = "orjson-3.10.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c4cc83960ab79a4031f3119cc4b1a1c627a3dc09df125b27c4201dff2af7eaa6"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddbeef2481d895ab8be5185f2432c334d6dec1f5d1933a9c83014d188e102cef"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e590a0477b23ecd5b0ac865b1b907b01b3c5535f5e8a8f6ab0e503efb896334"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6be38bd103d2fd9bdfa31c2720b23b5d47c6796bcb1d1b598e3924441b4298d"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff4f6edb1578960ed628a3b998fa54d78d9bb3e2eb2cfc5c2a09732431c678d0"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0482b21d0462eddd67e7fce10b89e0b6ac56570424662b685a0d6fccf581e13"}, + {file = "orjson-3.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bb5cc3527036ae3d98b65e37b7986a918955f85332c1ee07f9d3f82f3a6899b5"}, + {file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d569c1c462912acdd119ccbf719cf7102ea2c67dd03b99edcb1a3048651ac96b"}, + {file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1e6d33efab6b71d67f22bf2962895d3dc6f82a6273a965fab762e64fa90dc399"}, + {file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c33be3795e299f565681d69852ac8c1bc5c84863c0b0030b2b3468843be90388"}, + {file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eea80037b9fae5339b214f59308ef0589fc06dc870578b7cce6d71eb2096764c"}, + {file = "orjson-3.10.15-cp311-cp311-win32.whl", hash = "sha256:d5ac11b659fd798228a7adba3e37c010e0152b78b1982897020a8e019a94882e"}, + {file = "orjson-3.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:cf45e0214c593660339ef63e875f32ddd5aa3b4adc15e662cdb80dc49e194f8e"}, + {file = "orjson-3.10.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9d11c0714fc85bfcf36ada1179400862da3288fc785c30e8297844c867d7505a"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dba5a1e85d554e3897fa9fe6fbcff2ed32d55008973ec9a2b992bd9a65d2352d"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7723ad949a0ea502df656948ddd8b392780a5beaa4c3b5f97e525191b102fff0"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6fd9bc64421e9fe9bd88039e7ce8e58d4fead67ca88e3a4014b143cec7684fd4"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dadba0e7b6594216c214ef7894c4bd5f08d7c0135f4dd0145600be4fbcc16767"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48f59114fe318f33bbaee8ebeda696d8ccc94c9e90bc27dbe72153094e26f41"}, + {file = "orjson-3.10.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:035fb83585e0f15e076759b6fedaf0abb460d1765b6a36f48018a52858443514"}, + {file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d13b7fe322d75bf84464b075eafd8e7dd9eae05649aa2a5354cfa32f43c59f17"}, + {file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7066b74f9f259849629e0d04db6609db4cf5b973248f455ba5d3bd58a4daaa5b"}, + {file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88dc3f65a026bd3175eb157fea994fca6ac7c4c8579fc5a86fc2114ad05705b7"}, + {file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b342567e5465bd99faa559507fe45e33fc76b9fb868a63f1642c6bc0735ad02a"}, + {file = "orjson-3.10.15-cp312-cp312-win32.whl", hash = "sha256:0a4f27ea5617828e6b58922fdbec67b0aa4bb844e2d363b9244c47fa2180e665"}, + {file = "orjson-3.10.15-cp312-cp312-win_amd64.whl", hash = "sha256:ef5b87e7aa9545ddadd2309efe6824bd3dd64ac101c15dae0f2f597911d46eaa"}, + {file = "orjson-3.10.15-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bae0e6ec2b7ba6895198cd981b7cca95d1487d0147c8ed751e5632ad16f031a6"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93ce145b2db1252dd86af37d4165b6faa83072b46e3995ecc95d4b2301b725a"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c203f6f969210128af3acae0ef9ea6aab9782939f45f6fe02d05958fe761ef9"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8918719572d662e18b8af66aef699d8c21072e54b6c82a3f8f6404c1f5ccd5e0"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f71eae9651465dff70aa80db92586ad5b92df46a9373ee55252109bb6b703307"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e117eb299a35f2634e25ed120c37c641398826c2f5a3d3cc39f5993b96171b9e"}, + {file = "orjson-3.10.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13242f12d295e83c2955756a574ddd6741c81e5b99f2bef8ed8d53e47a01e4b7"}, + {file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7946922ada8f3e0b7b958cc3eb22cfcf6c0df83d1fe5521b4a100103e3fa84c8"}, + {file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b7155eb1623347f0f22c38c9abdd738b287e39b9982e1da227503387b81b34ca"}, + {file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:208beedfa807c922da4e81061dafa9c8489c6328934ca2a562efa707e049e561"}, + {file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eca81f83b1b8c07449e1d6ff7074e82e3fd6777e588f1a6632127f286a968825"}, + {file = "orjson-3.10.15-cp313-cp313-win32.whl", hash = "sha256:c03cd6eea1bd3b949d0d007c8d57049aa2b39bd49f58b4b2af571a5d3833d890"}, + {file = "orjson-3.10.15-cp313-cp313-win_amd64.whl", hash = "sha256:fd56a26a04f6ba5fb2045b0acc487a63162a958ed837648c5781e1fe3316cfbf"}, + {file = "orjson-3.10.15-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:5e8afd6200e12771467a1a44e5ad780614b86abb4b11862ec54861a82d677746"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da9a18c500f19273e9e104cca8c1f0b40a6470bcccfc33afcc088045d0bf5ea6"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb00b7bfbdf5d34a13180e4805d76b4567025da19a197645ca746fc2fb536586"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33aedc3d903378e257047fee506f11e0833146ca3e57a1a1fb0ddb789876c1e1"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd0099ae6aed5eb1fc84c9eb72b95505a3df4267e6962eb93cdd5af03be71c98"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c864a80a2d467d7786274fce0e4f93ef2a7ca4ff31f7fc5634225aaa4e9e98c"}, + {file = "orjson-3.10.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c25774c9e88a3e0013d7d1a6c8056926b607a61edd423b50eb5c88fd7f2823ae"}, + {file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e78c211d0074e783d824ce7bb85bf459f93a233eb67a5b5003498232ddfb0e8a"}, + {file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:43e17289ffdbbac8f39243916c893d2ae41a2ea1a9cbb060a56a4d75286351ae"}, + {file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:781d54657063f361e89714293c095f506c533582ee40a426cb6489c48a637b81"}, + {file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6875210307d36c94873f553786a808af2788e362bd0cf4c8e66d976791e7b528"}, + {file = "orjson-3.10.15-cp38-cp38-win32.whl", hash = "sha256:305b38b2b8f8083cc3d618927d7f424349afce5975b316d33075ef0f73576b60"}, + {file = "orjson-3.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:5dd9ef1639878cc3efffed349543cbf9372bdbd79f478615a1c633fe4e4180d1"}, + {file = "orjson-3.10.15-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ffe19f3e8d68111e8644d4f4e267a069ca427926855582ff01fc012496d19969"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d433bf32a363823863a96561a555227c18a522a8217a6f9400f00ddc70139ae2"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da03392674f59a95d03fa5fb9fe3a160b0511ad84b7a3914699ea5a1b3a38da2"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a63bb41559b05360ded9132032239e47983a39b151af1201f07ec9370715c82"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3766ac4702f8f795ff3fa067968e806b4344af257011858cc3d6d8721588b53f"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a1c73dcc8fadbd7c55802d9aa093b36878d34a3b3222c41052ce6b0fc65f8e8"}, + {file = "orjson-3.10.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b299383825eafe642cbab34be762ccff9fd3408d72726a6b2a4506d410a71ab3"}, + {file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:abc7abecdbf67a173ef1316036ebbf54ce400ef2300b4e26a7b843bd446c2480"}, + {file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:3614ea508d522a621384c1d6639016a5a2e4f027f3e4a1c93a51867615d28829"}, + {file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:295c70f9dc154307777ba30fe29ff15c1bcc9dfc5c48632f37d20a607e9ba85a"}, + {file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:63309e3ff924c62404923c80b9e2048c1f74ba4b615e7584584389ada50ed428"}, + {file = "orjson-3.10.15-cp39-cp39-win32.whl", hash = "sha256:a2f708c62d026fb5340788ba94a55c23df4e1869fec74be455e0b2f5363b8507"}, + {file = "orjson-3.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:efcf6c735c3d22ef60c4aa27a5238f1a477df85e9b15f2142f9d669beb2d13fd"}, + {file = "orjson-3.10.15.tar.gz", hash = "sha256:05ca7fe452a2e9d8d9d706a2984c95b9c2ebc5db417ce0b7a49b91d50642a23e"}, ] [[package]] @@ -1034,13 +1049,13 @@ files = [ [[package]] name = "pytest" -version = "8.3.3" +version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, - {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, + {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, + {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, ] [package.dependencies] @@ -1108,6 +1123,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -1165,29 +1181,29 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.7.0" +version = "0.9.6" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.7.0-py3-none-linux_armv6l.whl", hash = "sha256:0cdf20c2b6ff98e37df47b2b0bd3a34aaa155f59a11182c1303cce79be715628"}, - {file = "ruff-0.7.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:496494d350c7fdeb36ca4ef1c9f21d80d182423718782222c29b3e72b3512737"}, - {file = "ruff-0.7.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:214b88498684e20b6b2b8852c01d50f0651f3cc6118dfa113b4def9f14faaf06"}, - {file = "ruff-0.7.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630fce3fefe9844e91ea5bbf7ceadab4f9981f42b704fae011bb8efcaf5d84be"}, - {file = "ruff-0.7.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:211d877674e9373d4bb0f1c80f97a0201c61bcd1e9d045b6e9726adc42c156aa"}, - {file = "ruff-0.7.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:194d6c46c98c73949a106425ed40a576f52291c12bc21399eb8f13a0f7073495"}, - {file = "ruff-0.7.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:82c2579b82b9973a110fab281860403b397c08c403de92de19568f32f7178598"}, - {file = "ruff-0.7.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9af971fe85dcd5eaed8f585ddbc6bdbe8c217fb8fcf510ea6bca5bdfff56040e"}, - {file = "ruff-0.7.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b641c7f16939b7d24b7bfc0be4102c56562a18281f84f635604e8a6989948914"}, - {file = "ruff-0.7.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d71672336e46b34e0c90a790afeac8a31954fd42872c1f6adaea1dff76fd44f9"}, - {file = "ruff-0.7.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ab7d98c7eed355166f367597e513a6c82408df4181a937628dbec79abb2a1fe4"}, - {file = "ruff-0.7.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1eb54986f770f49edb14f71d33312d79e00e629a57387382200b1ef12d6a4ef9"}, - {file = "ruff-0.7.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dc452ba6f2bb9cf8726a84aa877061a2462afe9ae0ea1d411c53d226661c601d"}, - {file = "ruff-0.7.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4b406c2dce5be9bad59f2de26139a86017a517e6bcd2688da515481c05a2cb11"}, - {file = "ruff-0.7.0-py3-none-win32.whl", hash = "sha256:f6c968509f767776f524a8430426539587d5ec5c662f6addb6aa25bc2e8195ec"}, - {file = "ruff-0.7.0-py3-none-win_amd64.whl", hash = "sha256:ff4aabfbaaba880e85d394603b9e75d32b0693152e16fa659a3064a85df7fce2"}, - {file = "ruff-0.7.0-py3-none-win_arm64.whl", hash = "sha256:10842f69c245e78d6adec7e1db0a7d9ddc2fff0621d730e61657b64fa36f207e"}, - {file = "ruff-0.7.0.tar.gz", hash = "sha256:47a86360cf62d9cd53ebfb0b5eb0e882193fc191c6d717e8bef4462bc3b9ea2b"}, + {file = "ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba"}, + {file = "ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504"}, + {file = "ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656"}, + {file = "ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d"}, + {file = "ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa"}, + {file = "ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a"}, + {file = "ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9"}, ] [[package]] @@ -1427,13 +1443,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "wheel" -version = "0.44.0" +version = "0.45.1" description = "A built-package format for Python" optional = false python-versions = ">=3.8" files = [ - {file = "wheel-0.44.0-py3-none-any.whl", hash = "sha256:2376a90c98cc337d18623527a97c31797bd02bad0033d41547043a1cbfbe448f"}, - {file = "wheel-0.44.0.tar.gz", hash = "sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49"}, + {file = "wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248"}, + {file = "wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729"}, ] [package.extras] @@ -1463,5 +1479,5 @@ orjson = ["orjson"] [metadata] lock-version = "2.0" -python-versions = "^3.8.1" -content-hash = "71704ba175e33528872fab8121cb609041bd97b6a99f8f04022a26904941b27c" +python-versions = ">=3.8.1" +content-hash = "0ec27e1dca1f3b60dce28a2109a95eaada0bce2cbfbaee4d209d434a0d6e4086" diff --git a/pyproject.toml b/pyproject.toml index 1e15fe569..ff1665908 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "rdflib" -version = "7.1.1" +version = "7.3.0-a0" description = """RDFLib is a Python library for working with RDF, \ a simple yet powerful language for representing information.""" authors = ["Daniel 'eikeon' Krech "] @@ -38,7 +38,7 @@ rdfs2dot = 'rdflib.tools.rdfs2dot:main' rdfgraphisomorphism = 'rdflib.tools.graphisomorphism:main' [tool.poetry.dependencies] -python = "^3.8.1" +python = ">=3.8.1" isodate = {version=">=0.7.2,<1.0.0", python = "<3.11"} pyparsing = ">=2.1.0,<4" berkeleydb = {version = "^18.1.0", optional = true} @@ -59,7 +59,7 @@ pytest-cov = ">=4,<6" coverage = {version = "^7.0.1", extras = ["toml"]} types-setuptools = ">=68.0.0.3,<72.0.0.0" setuptools = ">=68,<72" -wheel = ">=0.42,<0.45" +wheel = ">=0.42,<0.46" [tool.poetry.group.docs.dependencies] sphinx = ">=7.1.2,<8" @@ -69,7 +69,7 @@ sphinx-autodoc-typehints = ">=1.25.3,<=2.0.1" typing-extensions = "^4.5.0" [tool.poetry.group.lint.dependencies] -ruff = ">=0.0.286,<0.8.0" +ruff = ">=0.0.286,<0.10.0" [tool.poetry.extras] berkeleydb = ["berkeleydb"] @@ -166,7 +166,7 @@ ignore = [ ] [tool.black] -line-length = "88" +line-length = 88 target-version = ['py38'] required-version = "24.4.2" include = '\.pyi?$' diff --git a/rdflib/__init__.py b/rdflib/__init__.py index 0c40cd7a4..af6dfeefe 100644 --- a/rdflib/__init__.py +++ b/rdflib/__init__.py @@ -52,13 +52,14 @@ __docformat__ = "restructuredtext en" __version__: str = _DISTRIBUTION_METADATA["Version"] -__date__ = "2024-10-28" +__date__ = "2025-09-19" __all__ = [ "URIRef", "BNode", "IdentifiedNode", "Literal", + "Node", "Variable", "Namespace", "Dataset", @@ -195,7 +196,7 @@ XSD, Namespace, ) -from rdflib.term import BNode, IdentifiedNode, Literal, URIRef, Variable +from rdflib.term import BNode, IdentifiedNode, Literal, Node, URIRef, Variable from rdflib import plugin, query, util # isort:skip from rdflib.container import * # isort:skip # noqa: F403 diff --git a/rdflib/extras/shacl.py b/rdflib/extras/shacl.py index 30fdab07b..1a5094ce3 100644 --- a/rdflib/extras/shacl.py +++ b/rdflib/extras/shacl.py @@ -4,18 +4,30 @@ from __future__ import annotations -from typing import Optional, Union +from typing import TYPE_CHECKING, Optional, Union -from rdflib import Graph, Literal, URIRef, paths +from rdflib import BNode, Graph, Literal, URIRef, paths +from rdflib.collection import Collection from rdflib.namespace import RDF, SH from rdflib.paths import Path from rdflib.term import Node +if TYPE_CHECKING: + from rdflib.term import IdentifiedNode + class SHACLPathError(Exception): pass +# Map the variable length path operators to the corresponding SHACL path predicates +_PATH_MOD_TO_PRED = { + paths.ZeroOrMore: SH.zeroOrMorePath, + paths.OneOrMore: SH.oneOrMorePath, + paths.ZeroOrOne: SH.zeroOrOnePath, +} + + # This implementation is roughly based on # pyshacl.helper.sparql_query_helper::SPARQLQueryHelper._shacl_path_to_sparql_path def parse_shacl_path( @@ -91,3 +103,110 @@ def parse_shacl_path( raise SHACLPathError(f"Cannot parse {repr(path_identifier)} as a SHACL Path.") return path + + +def _build_path_component( + graph: Graph, path_component: URIRef | Path +) -> IdentifiedNode: + """ + Helper method that implements the recursive component of SHACL path + triple construction. + + :param graph: A :class:`~rdflib.graph.Graph` into which to insert triples + :param graph_component: A :class:`~rdflib.term.URIRef` or + :class:`~rdflib.paths.Path` that is part of a path expression + :return: The :class:`~rdflib.term.IdentifiedNode of the resource in the + graph that corresponds to the provided path_component + """ + # Literals or other types are not allowed + if not isinstance(path_component, (URIRef, Path)): + raise TypeError( + f"Objects of type {type(path_component)} are not valid " + + "components of a SHACL path." + ) + + # If the path component is a URI, return it + elif isinstance(path_component, URIRef): + return path_component + # Otherwise, the path component is represented as a blank node + bnode = BNode() + + # Handle Sequence Paths + if isinstance(path_component, paths.SequencePath): + # Sequence paths are a Collection directly with at least two items + if len(path_component.args) < 2: + raise SHACLPathError( + "A list of SHACL Sequence Paths must contain at least two path items." + ) + Collection( + graph, + bnode, + [_build_path_component(graph, arg) for arg in path_component.args], + ) + + # Handle Inverse Paths + elif isinstance(path_component, paths.InvPath): + graph.add( + (bnode, SH.inversePath, _build_path_component(graph, path_component.arg)) + ) + + # Handle Alternative Paths + elif isinstance(path_component, paths.AlternativePath): + # Alternative paths are a Collection but referenced by sh:alternativePath + # with at least two items + if len(path_component.args) < 2: + raise SHACLPathError( + "List of SHACL alternate paths must have at least two path items." + ) + coll = Collection( + graph, + BNode(), + [_build_path_component(graph, arg) for arg in path_component.args], + ) + graph.add((bnode, SH.alternativePath, coll.uri)) + + # Handle Variable Length Paths + elif isinstance(path_component, paths.MulPath): + # Get the predicate corresponding to the path modifiier + pred = _PATH_MOD_TO_PRED.get(path_component.mod) + if pred is None: + raise SHACLPathError(f"Unknown path modifier {path_component.mod}") + graph.add((bnode, pred, _build_path_component(graph, path_component.path))) + + # Return the blank node created for the provided path_component + return bnode + + +def build_shacl_path( + path: URIRef | Path, target_graph: Graph | None = None +) -> tuple[IdentifiedNode, Graph | None]: + """ + Build the SHACL Path triples for a path given by a :class:`~rdflib.term.URIRef` for + simple paths or a :class:`~rdflib.paths.Path` for complex paths. + + Returns an :class:`~rdflib.term.IdentifiedNode` for the path (which should be + the object of a triple with predicate sh:path) and the graph into which any + new triples were added. + + :param path: A :class:`~rdflib.term.URIRef` or a :class:`~rdflib.paths.Path` + :param target_graph: Optionally, a :class:`~rdflib.graph.Graph` into which to put + constructed triples. If not provided, a new graph will be created + :return: A (path_identifier, graph) tuple where: + - path_identifier: If path is a :class:`~rdflib.term.URIRef`, this is simply + the provided path. If path is a :class:`~rdflib.paths.Path`, this is + the :class:`~rdflib.term.BNode` corresponding to the root of the SHACL + path expression added to the graph. + - graph: None if path is a :class:`~rdflib.term.URIRef` (as no new triples + are constructed). If path is a :class:`~rdflib.paths.Path`, this is either the + target_graph provided or a new graph into which the path triples were added. + """ + # If a path is a URI, that's the whole path. No graph needs to be constructed. + if isinstance(path, URIRef): + return path, None + + # Create a graph if one was not provided + if target_graph is None: + target_graph = Graph() + + # Recurse through the path to build the graph representation + return _build_path_component(target_graph, path), target_graph diff --git a/rdflib/graph.py b/rdflib/graph.py index 80ccc3fa8..7b7256d04 100644 --- a/rdflib/graph.py +++ b/rdflib/graph.py @@ -355,6 +355,11 @@ _TripleOrQuadSelectorType = Union["_TripleSelectorType", "_QuadSelectorType"] _TriplePathType = Tuple["_SubjectType", Path, "_ObjectType"] _TripleOrTriplePathType = Union["_TripleType", "_TriplePathType"] +_TripleChoiceType = Union[ + Tuple[List[_SubjectType], Optional[_PredicateType], Optional[_ObjectType]], + Tuple[Optional[_SubjectType], List[_PredicateType], Optional[_ObjectType]], + Tuple[Optional[_SubjectType], Optional[_PredicateType], List[_ObjectType]], +] _GraphT = TypeVar("_GraphT", bound="Graph") _ConjunctiveGraphT = TypeVar("_ConjunctiveGraphT", bound="ConjunctiveGraph") @@ -411,11 +416,50 @@ class Graph(Node): - """An RDF Graph + """An RDF Graph: a Python object containing nodes and relations between them as + RDF 'triples'. + + This is the central RDFLib object class and Graph objects are almost always present + it all uses of RDFLib. + + The basic use is to create a Graph and iterate through or query its content, e.g.: + + >>> from rdflib import Graph, URIRef + >>> g = Graph() + + >>> g.add(( + ... URIRef("http://example.com/s1"), # subject + ... URIRef("http://example.com/p1"), # predicate + ... URIRef("http://example.com/o1"), # object + ... )) # doctest: +ELLIPSIS + )> + + >>> g.add(( + ... URIRef("http://example.com/s2"), # subject + ... URIRef("http://example.com/p2"), # predicate + ... URIRef("http://example.com/o2"), # object + ... )) # doctest: +ELLIPSIS + )> - The constructor accepts one argument, the "store" - that will be used to store the graph data (see the "store" - package for stores currently shipped with rdflib). + >>> for triple in sorted(g): # simple looping + ... print(triple) + (rdflib.term.URIRef('http://example.com/s1'), rdflib.term.URIRef('http://example.com/p1'), rdflib.term.URIRef('http://example.com/o1')) + (rdflib.term.URIRef('http://example.com/s2'), rdflib.term.URIRef('http://example.com/p2'), rdflib.term.URIRef('http://example.com/o2')) + + >>> # get the object of the triple with subject s1 and predicate p1 + >>> o = g.value( + ... subject=URIRef("http://example.com/s1"), + ... predicate=URIRef("http://example.com/p1") + ... ) + + + The constructor accepts one argument, the "store" that will be used to store the + graph data with the default being the `Memory ` + (in memory) Store. Other Stores that persist content to disk using various file + databases or Stores that use remote servers (SPARQL systems) are supported. See + the :doc:`rdflib.plugins.stores` package for Stores currently shipped with RDFLib. + Other Stores not shipped with RDFLib can be added, such as + `HDT `_. Stores can be context-aware or unaware. Unaware stores take up (some) less space but cannot support features that require @@ -423,14 +467,15 @@ class Graph(Node): provenance. Even if used with a context-aware store, Graph will only expose the quads which - belong to the default graph. To access the rest of the data, `ConjunctiveGraph` or - `Dataset` classes can be used instead. + belong to the default graph. To access the rest of the data the + `Dataset` class can be used instead. The Graph constructor can take an identifier which identifies the Graph by name. If none is given, the graph is assigned a BNode for its identifier. - For more on named graphs, see: http://www.w3.org/2004/03/trix/ + For more on Named Graphs, see the RDFLib `Dataset` class and the TriG Specification, + https://www.w3.org/TR/trig/. """ context_aware: bool @@ -517,7 +562,9 @@ def rollback(self: _GraphT) -> _GraphT: self.__store.rollback() return self - def open(self, configuration: str, create: bool = False) -> Optional[int]: + def open( + self, configuration: Union[str, tuple[str, str]], create: bool = False + ) -> Optional[int]: """Open the graph store Might be necessary for stores that require opening a connection to a @@ -807,26 +854,32 @@ def set( def subjects( self, predicate: Union[None, Path, _PredicateType] = None, - object: Optional[_ObjectType] = None, + object: Optional[Union[_ObjectType, List[_ObjectType]]] = None, unique: bool = False, ) -> Generator[_SubjectType, None, None]: """A generator of (optionally unique) subjects with the given - predicate and object""" - if not unique: - for s, p, o in self.triples((None, predicate, object)): - yield s + predicate and object(s)""" + # if the object is a list of Nodes, yield results from subject() call for each + if isinstance(object, list): + for obj in object: + for s in self.subjects(predicate, obj, unique): + yield s else: - subs = set() - for s, p, o in self.triples((None, predicate, object)): - if s not in subs: + if not unique: + for s, p, o in self.triples((None, predicate, object)): yield s - try: - subs.add(s) - except MemoryError as e: - logger.error( - f"{e}. Consider not setting parameter 'unique' to True" - ) - raise + else: + subs = set() + for s, p, o in self.triples((None, predicate, object)): + if s not in subs: + yield s + try: + subs.add(s) + except MemoryError as e: + logger.error( + f"{e}. Consider not setting parameter 'unique' to True" + ) + raise def predicates( self, @@ -854,27 +907,32 @@ def predicates( def objects( self, - subject: Optional[_SubjectType] = None, + subject: Optional[Union[_SubjectType, List[_SubjectType]]] = None, predicate: Union[None, Path, _PredicateType] = None, unique: bool = False, ) -> Generator[_ObjectType, None, None]: """A generator of (optionally unique) objects with the given - subject and predicate""" - if not unique: - for s, p, o in self.triples((subject, predicate, None)): - yield o + subject(s) and predicate""" + if isinstance(subject, list): + for subj in subject: + for o in self.objects(subj, predicate, unique): + yield o else: - objs = set() - for s, p, o in self.triples((subject, predicate, None)): - if o not in objs: + if not unique: + for s, p, o in self.triples((subject, predicate, None)): yield o - try: - objs.add(o) - except MemoryError as e: - logger.error( - f"{e}. Consider not setting parameter 'unique' to True" - ) - raise + else: + objs = set() + for s, p, o in self.triples((subject, predicate, None)): + if o not in objs: + yield o + try: + objs.add(o) + except MemoryError as e: + logger.error( + f"{e}. Consider not setting parameter 'unique' to True" + ) + raise def subject_predicates( self, object: Optional[_ObjectType] = None, unique: bool = False @@ -943,11 +1001,7 @@ def predicate_objects( def triples_choices( self, - triple: Union[ - Tuple[List[_SubjectType], _PredicateType, _ObjectType], - Tuple[_SubjectType, List[_PredicateType], _ObjectType], - Tuple[_SubjectType, _PredicateType, List[_ObjectType]], - ], + triple: _TripleChoiceType, context: Optional[_ContextType] = None, ) -> Generator[_TripleType, None, None]: subject, predicate, object_ = triple @@ -1090,10 +1144,10 @@ def transitiveClosure( # noqa: N802 function against the graph >>> from rdflib.collection import Collection - >>> g=Graph() - >>> a=BNode("foo") - >>> b=BNode("bar") - >>> c=BNode("baz") + >>> g = Graph() + >>> a = BNode("foo") + >>> b = BNode("bar") + >>> c = BNode("baz") >>> g.add((a,RDF.first,RDF.type)) # doctest: +ELLIPSIS )> >>> g.add((a,RDF.rest,b)) # doctest: +ELLIPSIS @@ -1354,7 +1408,7 @@ def serialize( else: os_path = location with open(os_path, "wb") as stream: - serializer.serialize(stream, encoding=encoding, **args) + serializer.serialize(stream, base=base, encoding=encoding, **args) return self def print( @@ -1817,12 +1871,11 @@ def do_de_skolemize2(t: _TripleType) -> _TripleType: # type error: Argument 1 to "Genid" has incompatible type "Node"; expected "str" s = Genid(s).de_skolemize() # type: ignore[arg-type] - if RDFLibGenid._is_rdflib_skolem(o): - # type error: Argument 1 to "RDFLibGenid" has incompatible type "Node"; expected "str" - o = RDFLibGenid(o).de_skolemize() # type: ignore[arg-type] - elif Genid._is_external_skolem(o): - # type error: Argument 1 to "Genid" has incompatible type "Node"; expected "str" - o = Genid(o).de_skolemize() # type: ignore[arg-type] + if isinstance(o, URIRef): + if RDFLibGenid._is_rdflib_skolem(o): + o = RDFLibGenid(o).de_skolemize() + elif Genid._is_external_skolem(o): + o = Genid(o).de_skolemize() return s, p, o @@ -1916,7 +1969,7 @@ class ConjunctiveGraph(Graph): All queries are carried out against the union of all graphs. """ - default_context: _ContextType + _default_context: _ContextType def __init__( self, @@ -1938,10 +1991,18 @@ def __init__( ) self.context_aware = True self.default_union = True # Conjunctive! - self.default_context: _ContextType = Graph( + self._default_context: _ContextType = Graph( store=self.store, identifier=identifier or BNode(), base=default_graph_base ) + @property + def default_context(self): + return self._default_context + + @default_context.setter + def default_context(self, value): + self._default_context = value + def __str__(self) -> str: pattern = ( "[a rdflib:ConjunctiveGraph;rdflib:storage " @@ -2051,7 +2112,19 @@ def _graph( if not isinstance(c, Graph): return self.get_context(c) else: - return c + if isinstance(c, (Dataset, ConjunctiveGraph)): + # Preserve the old behaviour for datasets. + return c + else: + # Copy the graph triples so they're added to the store. + try: + _graph = self.get_graph(c.identifier) + assert _graph is not None + except IndexError: + _graph = self.get_context(c.identifier) + _graph.__iadd__(c) + # Return the graph with the same backing store. + return _graph def addN( # noqa: N802 self: _ConjunctiveGraphT, quads: Iterable[_QuadType] @@ -2145,11 +2218,7 @@ def quads( def triples_choices( self, - triple: Union[ - Tuple[List[_SubjectType], _PredicateType, _ObjectType], - Tuple[_SubjectType, List[_PredicateType], _ObjectType], - Tuple[_SubjectType, _PredicateType, List[_ObjectType]], - ], + triple: _TripleChoiceType, context: Optional[_ContextType] = None, ) -> Generator[_TripleType, None, None]: """Iterate over all the triples in the entire conjunctive graph""" @@ -2285,8 +2354,7 @@ def parse( context = self.default_context context.parse(source, publicID=publicID, format=format, **args) - # TODO: FIXME: This should not return context, but self. - return context + return self def __reduce__(self) -> Tuple[Type[Graph], Tuple[Store, _ContextIdentifierType]]: return ConjunctiveGraph, (self.store, self.identifier) @@ -2297,21 +2365,49 @@ def __reduce__(self) -> Tuple[Type[Graph], Tuple[Store, _ContextIdentifierType]] class Dataset(ConjunctiveGraph): """ - RDF 1.1 Dataset. Small extension to the Conjunctive Graph: - - the primary term is graphs in the datasets and not contexts with quads, - so there is a separate method to set/retrieve a graph in a dataset and - operate with graphs - - graphs cannot be identified with blank nodes - - added a method to directly add a single quad + An RDFLib Dataset is an object that stores multiple Named Graphs - instances of + RDFLib Graph identified by IRI - within it and allows whole-of-dataset or single + Graph use. + + RDFLib's Dataset class is based on the `RDF 1.2. 'Dataset' definition + `_: + + .. + + An RDF dataset is a collection of RDF graphs, and comprises: + + - Exactly one default graph, being an RDF graph. The default graph does not + have a name and MAY be empty. + - Zero or more named graphs. Each named graph is a pair consisting of an IRI or + a blank node (the graph name), and an RDF graph. Graph names are unique + within an RDF dataset. + + Accordingly, a Dataset allows for `Graph` objects to be added to it with + :class:`rdflib.term.URIRef` or :class:`rdflib.term.BNode` identifiers and always + creats a default graph with the :class:`rdflib.term.URIRef` identifier + :code:`urn:x-rdflib:default`. + + Dataset extends Graph's Subject, Predicate, Object (s, p, o) 'triple' + structure to include a graph identifier - archaically called Context - producing + 'quads' of s, p, o, g. + + Triples, or quads, can be added to a Dataset. Triples, or quads with the graph + identifer :code:`urn:x-rdflib:default` go into the default graph. - Examples of usage: + .. note:: Dataset builds on the `ConjunctiveGraph` class but that class's direct + use is now deprecated (since RDFLib 7.x) and it should not be used. + `ConjunctiveGraph` will be removed from future RDFLib versions. + + Examples of usage and see also the examples/datast.py file: >>> # Create a new Dataset >>> ds = Dataset() >>> # simple triples goes to default graph - >>> ds.add((URIRef("http://example.org/a"), - ... URIRef("http://www.example.org/b"), - ... Literal("foo"))) # doctest: +ELLIPSIS + >>> ds.add(( + ... URIRef("http://example.org/a"), + ... URIRef("http://www.example.org/b"), + ... Literal("foo") + ... )) # doctest: +ELLIPSIS )> >>> >>> # Create a graph in the dataset, if the graph name has already been @@ -2320,16 +2416,19 @@ class Dataset(ConjunctiveGraph): >>> g = ds.graph(URIRef("http://www.example.com/gr")) >>> >>> # add triples to the new graph as usual - >>> g.add( - ... (URIRef("http://example.org/x"), + >>> g.add(( + ... URIRef("http://example.org/x"), ... URIRef("http://example.org/y"), - ... Literal("bar")) ) # doctest: +ELLIPSIS + ... Literal("bar") + ... )) # doctest: +ELLIPSIS )> >>> # alternatively: add a quad to the dataset -> goes to the graph - >>> ds.add( - ... (URIRef("http://example.org/x"), + >>> ds.add(( + ... URIRef("http://example.org/x"), ... URIRef("http://example.org/z"), - ... Literal("foo-bar"),g) ) # doctest: +ELLIPSIS + ... Literal("foo-bar"), + ... g + ... )) # doctest: +ELLIPSIS )> >>> >>> # querying triples return them all regardless of the graph @@ -2395,8 +2494,8 @@ class Dataset(ConjunctiveGraph): >>> >>> # graph names in the dataset can be queried: >>> for c in ds.graphs(): # doctest: +SKIP - ... print(c) # doctest: - DEFAULT + ... print(c.identifier) # doctest: + urn:x-rdflib:default http://www.example.com/gr >>> # A graph can be created without specifying a name; a skolemized genid >>> # is created on the fly @@ -2415,7 +2514,7 @@ class Dataset(ConjunctiveGraph): >>> >>> # a graph can also be removed from a dataset via ds.remove_graph(g) - .. versionadded:: 4.0 + ... versionadded:: 4.0 """ def __init__( @@ -2428,7 +2527,7 @@ def __init__( if not self.store.graph_aware: raise Exception("DataSet must be backed by a graph-aware store!") - self.default_context = Graph( + self._default_context = Graph( store=self.store, identifier=DATASET_DEFAULT_GRAPH_ID, base=default_graph_base, @@ -2436,6 +2535,41 @@ def __init__( self.default_union = default_union + @property + def default_context(self): + warnings.warn( + "Dataset.default_context is deprecated, use Dataset.default_graph instead.", + DeprecationWarning, + stacklevel=2, + ) + return self._default_context + + @default_context.setter + def default_context(self, value): + warnings.warn( + "Dataset.default_context is deprecated, use Dataset.default_graph instead.", + DeprecationWarning, + stacklevel=2, + ) + self._default_context = value + + @property + def default_graph(self): + return self._default_context + + @default_graph.setter + def default_graph(self, value): + self._default_context = value + + @property + def identifier(self): + warnings.warn( + "Dataset.identifier is deprecated and will be removed in future versions.", + DeprecationWarning, + stacklevel=2, + ) + return super(Dataset, self).identifier + def __str__(self) -> str: pattern = ( "[a rdflib:Dataset;rdflib:storage " "[a rdflib:Store;rdfs:label '%s']]" @@ -2448,14 +2582,14 @@ def __reduce__(self) -> Tuple[Type[Dataset], Tuple[Store, bool]]: # type: ignor return (type(self), (self.store, self.default_union)) def __getstate__(self) -> Tuple[Store, _ContextIdentifierType, _ContextType, bool]: - return self.store, self.identifier, self.default_context, self.default_union + return self.store, self.identifier, self.default_graph, self.default_union def __setstate__( self, state: Tuple[Store, _ContextIdentifierType, _ContextType, bool] ) -> None: # type error: Property "store" defined in "Graph" is read-only # type error: Property "identifier" defined in "Graph" is read-only - self.store, self.identifier, self.default_context, self.default_union = state # type: ignore[misc] + self.store, self.identifier, self.default_graph, self.default_union = state # type: ignore[misc] def graph( self, @@ -2489,7 +2623,7 @@ def parse( file: Optional[Union[BinaryIO, TextIO]] = None, data: Optional[Union[str, bytes]] = None, **args: Any, - ) -> Graph: + ) -> Dataset: """ Parse an RDF source adding the resulting triples to the Graph. @@ -2499,7 +2633,7 @@ def parse( If the source is in a format that does not support named graphs its triples will be added to the default graph - (i.e. :attr:`.Dataset.default_context`). + (i.e. :attr:`.Dataset.default_graph`). .. caution:: @@ -2520,14 +2654,13 @@ def parse( the ``publicID`` parameter will also not be used as the name for the graph that the data is loaded into, and instead the triples from sources that do not support named graphs will be loaded into the default graph - (i.e. :attr:`.Dataset.default_context`). + (i.e. :attr:`.Dataset.default_graph`). """ - c = ConjunctiveGraph.parse( + ConjunctiveGraph.parse( self, source, publicID, format, location, file, data, **args ) - self.graph(c) - return c + return self def add_graph( self, g: Optional[Union[_ContextIdentifierType, _ContextType, str]] @@ -2542,15 +2675,20 @@ def remove_graph( g = self.get_context(g) self.store.remove_graph(g) - if g is None or g == self.default_context: + if g is None or g == self.default_graph: # default graph cannot be removed # only triples deleted, so add it back in - self.store.add_graph(self.default_context) + self.store.add_graph(self.default_graph) return self def contexts( self, triple: Optional[_TripleType] = None ) -> Generator[_ContextType, None, None]: + warnings.warn( + "Dataset.contexts is deprecated, use Dataset.graphs instead.", + DeprecationWarning, + stacklevel=2, + ) default = False for c in super(Dataset, self).contexts(triple): default |= c.identifier == DATASET_DEFAULT_GRAPH_ID @@ -2558,7 +2696,15 @@ def contexts( if not default: yield self.graph(DATASET_DEFAULT_GRAPH_ID) - graphs = contexts + def graphs( + self, triple: Optional[_TripleType] = None + ) -> Generator[_ContextType, None, None]: + default = False + for c in super(Dataset, self).contexts(triple): + default |= c.identifier == DATASET_DEFAULT_GRAPH_ID + yield c + if not default: + yield self.graph(DATASET_DEFAULT_GRAPH_ID) # type error: Return type "Generator[Tuple[Node, Node, Node, Optional[Node]], None, None]" of "quads" incompatible with return type "Generator[Tuple[Node, Node, Node, Optional[Graph]], None, None]" in supertype "ConjunctiveGraph" def quads( # type: ignore[override] @@ -2566,7 +2712,7 @@ def quads( # type: ignore[override] ) -> Generator[_OptionalIdentifiedQuadType, None, None]: for s, p, o, c in super(Dataset, self).quads(quad): # type error: Item "None" of "Optional[Graph]" has no attribute "identifier" - if c.identifier == self.default_context: # type: ignore[union-attr] + if c.identifier == self.default_graph: # type: ignore[union-attr] yield s, p, o, None else: # type error: Item "None" of "Optional[Graph]" has no attribute "identifier" [union-attr] @@ -2579,6 +2725,73 @@ def __iter__( # type: ignore[override] """Iterates over all quads in the store""" return self.quads((None, None, None, None)) + @overload + def serialize( + self, + destination: None, + format: str, + base: Optional[str], + encoding: str, + **args: Any, + ) -> bytes: ... + + # no destination and non-None keyword encoding + @overload + def serialize( + self, + destination: None = ..., + format: str = ..., + base: Optional[str] = ..., + *, + encoding: str, + **args: Any, + ) -> bytes: ... + + # no destination and None encoding + @overload + def serialize( + self, + destination: None = ..., + format: str = ..., + base: Optional[str] = ..., + encoding: None = ..., + **args: Any, + ) -> str: ... + + # non-None destination + @overload + def serialize( + self, + destination: Union[str, pathlib.PurePath, IO[bytes]], + format: str = ..., + base: Optional[str] = ..., + encoding: Optional[str] = ..., + **args: Any, + ) -> Graph: ... + + # fallback + @overload + def serialize( + self, + destination: Optional[Union[str, pathlib.PurePath, IO[bytes]]] = ..., + format: str = ..., + base: Optional[str] = ..., + encoding: Optional[str] = ..., + **args: Any, + ) -> Union[bytes, str, Graph]: ... + + def serialize( + self, + destination: Optional[Union[str, pathlib.PurePath, IO[bytes]]] = None, + format: str = "trig", + base: Optional[str] = None, + encoding: Optional[str] = None, + **args: Any, + ) -> Union[bytes, str, Graph]: + return super(Dataset, self).serialize( + destination=destination, format=format, base=base, encoding=encoding, **args + ) + class QuotedGraph(Graph): """ @@ -2746,7 +2959,7 @@ def commit(self) -> NoReturn: def rollback(self) -> NoReturn: raise ModificationException() - def open(self, configuration: str, create: bool = False) -> None: + def open(self, configuration: str | tuple[str, str], create: bool = False) -> None: # TODO: is there a use case for this method? for graph in self.graphs: # type error: Too many arguments for "open" of "Graph" @@ -2864,11 +3077,7 @@ def __isub__(self: _GraphT, other: Iterable[_TripleType]) -> NoReturn: def triples_choices( self, - triple: Union[ - Tuple[List[_SubjectType], _PredicateType, _ObjectType], - Tuple[_SubjectType, List[_PredicateType], _ObjectType], - Tuple[_SubjectType, _PredicateType, List[_ObjectType]], - ], + triple: _TripleChoiceType, context: Optional[_ContextType] = None, ) -> Generator[_TripleType, None, None]: subject, predicate, object_ = triple diff --git a/rdflib/namespace/__init__.py b/rdflib/namespace/__init__.py index 4077b0be3..cd2946ad5 100644 --- a/rdflib/namespace/__init__.py +++ b/rdflib/namespace/__init__.py @@ -74,6 +74,22 @@ import logging import warnings + +try: + # Python >= 3.14 + from annotationlib import ( + get_annotations, # type: ignore[attr-defined,unused-ignore] + ) +except ImportError: # pragma: no cover + try: + # Python >= 3.10 + from inspect import get_annotations # type: ignore[attr-defined,unused-ignore] + except ImportError: + + def get_annotations(thing: Any) -> dict: + return thing.__annotations__ + + from functools import lru_cache from pathlib import Path from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Set, Tuple, Union @@ -226,6 +242,7 @@ def __repr__(self) -> str: # considered part of __dir__ results. These should be all annotations on # `DefinedNamespaceMeta`. _DFNS_RESERVED_ATTRS: Set[str] = { + "__slots__", "_NS", "_warn", "_fail", @@ -244,6 +261,8 @@ def __repr__(self) -> str: class DefinedNamespaceMeta(type): """Utility metaclass for generating URIRefs with a common prefix.""" + __slots__: Tuple[str, ...] = tuple() + _NS: Namespace _warn: bool = True _fail: bool = False # True means mimic ClosedNamespace @@ -255,15 +274,11 @@ def __getitem__(cls, name: str, default=None) -> URIRef: name = str(name) if name in _DFNS_RESERVED_ATTRS: - raise AttributeError( - f"DefinedNamespace like object has no attribute {name!r}" + raise KeyError( + f"DefinedNamespace like object has no access item named {name!r}" ) elif name in _IGNORED_ATTR_LOOKUP: raise KeyError() - if str(name).startswith("__"): - # NOTE on type ignore: This seems to be a real bug, super() does not - # implement this method, it will fail if it is ever reached. - return super().__getitem__(name, default) # type: ignore[misc] # undefined in superclass if (cls._warn or cls._fail) and name not in cls: if cls._fail: raise AttributeError(f"term '{name}' not in namespace '{cls._NS}'") @@ -277,28 +292,41 @@ def __getitem__(cls, name: str, default=None) -> URIRef: def __getattr__(cls, name: str): if name in _IGNORED_ATTR_LOOKUP: raise AttributeError() + elif name in _DFNS_RESERVED_ATTRS: + raise AttributeError( + f"DefinedNamespace like object has no attribute {name!r}" + ) + elif name.startswith("__"): + return super(DefinedNamespaceMeta, cls).__getattribute__(name) return cls.__getitem__(name) def __repr__(cls) -> str: - return f"Namespace({str(cls._NS)!r})" + try: + ns_repr = repr(cls._NS) + except AttributeError: + ns_repr = "" + return f"Namespace({ns_repr})" def __str__(cls) -> str: - return str(cls._NS) + try: + return str(cls._NS) + except AttributeError: + return "" def __add__(cls, other: str) -> URIRef: return cls.__getitem__(other) def __contains__(cls, item: str) -> bool: """Determine whether a URI or an individual item belongs to this namespace""" + try: + this_ns = cls._NS + except AttributeError: + return False item_str = str(item) - if item_str.startswith("__"): - # NOTE on type ignore: This seems to be a real bug, super() does not - # implement this method, it will fail if it is ever reached. - return super().__contains__(item) # type: ignore[misc] # undefined in superclass - if item_str.startswith(str(cls._NS)): - item_str = item_str[len(str(cls._NS)) :] + if item_str.startswith(str(this_ns)): + item_str = item_str[len(str(this_ns)) :] return any( - item_str in c.__annotations__ + item_str in get_annotations(c) or item_str in c._extras or (cls._underscore_num and item_str[0] == "_" and item_str[1:].isdigit()) for c in cls.mro() @@ -306,16 +334,16 @@ def __contains__(cls, item: str) -> bool: ) def __dir__(cls) -> Iterable[str]: - attrs = {str(x) for x in cls.__annotations__} + attrs = {str(x) for x in get_annotations(cls)} # Removing these as they should not be considered part of the namespace. attrs.difference_update(_DFNS_RESERVED_ATTRS) values = {cls[str(x)] for x in attrs} return values def as_jsonld_context(self, pfx: str) -> dict: # noqa: N804 - """Returns this DefinedNamespace as a a JSON-LD 'context' object""" + """Returns this DefinedNamespace as a JSON-LD 'context' object""" terms = {pfx: str(self._NS)} - for key, term in self.__annotations__.items(): + for key, term in get_annotations(self).items(): if issubclass(term, URIRef): terms[key] = f"{pfx}:{key}" @@ -328,6 +356,8 @@ class DefinedNamespace(metaclass=DefinedNamespaceMeta): Warnings are emitted if unknown members are referenced if _warn is True """ + __slots__: Tuple[str, ...] = tuple() + def __init__(self): raise TypeError("namespace may not be instantiated") @@ -704,7 +734,7 @@ def _store_bind(self, prefix: str, namespace: URIRef, override: bool) -> None: return self.store.bind(prefix, namespace, override=override) except TypeError as error: if "override" in str(error): - logger.warning( + logger.debug( "caught a TypeError, " "retrying call to %s.bind without override, " "see https://github.com/RDFLib/rdflib/issues/1880 for more info", diff --git a/rdflib/plugin.py b/rdflib/plugin.py index 23699e68d..556b78804 100644 --- a/rdflib/plugin.py +++ b/rdflib/plugin.py @@ -579,18 +579,6 @@ def plugins( "rdflib.plugins.sparql.results.xmlresults", "XMLResultParser", ) -register( - "application/sparql-results+xml; charset=UTF-8", - ResultParser, - "rdflib.plugins.sparql.results.xmlresults", - "XMLResultParser", -) -register( - "application/rdf+xml", - ResultParser, - "rdflib.plugins.sparql.results.graph", - "GraphResultParser", -) register( "json", ResultParser, @@ -627,3 +615,14 @@ def plugins( "rdflib.plugins.sparql.results.tsvresults", "TSVResultParser", ) + +graph_parsers = {parser.name for parser in plugins(kind=Parser)} +result_parsers = {parser.name for parser in plugins(kind=ResultParser)} +graph_result_parsers = graph_parsers - result_parsers +for parser_name in graph_result_parsers: + register( + parser_name, + ResultParser, + "rdflib.plugins.sparql.results.graph", + "GraphResultParser", + ) diff --git a/rdflib/plugins/parsers/jsonld.py b/rdflib/plugins/parsers/jsonld.py index 295a97126..e103e7033 100644 --- a/rdflib/plugins/parsers/jsonld.py +++ b/rdflib/plugins/parsers/jsonld.py @@ -34,6 +34,7 @@ # we should consider streaming the input to deal with arbitrarily large graphs. from __future__ import annotations +import secrets import warnings from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Union @@ -221,6 +222,7 @@ def __init__( if allow_lists_of_lists is not None else ALLOW_LISTS_OF_LISTS ) + self.invalid_uri_to_bnode: dict[str, BNode] = {} def parse(self, data: Any, context: Context, dataset: Graph) -> Graph: topcontext = False @@ -629,7 +631,12 @@ def _to_rdf_id(self, context: Context, id_val: str) -> Optional[IdentifiedNode]: uri = context.resolve(id_val) if not self.generalized_rdf and ":" not in uri: return None - return URIRef(uri) + node: IdentifiedNode = URIRef(uri) + if not str(node): + if id_val not in self.invalid_uri_to_bnode: + self.invalid_uri_to_bnode[id_val] = BNode(secrets.token_urlsafe(20)) + node = self.invalid_uri_to_bnode[id_val] + return node def _get_bnodeid(self, ref: str) -> Optional[str]: if not ref.startswith("_:"): diff --git a/rdflib/plugins/parsers/notation3.py b/rdflib/plugins/parsers/notation3.py index da71405e0..e9c2d0f27 100755 --- a/rdflib/plugins/parsers/notation3.py +++ b/rdflib/plugins/parsers/notation3.py @@ -57,7 +57,7 @@ from rdflib.compat import long_type from rdflib.exceptions import ParserError -from rdflib.graph import ConjunctiveGraph, Graph, QuotedGraph +from rdflib.graph import Dataset, Graph, QuotedGraph from rdflib.term import ( _XSD_PFX, BNode, @@ -83,6 +83,7 @@ "Formula", "RDFSink", "SinkParser", + "sfloat", ] from rdflib.parser import Parser @@ -380,6 +381,10 @@ def unicodeExpand(m: Match) -> str: langcode = re.compile(r"[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*") +class sfloat(str): # noqa: N801 + """don't normalize raw XSD.double string representation""" + + class SinkParser: def __init__( self, @@ -1528,7 +1533,7 @@ def nodeOrLiteral(self, argstr: str, i: int, res: MutableSequence[Any]) -> int: m = exponent_syntax.match(argstr, i) if m: j = m.end() - res.append(float(argstr[i:j])) + res.append(sfloat(argstr[i:j])) return j m = decimal_syntax.match(argstr, i) @@ -1911,7 +1916,7 @@ def makeStatement( def normalise( self, f: Optional[Formula], - n: Union[Tuple[int, str], bool, int, Decimal, float, _AnyT], + n: Union[Tuple[int, str], bool, int, Decimal, sfloat, _AnyT], ) -> Union[URIRef, Literal, BNode, _AnyT]: if isinstance(n, tuple): return URIRef(str(n[1])) @@ -1931,7 +1936,7 @@ def normalise( s = Literal(value, datatype=DECIMAL_DATATYPE) return s - if isinstance(n, float): + if isinstance(n, sfloat): s = Literal(str(n), datatype=DOUBLE_DATATYPE) return s @@ -1947,7 +1952,7 @@ def normalise( # f.universals[n] = f.newBlankNode() # return f.universals[n] # type error: Incompatible return value type (got "Union[int, _AnyT]", expected "Union[URIRef, Literal, BNode, _AnyT]") [return-value] - return n # type: ignore[return-value] + return n def intern(self, something: _AnyT) -> _AnyT: return something @@ -2047,7 +2052,7 @@ def parse( # type: ignore[override] elif not fa: raise ParserError("Cannot parse N3 into non-formula-aware store.") - conj_graph = ConjunctiveGraph(store=graph.store) + conj_graph = Dataset(store=graph.store) conj_graph.default_context = graph # TODO: CG __init__ should have a # default_context arg # TODO: update N3Processor so that it can use conj_graph as the sink diff --git a/rdflib/plugins/parsers/nquads.py b/rdflib/plugins/parsers/nquads.py index 60b793b65..cadcfa28a 100644 --- a/rdflib/plugins/parsers/nquads.py +++ b/rdflib/plugins/parsers/nquads.py @@ -7,7 +7,7 @@ >>> g = ConjunctiveGraph() >>> data = open("test/data/nquads.rdflib/example.nquads", "rb") >>> g.parse(data, format="nquads") # doctest:+ELLIPSIS -)> +)> >>> assert len(g.store) == 449 >>> # There should be 16 separate contexts >>> assert len([x for x in g.store.contexts()]) == 16 diff --git a/rdflib/plugins/serializers/hext.py b/rdflib/plugins/serializers/hext.py index 9a8187c76..898308a09 100644 --- a/rdflib/plugins/serializers/hext.py +++ b/rdflib/plugins/serializers/hext.py @@ -77,8 +77,8 @@ def serialize( stream: IO[bytes], base: Optional[str] = None, encoding: Optional[str] = "utf-8", - **kwargs, - ): + **kwargs: Any, + ) -> None: if base is not None: warnings.warn( "base has no meaning for Hextuples serialization. " diff --git a/rdflib/plugins/serializers/jsonld.py b/rdflib/plugins/serializers/jsonld.py index 15f307edf..0afe8305a 100644 --- a/rdflib/plugins/serializers/jsonld.py +++ b/rdflib/plugins/serializers/jsonld.py @@ -64,8 +64,8 @@ def serialize( stream: IO[bytes], base: Optional[str] = None, encoding: Optional[str] = None, - **kwargs, - ): + **kwargs: Any, + ) -> None: # TODO: docstring w. args and return value encoding = encoding or "utf-8" if encoding not in ("utf-8", "utf-16"): diff --git a/rdflib/plugins/serializers/longturtle.py b/rdflib/plugins/serializers/longturtle.py index e886574f3..1e68e6849 100644 --- a/rdflib/plugins/serializers/longturtle.py +++ b/rdflib/plugins/serializers/longturtle.py @@ -16,7 +16,13 @@ - Nicholas Car, 2023 """ +from __future__ import annotations + +from typing import IO, Any, Optional + +from rdflib.compare import to_canonical_graph from rdflib.exceptions import Error +from rdflib.graph import Graph, _TripleType from rdflib.namespace import RDF from rdflib.term import BNode, Literal, URIRef @@ -33,16 +39,24 @@ class LongTurtleSerializer(RecursiveSerializer): + """LongTurtle, a Turtle serialization format. + + When the optional parameter ``canon`` is set to :py:obj:`True`, the graph is canonicalized + before serialization. This normalizes blank node identifiers and allows for + deterministic serialization of the graph. Useful when consistent outputs are required. + """ + short_name = "longturtle" indentString = " " def __init__(self, store): self._ns_rewrite = {} + self._canon = False super(LongTurtleSerializer, self).__init__(store) self.keywords = {RDF.type: "a"} self.reset() self.stream = None - self._spacious = _SPACIOUS_OUTPUT + self._spacious: bool = _SPACIOUS_OUTPUT def addNamespace(self, prefix, namespace): # Turtle does not support prefixes that start with _ @@ -68,13 +82,44 @@ def addNamespace(self, prefix, namespace): super(LongTurtleSerializer, self).addNamespace(prefix, namespace) return prefix + def canonize(self): + """Apply canonicalization to the store. + + This normalizes blank node identifiers and allows for deterministic + serialization of the graph. + """ + if not self._canon: + return + + namespace_manager = self.store.namespace_manager + store = to_canonical_graph(self.store) + content = store.serialize(format="application/n-triples") + lines = content.split("\n") + lines.sort() + graph = Graph() + graph.parse( + data="\n".join(lines), format="application/n-triples", skolemize=True + ) + graph = graph.de_skolemize() + graph.namespace_manager = namespace_manager + self.store = graph + def reset(self): super(LongTurtleSerializer, self).reset() self._shortNames = {} self._started = False self._ns_rewrite = {} + self.canonize() - def serialize(self, stream, base=None, encoding=None, spacious=None, **args): + def serialize( + self, + stream: IO[bytes], + base: Optional[str] = None, + encoding: Optional[str] = None, + spacious: Optional[bool] = None, + **kwargs: Any, + ) -> None: + self._canon = kwargs.get("canon", False) self.reset() self.stream = stream # if base is given here, use, if not and a base is set for the graph use that @@ -104,11 +149,20 @@ def serialize(self, stream, base=None, encoding=None, spacious=None, **args): self.base = None - def preprocessTriple(self, triple): + def preprocessTriple(self, triple: _TripleType) -> None: super(LongTurtleSerializer, self).preprocessTriple(triple) for i, node in enumerate(triple): - if node in self.keywords: - continue + if i == VERB: + if node in self.keywords: + # predicate is a keyword + continue + if ( + self.base is not None + and isinstance(node, URIRef) + and node.startswith(self.base) + ): + # predicate corresponds to base namespace + continue # Don't use generated prefixes for subjects and objects self.getQName(node, gen_prefix=(i == VERB)) if isinstance(node, Literal) and node.datatype: @@ -135,6 +189,8 @@ def getQName(self, uri, gen_prefix=True): prefix, namespace, local = parts + local = local.replace(r"(", r"\(").replace(r")", r"\)") + # QName cannot end with . if local.endswith("."): return None @@ -175,7 +231,7 @@ def s_squared(self, subject): return False self.write("\n" + self.indent() + "[]") self.predicateList(subject, newline=False) - self.write(" ;\n.") + self.write("\n.") return True def path(self, node, position, newline=False): @@ -292,6 +348,8 @@ def objectList(self, objects): if count > 1: if not isinstance(objects[0], BNode): self.write("\n" + self.indent(1)) + else: + self.write(" ") first_nl = True self.path(objects[0], OBJECT, newline=first_nl) for obj in objects[1:]: diff --git a/rdflib/plugins/serializers/nquads.py b/rdflib/plugins/serializers/nquads.py index 3c8d02ccc..d88454d1e 100644 --- a/rdflib/plugins/serializers/nquads.py +++ b/rdflib/plugins/serializers/nquads.py @@ -1,9 +1,9 @@ from __future__ import annotations import warnings -from typing import IO, Optional +from typing import IO, Any, Optional -from rdflib.graph import ConjunctiveGraph, Graph +from rdflib.graph import DATASET_DEFAULT_GRAPH_ID, ConjunctiveGraph, Graph from rdflib.plugins.serializers.nt import _quoteLiteral from rdflib.serializer import Serializer from rdflib.term import Literal @@ -26,8 +26,8 @@ def serialize( stream: IO[bytes], base: Optional[str] = None, encoding: Optional[str] = None, - **args, - ): + **kwargs: Any, + ) -> None: if base is not None: warnings.warn("NQuadsSerializer does not support base.") if encoding is not None and encoding.lower() != self.encoding.lower(): @@ -45,17 +45,18 @@ def serialize( def _nq_row(triple, context): + graph_name = context.n3() if context and context != DATASET_DEFAULT_GRAPH_ID else "" if isinstance(triple[2], Literal): return "%s %s %s %s .\n" % ( triple[0].n3(), triple[1].n3(), _quoteLiteral(triple[2]), - context.n3(), + graph_name, ) else: return "%s %s %s %s .\n" % ( triple[0].n3(), triple[1].n3(), triple[2].n3(), - context.n3(), + graph_name, ) diff --git a/rdflib/plugins/serializers/nt.py b/rdflib/plugins/serializers/nt.py index e87f949e3..1b0343b5a 100644 --- a/rdflib/plugins/serializers/nt.py +++ b/rdflib/plugins/serializers/nt.py @@ -2,7 +2,7 @@ import codecs import warnings -from typing import IO, TYPE_CHECKING, Optional, Tuple, Union +from typing import IO, TYPE_CHECKING, Any, Optional, Tuple, Union from rdflib.graph import Graph from rdflib.serializer import Serializer @@ -33,7 +33,7 @@ def serialize( stream: IO[bytes], base: Optional[str] = None, encoding: Optional[str] = "utf-8", - **args, + **kwargs: Any, ) -> None: if base is not None: warnings.warn("NTSerializer does not support base.") diff --git a/rdflib/plugins/serializers/patch.py b/rdflib/plugins/serializers/patch.py index 3a5d37215..1bc5ff41f 100644 --- a/rdflib/plugins/serializers/patch.py +++ b/rdflib/plugins/serializers/patch.py @@ -1,7 +1,7 @@ from __future__ import annotations import warnings -from typing import IO, Optional +from typing import IO, Any, Optional from uuid import uuid4 from rdflib import Dataset @@ -32,8 +32,8 @@ def serialize( stream: IO[bytes], base: Optional[str] = None, encoding: Optional[str] = None, - **kwargs, - ): + **kwargs: Any, + ) -> None: """ Serialize the store to the given stream. :param stream: The stream to serialize to. diff --git a/rdflib/plugins/serializers/rdfxml.py b/rdflib/plugins/serializers/rdfxml.py index d6a2f6abb..8ae7d78cb 100644 --- a/rdflib/plugins/serializers/rdfxml.py +++ b/rdflib/plugins/serializers/rdfxml.py @@ -1,7 +1,7 @@ from __future__ import annotations import xml.dom.minidom -from typing import IO, Dict, Generator, Optional, Set, Tuple +from typing import IO, Any, Dict, Generator, Optional, Set, Tuple from xml.sax.saxutils import escape, quoteattr from rdflib.collection import Collection @@ -47,7 +47,7 @@ def serialize( stream: IO[bytes], base: Optional[str] = None, encoding: Optional[str] = None, - **args, + **kwargs: Any, ) -> None: # if base is given here, use that, if not and a base is set for the graph use that if base is not None: @@ -66,8 +66,8 @@ def serialize( write(" None: self.__serialized: Dict[Identifier, int] = {} store = self.store @@ -185,7 +185,7 @@ def serialize( self.base = base elif store.base is not None: self.base = store.base - self.max_depth = args.get("max_depth", 3) + self.max_depth = kwargs.get("max_depth", 3) assert self.max_depth > 0, "max_depth must be greater than 0" self.nm = nm = store.namespace_manager @@ -205,8 +205,8 @@ def serialize( writer.push(RDFVOC.RDF) - if "xml_base" in args: - writer.attribute(XMLBASE, args["xml_base"]) + if "xml_base" in kwargs: + writer.attribute(XMLBASE, kwargs["xml_base"]) elif self.base: writer.attribute(XMLBASE, self.base) diff --git a/rdflib/plugins/serializers/trig.py b/rdflib/plugins/serializers/trig.py index 984f80c5a..95b5e42c0 100644 --- a/rdflib/plugins/serializers/trig.py +++ b/rdflib/plugins/serializers/trig.py @@ -5,7 +5,7 @@ from __future__ import annotations -from typing import IO, TYPE_CHECKING, Dict, List, Optional, Tuple, Union +from typing import IO, TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union from rdflib.graph import ConjunctiveGraph, Graph from rdflib.plugins.serializers.turtle import TurtleSerializer @@ -67,8 +67,8 @@ def serialize( base: Optional[str] = None, encoding: Optional[str] = None, spacious: Optional[bool] = None, - **args, - ): + **kwargs: Any, + ) -> None: self.reset() self.stream = stream # if base is given here, use that, if not and a base is set for the graph use that diff --git a/rdflib/plugins/serializers/trix.py b/rdflib/plugins/serializers/trix.py index 008360e6b..95730e8fb 100644 --- a/rdflib/plugins/serializers/trix.py +++ b/rdflib/plugins/serializers/trix.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import IO, Optional +from typing import IO, Any, Optional from rdflib.graph import ConjunctiveGraph, Graph from rdflib.namespace import Namespace @@ -28,8 +28,8 @@ def serialize( stream: IO[bytes], base: Optional[str] = None, encoding: Optional[str] = None, - **args, - ): + **kwargs: Any, + ) -> None: nm = self.store.namespace_manager self.writer = XMLWriter(stream, nm, encoding, extra_ns={"": TRIXNS}) diff --git a/rdflib/plugins/serializers/turtle.py b/rdflib/plugins/serializers/turtle.py index a26df04a6..abee2e43b 100644 --- a/rdflib/plugins/serializers/turtle.py +++ b/rdflib/plugins/serializers/turtle.py @@ -228,7 +228,7 @@ def serialize( base: Optional[str] = None, encoding: Optional[str] = None, spacious: Optional[bool] = None, - **args: Any, + **kwargs: Any, ) -> None: self.reset() self.stream = stream @@ -263,9 +263,17 @@ def serialize( def preprocessTriple(self, triple: _TripleType) -> None: super(TurtleSerializer, self).preprocessTriple(triple) for i, node in enumerate(triple): - if i == VERB and node in self.keywords: - # predicate is a keyword - continue + if i == VERB: + if node in self.keywords: + # predicate is a keyword + continue + if ( + self.base is not None + and isinstance(node, URIRef) + and node.startswith(self.base) + ): + # predicate corresponds to base namespace + continue # Don't use generated prefixes for subjects and objects self.getQName(node, gen_prefix=(i == VERB)) if isinstance(node, Literal) and node.datatype: diff --git a/rdflib/plugins/sparql/evaluate.py b/rdflib/plugins/sparql/evaluate.py index 82fe8034f..363918179 100644 --- a/rdflib/plugins/sparql/evaluate.py +++ b/rdflib/plugins/sparql/evaluate.py @@ -191,7 +191,7 @@ def evalLeftJoin( for b in evalPart(c, join.p2): if _ebv(join.expr, b.forget(ctx)): ok = True - yield b + yield b.merge(a) if not ok: # we've cheated, the ctx above may contain # vars bound outside our scope diff --git a/rdflib/plugins/sparql/parser.py b/rdflib/plugins/sparql/parser.py index 3ee230f53..789d07610 100644 --- a/rdflib/plugins/sparql/parser.py +++ b/rdflib/plugins/sparql/parser.py @@ -1483,7 +1483,7 @@ def expandCollection(terms: ParseResults) -> List[List[Any]]: AskQuery = Comp( "AskQuery", Keyword("ASK") - + Param("datasetClause", ZeroOrMore(DatasetClause)) + + ZeroOrMore(ParamList("datasetClause", DatasetClause)) + WhereClause + SolutionModifier + ValuesClause, diff --git a/rdflib/plugins/sparql/update.py b/rdflib/plugins/sparql/update.py index cd22a7520..c9d36564c 100644 --- a/rdflib/plugins/sparql/update.py +++ b/rdflib/plugins/sparql/update.py @@ -181,8 +181,11 @@ def evalModify(ctx: QueryContext, u: CompValue) -> None: g = ctx.dataset.get_context(u.withClause) ctx = ctx.pushGraph(g) - for c in res: - dg = ctx.graph + for c in list(res): + # TODO: Make this more intentional and without the weird type checking logic + # once ConjunctiveGraph is removed and Dataset no longer inherits from + # Graph. + dg = ctx.graph if type(ctx.graph) is Graph else ctx.dataset.default_context if u.delete: # type error: Unsupported left operand type for - ("None") # type error: Unsupported operand types for - ("Graph" and "Generator[Tuple[Identifier, Identifier, Identifier], None, None]") diff --git a/rdflib/plugins/stores/auditable.py b/rdflib/plugins/stores/auditable.py index 7a9748c69..ca2c7d79b 100644 --- a/rdflib/plugins/stores/auditable.py +++ b/rdflib/plugins/stores/auditable.py @@ -10,7 +10,7 @@ Calls to commit or rollback, flush the list of reverse operations This provides thread-safe atomicity and isolation (assuming concurrent operations occur with different store instances), but no durability (transactions are -persisted in memory and wont be available to reverse operations after the +persisted in memory and won't be available to reverse operations after the system fails): A and I out of ACID. """ @@ -18,7 +18,7 @@ from __future__ import annotations import threading -from typing import TYPE_CHECKING, Any, Generator, Iterator, List, Optional, Tuple +from typing import TYPE_CHECKING, Any, Generator, Iterator, List, Optional, Tuple, Union from rdflib.graph import ConjunctiveGraph, Graph from rdflib.store import Store @@ -62,7 +62,9 @@ def __init__(self, store: Store): ] = [] self.rollbackLock = threading.RLock() - def open(self, configuration: str, create: bool = True) -> Optional[int]: + def open( + self, configuration: Union[str, tuple[str, str]], create: bool = True + ) -> Optional[int]: return self.store.open(configuration, create) def close(self, commit_pending_transaction: bool = False) -> None: diff --git a/rdflib/plugins/stores/berkeleydb.py b/rdflib/plugins/stores/berkeleydb.py index 12009787c..11195432f 100644 --- a/rdflib/plugins/stores/berkeleydb.py +++ b/rdflib/plugins/stores/berkeleydb.py @@ -4,7 +4,17 @@ from os import mkdir from os.path import abspath, exists from threading import Thread -from typing import TYPE_CHECKING, Any, Callable, Dict, Generator, List, Optional, Tuple +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Dict, + Generator, + List, + Optional, + Tuple, + Union, +) from urllib.request import pathname2url from rdflib.store import NO_STORE, VALID_STORE, Store @@ -127,10 +137,16 @@ def _init_db_environment( def is_open(self) -> bool: return self.__open - def open(self, path: str, create: bool = True) -> Optional[int]: + def open( + self, configuration: Union[str, tuple[str, str]], create: bool = True + ) -> Optional[int]: if not has_bsddb: return NO_STORE - homeDir = path # noqa: N806 + + if type(configuration) is str: + homeDir = configuration # noqa: N806 + else: + raise Exception("Invalid configuration provided") if self.__identifier is None: self.__identifier = URIRef(pathname2url(http://github.com/abspath(homeDir))) diff --git a/rdflib/plugins/stores/sparqlconnector.py b/rdflib/plugins/stores/sparqlconnector.py index e2bb83909..d4cb86c63 100644 --- a/rdflib/plugins/stores/sparqlconnector.py +++ b/rdflib/plugins/stores/sparqlconnector.py @@ -9,8 +9,10 @@ from urllib.parse import urlencode from urllib.request import Request, urlopen -from rdflib.query import Result +from rdflib.plugin import plugins +from rdflib.query import Result, ResultParser from rdflib.term import BNode +from rdflib.util import FORMAT_MIMETYPE_MAP, RESPONSE_TABLE_FORMAT_MIMETYPE_MAP log = logging.getLogger(__name__) @@ -22,16 +24,6 @@ class SPARQLConnectorException(Exception): # noqa: N818 pass -# TODO: Pull in these from the result implementation plugins? -_response_mime_types = { - "xml": "application/sparql-results+xml, application/rdf+xml", - "json": "application/sparql-results+json", - "csv": "text/csv", - "tsv": "text/tab-separated-values", - "application/rdf+xml": "application/rdf+xml", -} - - class SPARQLConnector: """ this class deals with nitty gritty details of talking to a SPARQL server @@ -41,7 +33,7 @@ def __init__( self, query_endpoint: Optional[str] = None, update_endpoint: Optional[str] = None, - returnFormat: str = "xml", # noqa: N803 + returnFormat: Optional[str] = "xml", # noqa: N803 method: te.Literal["GET", "POST", "POST_FORM"] = "GET", auth: Optional[Tuple[str, str]] = None, **kwargs, @@ -95,7 +87,7 @@ def query( if default_graph is not None and type(default_graph) is not BNode: params["default-graph-uri"] = default_graph - headers = {"Accept": _response_mime_types[self.returnFormat]} + headers = {"Accept": self.response_mime_types()} args = copy.deepcopy(self.kwargs) @@ -170,7 +162,7 @@ def update( params["using-named-graph-uri"] = named_graph headers = { - "Accept": _response_mime_types[self.returnFormat], + "Accept": self.response_mime_types(), "Content-Type": "application/sparql-update; charset=UTF-8", } @@ -188,5 +180,27 @@ def update( ) ) + def response_mime_types(self) -> str: + """Construct a HTTP-Header Accept field to reflect the supported mime types. + + If the return_format parameter is set, the mime types are restricted to these accordingly. + """ + sparql_format_mimetype_map = { + k: FORMAT_MIMETYPE_MAP.get(k, []) + + RESPONSE_TABLE_FORMAT_MIMETYPE_MAP.get(k, []) + for k in list(FORMAT_MIMETYPE_MAP.keys()) + + list(RESPONSE_TABLE_FORMAT_MIMETYPE_MAP.keys()) + } + + supported_formats = set() + for plugin in plugins(name=self.returnFormat, kind=ResultParser): + if "/" not in plugin.name: + supported_formats.update( + sparql_format_mimetype_map.get(plugin.name, []) + ) + else: + supported_formats.add(plugin.name) + return ", ".join(supported_formats) + __all__ = ["SPARQLConnector", "SPARQLConnectorException"] diff --git a/rdflib/plugins/stores/sparqlstore.py b/rdflib/plugins/stores/sparqlstore.py index f9827cf94..2d3e259fe 100644 --- a/rdflib/plugins/stores/sparqlstore.py +++ b/rdflib/plugins/stores/sparqlstore.py @@ -35,6 +35,7 @@ _TripleType, _ContextType, _QuadType, + _TripleChoiceType, _TriplePatternType, _SubjectType, _PredicateType, @@ -128,7 +129,7 @@ def __init__( sparql11: bool = True, context_aware: bool = True, node_to_sparql: _NodeToSparql = _node_to_sparql, - returnFormat: str = "xml", # noqa: N803 + returnFormat: Optional[str] = "xml", # noqa: N803 auth: Optional[Tuple[str, str]] = None, **sparqlconnector_kwargs, ): @@ -147,11 +148,11 @@ def __init__( self._queries = 0 # type error: Missing return statement - def open(self, configuration: str, create: bool = False) -> Optional[int]: # type: ignore[return] + def open(self, configuration: Union[str, tuple[str, str]], create: bool = False) -> Optional[int]: # type: ignore[return] """This method is included so that calls to this Store via Graph, e.g. Graph("SPARQLStore"), can set the required parameters """ - if type(configuration) == str: # noqa: E721 + if type(configuration) is str: self.query_endpoint = configuration else: raise Exception( @@ -367,11 +368,7 @@ def triples( # type: ignore[override] def triples_choices( self, - _: Tuple[ - Union[_SubjectType, List[_SubjectType]], - Union[_PredicateType, List[_PredicateType]], - Union[_ObjectType, List[_ObjectType]], - ], + _: _TripleChoiceType, context: Optional[_ContextType] = None, ) -> Generator[ Tuple[ diff --git a/rdflib/store.py b/rdflib/store.py index 2ca03529a..86dabf185 100644 --- a/rdflib/store.py +++ b/rdflib/store.py @@ -36,7 +36,6 @@ Generator, Iterable, Iterator, - List, Mapping, Optional, Tuple, @@ -49,10 +48,8 @@ from rdflib.graph import ( Graph, _ContextType, - _ObjectType, - _PredicateType, _QuadType, - _SubjectType, + _TripleChoiceType, _TriplePatternType, _TripleType, ) @@ -208,9 +205,10 @@ def node_pickler(self) -> NodePickler: def create(self, configuration: str) -> None: self.dispatcher.dispatch(StoreCreatedEvent(configuration=configuration)) - def open(self, configuration: str, create: bool = False) -> Optional[int]: - """ - Opens the store specified by the configuration string. If + def open( + self, configuration: Union[str, tuple[str, str]], create: bool = False + ) -> Optional[int]: + """Opens the store specified by the configuration string or tuple. If create is True a store will be created if it does not already exist. If create is False and a store does not already exist an exception is raised. An exception is also raised if a store @@ -281,11 +279,7 @@ def remove( def triples_choices( self, - triple: Union[ - Tuple[List[_SubjectType], _PredicateType, _ObjectType], - Tuple[_SubjectType, List[_PredicateType], _ObjectType], - Tuple[_SubjectType, _PredicateType, List[_ObjectType]], - ], + triple: _TripleChoiceType, context: Optional[_ContextType] = None, ) -> Generator[ Tuple[ diff --git a/rdflib/term.py b/rdflib/term.py index 3e397674b..3e1b56ed6 100644 --- a/rdflib/term.py +++ b/rdflib/term.py @@ -76,8 +76,6 @@ parse_time, parse_xsd_date, parse_xsd_duration, - parse_xsd_gyear, - parse_xsd_gyearmonth, ) if TYPE_CHECKING: @@ -2065,8 +2063,6 @@ def _castPythonToLiteral( # noqa: N802 None: None, # plain literals map directly to value space URIRef(_XSD_PFX + "time"): parse_time, URIRef(_XSD_PFX + "date"): parse_xsd_date, - URIRef(_XSD_PFX + "gYear"): parse_xsd_gyear, - URIRef(_XSD_PFX + "gYearMonth"): parse_xsd_gyearmonth, URIRef(_XSD_PFX + "dateTime"): parse_datetime, URIRef(_XSD_PFX + "duration"): parse_xsd_duration, URIRef(_XSD_PFX + "dayTimeDuration"): parse_xsd_duration, diff --git a/rdflib/util.py b/rdflib/util.py index ab594b5be..96260fc20 100644 --- a/rdflib/util.py +++ b/rdflib/util.py @@ -74,6 +74,47 @@ _AnyT = TypeVar("_AnyT") +SUFFIX_FORMAT_MAP = { + "xml": "xml", + "rdf": "xml", + "owl": "xml", + "n3": "n3", + "ttl": "turtle", + "nt": "nt", + "trix": "trix", + "xhtml": "rdfa", + "html": "rdfa", + "svg": "rdfa", + "nq": "nquads", + "nquads": "nquads", + "trig": "trig", + "json": "json-ld", + "jsonld": "json-ld", + "json-ld": "json-ld", +} + + +FORMAT_MIMETYPE_MAP = { + "xml": ["application/rdf+xml"], + "n3": ["text/n3"], + "turtle": ["text/turtle"], + "nt": ["application/n-triples"], + "trix": ["application/trix"], + "rdfa": ["text/html", "application/xhtml+xml"], + "nquads": ["application/n-quads"], + "trig": ["application/trig"], + "json-ld": ["application/ld+json"], +} + + +RESPONSE_TABLE_FORMAT_MIMETYPE_MAP = { + "xml": ["application/sparql-results+xml"], + "json": ["application/sparql-results+json"], + "csv": ["text/csv"], + "tsv": ["text/tab-separated-values"], +} + + def list2set(seq: Iterable[_HashableT]) -> List[_HashableT]: """ Return a new list without duplicates. @@ -331,26 +372,6 @@ def parse_date_time(val: str) -> int: return t -SUFFIX_FORMAT_MAP = { - "xml": "xml", - "rdf": "xml", - "owl": "xml", - "n3": "n3", - "ttl": "turtle", - "nt": "nt", - "trix": "trix", - "xhtml": "rdfa", - "html": "rdfa", - "svg": "rdfa", - "nq": "nquads", - "nquads": "nquads", - "trig": "trig", - "json": "json-ld", - "jsonld": "json-ld", - "json-ld": "json-ld", -} - - def guess_format(fpath: str, fmap: Optional[Dict[str, str]] = None) -> Optional[str]: """ Guess RDF serialization based on file suffix. Uses diff --git a/rdflib/xsd_datetime.py b/rdflib/xsd_datetime.py index bc3bebd67..e05dd3c13 100644 --- a/rdflib/xsd_datetime.py +++ b/rdflib/xsd_datetime.py @@ -593,79 +593,6 @@ def parse_xsd_date(date_string: str): return parse_date(date_string if not minus else ("-" + date_string)) -def parse_xsd_gyear(gyear_string: str): - """ - XSD gYear has more features than ISO8601 dates, specifically - XSD allows timezones on a gYear, that must be stripped off. - """ - if gyear_string.endswith("Z") or gyear_string.endswith("z"): - gyear_string = gyear_string[:-1] - if gyear_string.startswith("-"): - gyear_string = gyear_string[1:] - minus = True - else: - minus = False - has_plus = gyear_string.rfind("+") - if has_plus > 0: - # Drop the +07:00 timezone part - gyear_string = gyear_string[:has_plus] - else: - split_parts = gyear_string.rsplit("-", 1) - if len(split_parts) > 1 and ":" in split_parts[-1]: - # Drop the -09:00 timezone part - gyear_string = split_parts[0] - if len(gyear_string) < 4: - raise ValueError("gYear string must be at least 4 numerals in length") - gyear_string = gyear_string.lstrip("0") # strip all leading zeros - try: - y = int(gyear_string if not minus else ("-" + gyear_string)) - except ValueError: - raise ValueError("gYear string must be a valid integer") - return date(y, 1, 1) - - -def parse_xsd_gyearmonth(gym_string: str): - """ - XSD gYearMonth has more features than ISO8601 dates, specifically - XSD allows timezones on a gYearMonth, that must be stripped off. - """ - if gym_string.endswith("Z") or gym_string.endswith("z"): - gym_string = gym_string[:-1] - if gym_string.startswith("-"): - gym_string = gym_string[1:] - minus = True - else: - minus = False - has_plus = gym_string.rfind("+") - if has_plus > 0: - # Drop the +07:00 timezone part - gym_string = gym_string[:has_plus] - else: - split_parts = gym_string.rsplit("-", 1) - if len(split_parts) > 1 and ":" in split_parts[-1]: - # Drop the -09:00 timezone part - gym_string = split_parts[0] - year_month_parts = gym_string.split("-", 1) - if len(year_month_parts) < 2: - raise ValueError("XSD gYearMonth string must contain one dash") - - if len(year_month_parts[0]) < 4: - raise ValueError("gYearMonth Year part must be at least 4 numerals in length") - elif len(year_month_parts[1]) < 2: - raise ValueError("gYearMonth Month part must be exactly 2 numerals in length") - year_string = year_month_parts[0].lstrip("0") # strip all leading zeros - month_string = year_month_parts[1].lstrip("0") # strip all leading zeros - try: - y = int(year_string if not minus else ("-" + year_string)) - except ValueError: - raise ValueError("gYearMonth Year part must be a valid integer") - try: - m = int(month_string) - except ValueError: - raise ValueError("gYearMonth Month part must be a valid integer") - return date(y, m, 1) - - # Parse XSD Datetime is the same as ISO8601 Datetime # It uses datetime.fromisoformat for python 3.11 and above # or isodate.parse_datetime for older versions diff --git a/test/data/longturtle/longturtle-target.ttl b/test/data/longturtle/longturtle-target.ttl new file mode 100644 index 000000000..b9df06e75 --- /dev/null +++ b/test/data/longturtle/longturtle-target.ttl @@ -0,0 +1,74 @@ +PREFIX cn: +PREFIX ex: +PREFIX geo: +PREFIX rdf: +PREFIX sdo: +PREFIX xsd: + +ex:nicholas + a sdo:Person ; + sdo:age 41 ; + sdo:alternateName + [ + sdo:name "Dr N.J. Car" ; + ] , + "N.J. Car" , + "Nick Car" ; + sdo:name + [ + a cn:CompoundName ; + sdo:hasPart + [ + a cn:CompoundName ; + sdo:hasPart + [ + a cn:CompoundName ; + rdf:value "Car" ; + ] , + [ + a cn:CompoundName ; + rdf:value "Maxov" ; + ] ; + ] , + [ + a cn:CompoundName ; + rdf:value "Nicholas" ; + ] , + [ + a cn:CompoundName ; + rdf:value "John" ; + ] ; + ] ; + sdo:worksFor ; +. + + + a sdo:Organization ; + sdo:location ; +. + + + a sdo:Place ; + sdo:address + [ + a sdo:PostalAddress ; + sdo:addressCountry + [ + sdo:identifier "au" ; + sdo:name "Australia" ; + ] ; + sdo:addressLocality "Shorncliffe" ; + sdo:addressRegion "QLD" ; + sdo:postalCode 4017 ; + sdo:streetAddress ( + 72 + "Yundah" + "Street" + ) ; + ] ; + sdo:geo + [ + sdo:polygon "POLYGON((153.082403 -27.325801, 153.08241 -27.32582, 153.082943 -27.325612, 153.083010 -27.325742, 153.083543 -27.325521, 153.083456 -27.325365, 153.082403 -27.325801))"^^geo:wktLiteral ; + ] ; + sdo:name "KurrawongAI HQ" ; +. diff --git a/test/jsonld/local-suite/manifest.jsonld b/test/jsonld/local-suite/manifest.jsonld index b32fd059a..0150b44c7 100644 --- a/test/jsonld/local-suite/manifest.jsonld +++ b/test/jsonld/local-suite/manifest.jsonld @@ -27,6 +27,17 @@ "purpose": "Multiple @id aliases. Issue #2164", "input": "toRdf-twoimports-in.jsonld", "expect": "toRdf-twoimports-out.nq" + }, + { + "@id": "#toRdf-two-invalid-ids", + "@type": ["jld:PositiveEvaluationTest", "jld:ToRDFTest"], + "name": "Two invalid identifiers", + "purpose": "Multiple nodes with invalid @ids are not merged together.", + "option": { + "produceGeneralizedRdf": true + }, + "input": "toRdf-twoinvalidids-in.jsonld", + "expect": "toRdf-twoinvalidids-out.nq" } ] } diff --git a/test/jsonld/local-suite/toRdf-twoinvalidids-in.jsonld b/test/jsonld/local-suite/toRdf-twoinvalidids-in.jsonld new file mode 100644 index 000000000..67f62927c --- /dev/null +++ b/test/jsonld/local-suite/toRdf-twoinvalidids-in.jsonld @@ -0,0 +1,20 @@ +{ + "@id": "https://example.org/root-object", + "https://schema.org/author": [ + { + "@id": "https://example.org/%20invalid%20url%201", + "https://schema.org/name": "Jane Doe" + }, + { + "@id": "https://example.org/%20invalid%20url%201", + "https://schema.org/givenName": "Jane", + "https://schema.org/familyName": "Doe" + }, + { + "@id": "https://example.org/%20invalid%20url%202", + "https://schema.org/name": "John Doe", + "https://schema.org/givenName": "John", + "https://schema.org/familyName": "Doe" + } + ] +} diff --git a/test/jsonld/local-suite/toRdf-twoinvalidids-out.nq b/test/jsonld/local-suite/toRdf-twoinvalidids-out.nq new file mode 100644 index 000000000..c6550560c --- /dev/null +++ b/test/jsonld/local-suite/toRdf-twoinvalidids-out.nq @@ -0,0 +1,10 @@ + + _:b1. + _:b2. + +_:b1 "Jane Doe". +_:b1 "Jane". +_:b1 "Doe". +_:b2 "John Doe". +_:b2 "John". +_:b2 "Doe". diff --git a/test/test_dataset/test_dataset.py b/test/test_dataset/test_dataset.py index 19b9fe830..9f9bc9c26 100644 --- a/test/test_dataset/test_dataset.py +++ b/test/test_dataset/test_dataset.py @@ -5,11 +5,10 @@ import pytest -from rdflib import URIRef, plugin +from rdflib import BNode, Namespace, URIRef, plugin from rdflib.graph import DATASET_DEFAULT_GRAPH_ID, Dataset, Graph from rdflib.store import Store from test.data import CONTEXT1, LIKES, PIZZA, TAREK -from test.utils.namespace import EGSCHEME # Will also run SPARQLUpdateStore tests against local SPARQL1.1 endpoint if # available. This assumes SPARQL1.1 query/update endpoints running locally at @@ -58,9 +57,9 @@ def get_dataset(request): except ImportError: pytest.skip("Dependencies for store '%s' not available!" % store) - graph = Dataset(store=store) + d = Dataset(store=store) - if not graph.store.graph_aware: + if not d.store.graph_aware: return if store in ["SQLiteLSM", "LevelDB"]: @@ -75,31 +74,39 @@ def get_dataset(request): else: path = tempfile.mkdtemp() - graph.open(path, create=True if store != "SPARQLUpdateStore" else False) + d.open(path, create=True if store != "SPARQLUpdateStore" else False) if store == "SPARQLUpdateStore": try: - graph.store.update("CLEAR ALL") + d.graph() + d.add( + ( + URIRef("http://example.com/s"), + URIRef("http://example.com/p"), + URIRef("http://example.com/o"), + ) + ) + d.store.update("CLEAR ALL") except Exception as e: if "SPARQLStore does not support BNodes! " in str(e): pass else: raise Exception(e) - yield store, graph + yield store, d if store == "SPARQLUpdateStore": try: - graph.store.update("CLEAR ALL") + d.update("CLEAR ALL") except Exception as e: if "SPARQLStore does not support BNodes! " in str(e): pass else: raise Exception(e) - graph.close() + d.close() else: - graph.close() - graph.destroy(path) + d.close() + d.destroy(path) if os.path.isdir(path): shutil.rmtree(path) else: @@ -121,7 +128,7 @@ def test_graph_aware(get_dataset): # empty named graphs if store != "SPARQLUpdateStore": # added graph exists - assert set(x.identifier for x in dataset.contexts()) == set( + assert set(x.identifier for x in dataset.graphs()) == set( [CONTEXT1, DATASET_DEFAULT_GRAPH_ID] ) @@ -131,7 +138,7 @@ def test_graph_aware(get_dataset): g1.add((TAREK, LIKES, PIZZA)) # added graph still exists - assert set(x.identifier for x in dataset.contexts()) == set( + assert set(x.identifier for x in dataset.graphs()) == set( [CONTEXT1, DATASET_DEFAULT_GRAPH_ID] ) @@ -147,14 +154,14 @@ def test_graph_aware(get_dataset): # empty named graphs if store != "SPARQLUpdateStore": # graph still exists, although empty - assert set(x.identifier for x in dataset.contexts()) == set( + assert set(x.identifier for x in dataset.graphs()) == set( [CONTEXT1, DATASET_DEFAULT_GRAPH_ID] ) dataset.remove_graph(CONTEXT1) # graph is gone - assert set(x.identifier for x in dataset.contexts()) == set( + assert set(x.identifier for x in dataset.graphs()) == set( [DATASET_DEFAULT_GRAPH_ID] ) @@ -173,7 +180,7 @@ def test_default_graph(get_dataset): dataset.add((TAREK, LIKES, PIZZA)) assert len(dataset) == 1 # only default exists - assert list(dataset.contexts()) == [dataset.default_context] + assert list(dataset.graphs()) == [dataset.default_context] # removing default graph removes triples but not actual graph dataset.remove_graph(DATASET_DEFAULT_GRAPH_ID) @@ -181,7 +188,7 @@ def test_default_graph(get_dataset): assert len(dataset) == 0 # default still exists - assert set(dataset.contexts()) == set([dataset.default_context]) + assert set(dataset.graphs()) == set([dataset.default_context]) def test_not_union(get_dataset): @@ -193,11 +200,11 @@ def test_not_union(get_dataset): "its default graph as the union of the named graphs" ) - subgraph1 = dataset.graph(CONTEXT1) - subgraph1.add((TAREK, LIKES, PIZZA)) + g1 = dataset.graph(CONTEXT1) + g1.add((TAREK, LIKES, PIZZA)) assert list(dataset.objects(TAREK, None)) == [] - assert list(subgraph1.objects(TAREK, None)) == [PIZZA] + assert list(g1.objects(TAREK, None)) == [PIZZA] def test_iter(get_dataset): @@ -208,16 +215,16 @@ def test_iter(get_dataset): uri_c = URIRef("https://example.com/c") uri_d = URIRef("https://example.com/d") - d.graph(URIRef("https://example.com/subgraph1")) - d.add((uri_a, uri_b, uri_c, URIRef("https://example.com/subgraph1"))) + d.graph(URIRef("https://example.com/g1")) + d.add((uri_a, uri_b, uri_c, URIRef("https://example.com/g1"))) d.add( - (uri_a, uri_b, uri_c, URIRef("https://example.com/subgraph1")) + (uri_a, uri_b, uri_c, URIRef("https://example.com/g1")) ) # pointless addition: duplicates above d.graph(URIRef("https://example.com/g2")) d.add((uri_a, uri_b, uri_c, URIRef("https://example.com/g2"))) - d.add((uri_a, uri_b, uri_d, URIRef("https://example.com/subgraph1"))) + d.add((uri_a, uri_b, uri_d, URIRef("https://example.com/g1"))) # traditional iterator i_trad = 0 @@ -232,7 +239,7 @@ def test_iter(get_dataset): assert i_new == i_trad # both should be 3 -def test_subgraph_without_identifier() -> None: +def test_graph_without_identifier() -> None: """ Graphs with no identifies assigned are identified by Skolem IRIs with a prefix that is bound to `genid`. @@ -241,9 +248,9 @@ def test_subgraph_without_identifier() -> None: reviewed at some point. """ - dataset = Dataset() + d = Dataset() - nman = dataset.namespace_manager + nman = d.namespace_manager genid_prefix = URIRef("https://rdflib.github.io/.well-known/genid/rdflib/") @@ -253,15 +260,36 @@ def test_subgraph_without_identifier() -> None: is None ) - subgraph: Graph = dataset.graph() - subgraph.add((EGSCHEME["subject"], EGSCHEME["predicate"], EGSCHEME["object"])) + ex = Namespace("http://example.com/") + g1: Graph = d.graph() + g1.add((ex.subject, ex.predicate, ex.object)) namespaces = set(nman.namespaces()) assert next( (namespace for namespace in namespaces if namespace[0] == "genid"), None ) == ("genid", genid_prefix) - assert f"{subgraph.identifier}".startswith(genid_prefix) + assert f"{g1.identifier}".startswith(genid_prefix) + + # now add a preexisting graph with no identifier + # i.e. not one created within this Dataset object + g2 = Graph() + g2.add((ex.subject, ex.predicate, ex.object)) + d.add_graph(g2) + + iris = 0 + bns = 0 + others = 0 + for g in d.graphs(): + if type(g.identifier) is URIRef: + iris += 1 + elif type(g.identifier) is BNode: + bns += 1 + else: + others += 1 + assert iris == 2 + assert bns == 1 + assert others == 0 def test_not_deprecated(): diff --git a/test/test_dataset/test_dataset_add.py b/test/test_dataset/test_dataset_add.py new file mode 100644 index 000000000..a3197ae2e --- /dev/null +++ b/test/test_dataset/test_dataset_add.py @@ -0,0 +1,101 @@ +from rdflib import RDF, RDFS, Dataset, Graph, URIRef +from test.data import TEST_DATA_DIR + + +def test_behaviour_where_graph_is_created_via_dataset(): + """ + Test that the dataset store state is intact when graphs are created from the dataset. + """ + ds = Dataset(default_union=True) + graph_name = URIRef("urn:graph") + graph = ds.graph(graph_name) + + graph.add((URIRef("urn:class"), RDF.type, RDFS.Class)) + assert len(graph) == 1 + assert len(ds) == 1 + + ds.add_graph(graph) + assert any(g.identifier == graph_name for g in ds.graphs()) + assert len(list(ds.objects(None, None))) == 1 + + retrieved_graph = ds.get_graph(graph_name) + assert retrieved_graph.identifier == graph_name + assert isinstance(retrieved_graph, Graph) + + assert len(retrieved_graph) == 1 + assert len(ds) == 1 + + ds.remove_graph(retrieved_graph) + assert len(retrieved_graph) == 0 + assert len(ds) == 0 + + +def test_behaviour_where_graph_is_created_separately(): + """ + Test that the graphs created externally from the dataset are added to the dataset + store. + """ + ds = Dataset(default_union=True) + graph_name = URIRef("urn:graph") + graph = Graph(identifier=graph_name) + + graph.add((URIRef("urn:class"), RDF.type, RDFS.Class)) + assert len(graph) == 1 + assert len(ds) == 0 + + ds.add_graph(graph) + assert any(g.identifier == graph_name for g in ds.graphs()) + + assert len(list(ds.objects(None, None))) == 1 + + retrieved_graph = ds.get_graph(graph_name) + assert retrieved_graph.identifier == graph_name + assert isinstance(retrieved_graph, Graph) + + assert len(retrieved_graph) == 1 + assert len(ds) == 1 + + ds.remove_graph(retrieved_graph) + assert len(retrieved_graph) == 0 + assert len(ds) == 0 + + +def test_adding_appends_to_dataset_graph(): + """ + Test that external graphs added to the dataset have their triples appended if + the graph identifier already exists. + """ + ds = Dataset(default_union=True) + graph_name = URIRef("urn:graph") + graph = Graph(identifier=graph_name) + + graph.add((URIRef("urn:class"), RDF.type, RDFS.Class)) + assert len(graph) == 1 + assert len(ds) == 0 + + # Make sure to use the returned graph object with the same dataset store. + graph = ds.add_graph(graph) + assert len(ds) == 1 + + graph.add((URIRef("urn:instance"), RDF.type, URIRef("urn:class"))) + assert len(graph) == 2 + assert len(ds) == 2 + + # Another graph, same identifier + another_graph = Graph(identifier=graph_name) + another_graph.add((URIRef("urn:another_instance"), RDF.type, URIRef("urn:class"))) + graph = ds.add_graph(another_graph) + assert len(graph) == 3 + assert len(ds) == 3 + + +def test_dataset_parse_return_value(): + """ + Test that the return value of ds.parse has the same reference as ds. + """ + ds = Dataset() + return_value = ds.parse( + source=TEST_DATA_DIR / "nquads.rdflib/example.nquads", format="nquads" + ) + assert len(ds) + assert return_value is ds diff --git a/test/test_dataset/test_dataset_default_serialize_format.py b/test/test_dataset/test_dataset_default_serialize_format.py new file mode 100644 index 000000000..ba12d0c70 --- /dev/null +++ b/test/test_dataset/test_dataset_default_serialize_format.py @@ -0,0 +1,18 @@ +from rdflib import Dataset +from test.data import TEST_DATA_DIR + + +def test_dataset_default_serialize_format_trig(): + ds = Dataset() + ds.parse(source=TEST_DATA_DIR / "nquads.rdflib" / "test5.nquads", format="nquads") + statements_count = len(ds) + assert statements_count + + # Previously, when the default format is 'turtle', given that the dataset has no + # statements in the default graph, the output of serialize() was empty. + output = ds.serialize().strip() + assert output != "" + + ds2 = Dataset() + ds2.parse(data=output, format="trig") + assert len(ds2) == statements_count diff --git a/test/test_dataset/test_dataset_deprec_notice.py b/test/test_dataset/test_dataset_deprec_notice.py new file mode 100644 index 000000000..068ddd3c2 --- /dev/null +++ b/test/test_dataset/test_dataset_deprec_notice.py @@ -0,0 +1,37 @@ +import pytest + +from rdflib import Dataset + + +def test_dataset_contexts_method(): + ds = Dataset() + with pytest.warns( + DeprecationWarning, + match="Dataset.contexts is deprecated, use Dataset.graphs instead.", + ): + # Call list() to consume the generator to emit the warning. + list(ds.contexts()) + + +def test_dataset_default_context_property(): + ds = Dataset() + with pytest.warns( + DeprecationWarning, + match="Dataset.default_context is deprecated, use Dataset.default_graph instead.", + ): + ds.default_context + + with pytest.warns( + DeprecationWarning, + match="Dataset.default_context is deprecated, use Dataset.default_graph instead.", + ): + ds.default_context = ds.graph() + + +def test_dataset_identifier_property(): + ds = Dataset() + with pytest.warns( + DeprecationWarning, + match="Dataset.identifier is deprecated and will be removed in future versions.", + ): + ds.identifier diff --git a/test/test_examples.py b/test/test_examples.py index 39b967c5c..0454d36ad 100644 --- a/test/test_examples.py +++ b/test/test_examples.py @@ -39,11 +39,7 @@ def test_example(example_file: Path) -> None: try: result.check_returncode() - except subprocess.CalledProcessError: - if ( - example_file.stem == "sparqlstore_example" - and "http.client.RemoteDisconnected: Remote end closed connection without response" - in result.stderr.decode("utf-8") - ): - pytest.skip("this test uses dbpedia which is down sometimes") + except subprocess.CalledProcessError as process_error: + if process_error.returncode == 126: + pytest.skip("This test returned 126 indikating to skip it.") raise diff --git a/test/test_extras/test_shacl_extras.py b/test/test_extras/test_shacl_extras.py index 417e75b68..1144e9b9e 100644 --- a/test/test_extras/test_shacl_extras.py +++ b/test/test_extras/test_shacl_extras.py @@ -4,8 +4,9 @@ import pytest -from rdflib import Graph, URIRef -from rdflib.extras.shacl import SHACLPathError, parse_shacl_path +from rdflib import Graph, Literal, URIRef, paths +from rdflib.compare import graph_diff +from rdflib.extras.shacl import SHACLPathError, build_shacl_path, parse_shacl_path from rdflib.namespace import SH, Namespace from rdflib.paths import Path @@ -109,7 +110,32 @@ def path_source_data(): ) ; ] ; . - ex:TestPropShape10 + ex:TestPropShape10a + sh:path ( + [ + sh:zeroOrMorePath [ + sh:inversePath ex:pred1 ; + ] ; + ] + [ + sh:alternativePath ( + [ + sh:zeroOrMorePath [ + sh:inversePath ex:pred1 ; + ] ; + ] + ex:pred1 + [ + sh:oneOrMorePath ex:pred2 ; + ] + [ + sh:zeroOrMorePath ex:pred3 ; + ] + ) ; + ] + ) ; + . + ex:TestPropShape10b sh:path ( [ sh:zeroOrMorePath [ @@ -192,7 +218,13 @@ def path_source_data(): ~EX.pred1 | EX.pred1 / EX.pred2 | EX.pred1 | EX.pred2 | EX.pred3, ), ( - EX.TestPropShape10, + EX.TestPropShape10a, + ~EX.pred1 + * "*" + / (~EX.pred1 * "*" | EX.pred1 | EX.pred2 * "+" | EX.pred3 * "*"), # type: ignore[operator] + ), + ( + EX.TestPropShape10b, ~EX.pred1 * "*" / (~EX.pred1 * "*" | EX.pred1 | EX.pred2 * "+" | EX.pred3 * "*"), # type: ignore[operator] @@ -216,3 +248,49 @@ def test_parse_shacl_path( parse_shacl_path(path_source_data, path_root) # type: ignore[arg-type] else: assert parse_shacl_path(path_source_data, path_root) == expected # type: ignore[arg-type] + + +@pytest.mark.parametrize( + ("resource", "path"), + ( + # Single SHACL Path + (EX.TestPropShape1, EX.pred1), + (EX.TestPropShape2a, EX.pred1 / EX.pred2 / EX.pred3), + (EX.TestPropShape3, ~EX.pred1), + (EX.TestPropShape4a, EX.pred1 | EX.pred2 | EX.pred3), + (EX.TestPropShape5, EX.pred1 * "*"), # type: ignore[operator] + (EX.TestPropShape6, EX.pred1 * "+"), # type: ignore[operator] + (EX.TestPropShape7, EX.pred1 * "?"), # type: ignore[operator] + # SHACL Path Combinations + (EX.TestPropShape8, ~EX.pred1 * "*"), + ( + EX.TestPropShape10a, + ~EX.pred1 + * "*" + / (~EX.pred1 * "*" | EX.pred1 | EX.pred2 * "+" | EX.pred3 * "*"), # type: ignore[operator] + ), + (TypeError, Literal("Not a valid path")), + (SHACLPathError, paths.SequencePath(SH.targetClass)), + (SHACLPathError, paths.AlternativePath(SH.targetClass)), + ), +) +def test_build_shacl_path( + path_source_data: Graph, resource: URIRef | type, path: Union[URIRef, Path] +): + if isinstance(resource, type): + with pytest.raises(resource): + build_shacl_path(path) + else: + expected_path_root = path_source_data.value(resource, SH.path) + actual_path_root, actual_path_graph = build_shacl_path(path) + if isinstance(expected_path_root, URIRef): + assert actual_path_root == expected_path_root + assert actual_path_graph is None + else: + assert isinstance(actual_path_graph, Graph) + expected_path_graph = path_source_data.cbd(expected_path_root) # type: ignore[arg-type] + in_both, in_first, in_second = graph_diff( + expected_path_graph, actual_path_graph + ) + assert len(in_first) == 0 + assert len(in_second) == 0 diff --git a/test/test_graph/test_aggregate_graphs.py b/test/test_graph/test_aggregate_graphs.py index fd45c4a14..6ede92fda 100644 --- a/test/test_graph/test_aggregate_graphs.py +++ b/test/test_graph/test_aggregate_graphs.py @@ -1,7 +1,7 @@ from io import StringIO -from rdflib import logger, plugin -from rdflib.graph import ConjunctiveGraph, Graph, ReadOnlyGraphAggregate +from rdflib import Dataset, Graph, logger, plugin +from rdflib.graph import ReadOnlyGraphAggregate from rdflib.namespace import RDF, RDFS from rdflib.store import Store from rdflib.term import URIRef @@ -108,10 +108,10 @@ def test_aggregate2(): graph4 = Graph(mem_store, RDFS) graph4.parse(data=TEST_GRAPH_1N3, format="n3") - g = ConjunctiveGraph(mem_store) + g = Dataset(store=mem_store, default_union=True) assert g is not None assert len(list(g.quads((None, None, None, None)))) == 11 - assert len(list(g.contexts())) == 4 + assert len(list(g.contexts())) == 5 logger.debug(list(g.contexts())) assert ( len(list(g.quads((None, None, None, URIRef("http://example.com/graph2"))))) == 4 diff --git a/test/test_graph/test_diff.py b/test/test_graph/test_diff.py index 696d8be89..a1d4f948e 100644 --- a/test/test_graph/test_diff.py +++ b/test/test_graph/test_diff.py @@ -9,7 +9,7 @@ import rdflib from rdflib import Graph from rdflib.compare import graph_diff -from rdflib.graph import ConjunctiveGraph, Dataset +from rdflib.graph import Dataset from rdflib.namespace import FOAF, RDF from rdflib.term import BNode, Literal from test.utils import ( @@ -111,7 +111,7 @@ def as_element_set(self, value: _ElementSetTypeOrStr) -> _ElementSetType: if isinstance(value, str): graph = self.graph_type() graph.parse(data=value, format=self.format) - if isinstance(graph, ConjunctiveGraph): + if isinstance(graph, Dataset): return GraphHelper.quad_set(graph, BNodeHandling.COLLAPSE) else: return GraphHelper.triple_set(graph, BNodeHandling.COLLAPSE) diff --git a/test/test_graph/test_graph.py b/test/test_graph/test_graph.py index 639aa710c..0e8227042 100644 --- a/test/test_graph/test_graph.py +++ b/test/test_graph/test_graph.py @@ -399,7 +399,7 @@ def test_guess_format_for_parse_http_text_plain(): assert len(graph) > 0 # A url that returns content-type text/html. - url = "https://github.com/RDFLib/rdflib/issues/2734" + url = "https://www.w3.org/TR/REC-rdf-syntax/" with pytest.raises(PluginException): graph = Graph().parse(url) diff --git a/test/test_graph/test_graph_context.py b/test/test_graph/test_graph_context.py index 7d0a90f7c..93c5f7d9b 100644 --- a/test/test_graph/test_graph_context.py +++ b/test/test_graph/test_graph_context.py @@ -9,7 +9,7 @@ import pytest -from rdflib import BNode, ConjunctiveGraph, Graph, URIRef, plugin +from rdflib import BNode, Dataset, Graph, URIRef, plugin from rdflib.store import Store @@ -20,7 +20,7 @@ class ContextTestCase(unittest.TestCase): def setUp(self): try: - self.graph = ConjunctiveGraph(store=self.store) + self.graph = Dataset(store=self.store, default_union=True) except ImportError: pytest.skip("Dependencies for store '%s' not available!" % self.store) if self.store == "SQLite": @@ -291,71 +291,66 @@ def test_triples(self): for c in [graph, self.graph.get_context(c1)]: # unbound subjects - asserte(set(c.subjects(likes, pizza)), set((michel, tarek))) - asserte(set(c.subjects(hates, pizza)), set((bob,))) - asserte(set(c.subjects(likes, cheese)), set([tarek, bob, michel])) + asserte(set(c.subjects(likes, pizza)), {michel, tarek}) + asserte(set(c.subjects(hates, pizza)), {bob}) + asserte(set(c.subjects(likes, cheese)), {tarek, bob, michel}) asserte(set(c.subjects(hates, cheese)), set()) # unbound objects - asserte(set(c.objects(michel, likes)), set([cheese, pizza])) - asserte(set(c.objects(tarek, likes)), set([cheese, pizza])) - asserte(set(c.objects(bob, hates)), set([michel, pizza])) - asserte(set(c.objects(bob, likes)), set([cheese])) + asserte(set(c.objects(michel, likes)), {cheese, pizza}) + asserte(set(c.objects(tarek, likes)), {cheese, pizza}) + asserte(set(c.objects(bob, hates)), {michel, pizza}) + asserte(set(c.objects(bob, likes)), {cheese}) # unbound predicates - asserte(set(c.predicates(michel, cheese)), set([likes])) - asserte(set(c.predicates(tarek, cheese)), set([likes])) - asserte(set(c.predicates(bob, pizza)), set([hates])) - asserte(set(c.predicates(bob, michel)), set([hates])) + asserte(set(c.predicates(michel, cheese)), {likes}) + asserte(set(c.predicates(tarek, cheese)), {likes}) + asserte(set(c.predicates(bob, pizza)), {hates}) + asserte(set(c.predicates(bob, michel)), {hates}) - asserte(set(c.subject_objects(hates)), set([(bob, pizza), (bob, michel)])) + asserte(set(c.subject_objects(hates)), {(bob, pizza), (bob, michel)}) asserte( set(c.subject_objects(likes)), - set( - [ - (tarek, cheese), - (michel, cheese), - (michel, pizza), - (bob, cheese), - (tarek, pizza), - ] - ), + { + (tarek, cheese), + (michel, cheese), + (michel, pizza), + (bob, cheese), + (tarek, pizza), + }, ) - asserte( - set(c.predicate_objects(michel)), set([(likes, cheese), (likes, pizza)]) - ) + asserte(set(c.predicate_objects(michel)), {(likes, cheese), (likes, pizza)}) asserte( set(c.predicate_objects(bob)), - set([(likes, cheese), (hates, pizza), (hates, michel)]), - ) - asserte( - set(c.predicate_objects(tarek)), set([(likes, cheese), (likes, pizza)]) + {(likes, cheese), (hates, pizza), (hates, michel)}, ) + asserte(set(c.predicate_objects(tarek)), {(likes, cheese), (likes, pizza)}) asserte( set(c.subject_predicates(pizza)), - set([(bob, hates), (tarek, likes), (michel, likes)]), + {(bob, hates), (tarek, likes), (michel, likes)}, ) asserte( set(c.subject_predicates(cheese)), - set([(bob, likes), (tarek, likes), (michel, likes)]), + {(bob, likes), (tarek, likes), (michel, likes)}, ) - asserte(set(c.subject_predicates(michel)), set([(bob, hates)])) + asserte(set(c.subject_predicates(michel)), {(bob, hates)}) + d = set() + for x in c: + d.add(x[0:3]) asserte( - set(c), - set( - [ - (bob, hates, michel), - (bob, likes, cheese), - (tarek, likes, pizza), - (michel, likes, pizza), - (michel, likes, cheese), - (bob, hates, pizza), - (tarek, likes, cheese), - ] - ), + set(d), + { + (bob, hates, michel), + (bob, likes, cheese), + (tarek, likes, pizza), + (michel, likes, pizza), + (michel, likes, cheese), + (bob, hates, pizza), + (tarek, likes, cheese), + }, ) # remove stuff and make sure the graph is empty again diff --git a/test/test_graph/test_graph_formula.py b/test/test_graph/test_graph_formula.py index 0f77dc294..eebc8385a 100644 --- a/test/test_graph/test_graph_formula.py +++ b/test/test_graph/test_graph_formula.py @@ -4,7 +4,7 @@ import pytest from rdflib import RDF, RDFS, BNode, URIRef, Variable, plugin -from rdflib.graph import ConjunctiveGraph, QuotedGraph +from rdflib.graph import Dataset, QuotedGraph implies = URIRef("http://www.w3.org/2000/10/swap/log#implies") testN3 = """ @@ -21,7 +21,7 @@ def checkFormulaStore(store="default", configString=None): # noqa: N802, N803 try: - g = ConjunctiveGraph(store=store) + g = Dataset(store=store) except ImportError: pytest.skip("Dependencies for store '%s' not available!" % store) @@ -48,7 +48,7 @@ def checkFormulaStore(store="default", configString=None): # noqa: N802, N803 d = URIRef("http://test/d") v = Variable("y") - universe = ConjunctiveGraph(g.store) + universe = Dataset(g.store) # test formula as terms assert len(list(universe.triples((formulaA, implies, formulaB)))) == 1 diff --git a/test/test_graph/test_graph_generators.py b/test/test_graph/test_graph_generators.py index 0d89c9b7f..bec7ccb4c 100644 --- a/test/test_graph/test_graph_generators.py +++ b/test/test_graph/test_graph_generators.py @@ -75,3 +75,19 @@ def test_parse_berners_lee_card_into_graph(): assert len(list(graph.subjects(unique=True))) == no_of_unique_subjects assert len(list(graph.predicates(unique=True))) == no_of_unique_predicates assert len(list(graph.objects(unique=True))) == no_of_unique_objects + + +def test_subjects_multi(): + graph = Graph() + add_stuff(graph) + assert len([subj for subj in graph.subjects(LIKES, [CHEESE, PIZZA])]) == 5 + assert len([subj for subj in graph.subjects(LIKES, [])]) == 0 + assert len([subj for subj in graph.subjects(LIKES | HATES, [CHEESE, PIZZA])]) == 6 + + +def test_objects_multi(): + graph = Graph() + add_stuff(graph) + assert len([obj for obj in graph.objects([TAREK, BOB], LIKES)]) == 6 + assert len([obj for obj in graph.objects([], LIKES)]) == 0 + assert len([obj for obj in graph.objects([TAREK, BOB], LIKES | HATES)]) == 8 diff --git a/test/test_graph/test_namespace_rebinding.py b/test/test_graph/test_namespace_rebinding.py index babac1b4f..253fbedc2 100644 --- a/test/test_graph/test_namespace_rebinding.py +++ b/test/test_graph/test_namespace_rebinding.py @@ -1,6 +1,6 @@ import pytest -from rdflib import ConjunctiveGraph, Graph, Literal +from rdflib import Dataset, Graph, Literal from rdflib.namespace import OWL, Namespace, NamespaceManager from rdflib.plugins.stores.memory import Memory from rdflib.term import URIRef @@ -292,12 +292,11 @@ def test_multigraph_bindings(): assert list(g1.namespaces()) == [("friend-of-a-friend", foaf1_uri)] # Including newly-created objects that use the store - cg = ConjunctiveGraph(store=store) + cg = Dataset(store=store, default_union=True) cg.namespace_manager = NamespaceManager(cg, bind_namespaces="core") assert ("foaf", foaf1_uri) not in list(cg.namespaces()) assert ("friend-of-a-friend", foaf1_uri) in list(cg.namespaces()) - assert len(list(g1.namespaces())) == 6 assert len(list(g2.namespaces())) == 6 assert len(list(cg.namespaces())) == 6 diff --git a/test/test_issues/test_issue3126.py b/test/test_issues/test_issue3126.py new file mode 100644 index 000000000..321ff7d3e --- /dev/null +++ b/test/test_issues/test_issue3126.py @@ -0,0 +1,21 @@ +import pytest + +from rdflib import Graph + + +def test_skolem_de_skolem_roundtrip(): + """Test deskolemization should ignore literals. + + Issue: https://github.com/RDFLib/rdflib/issues/3126 + """ + + nt = ( + ' "http://example.com [some remark]" .' + ) + + graph = Graph().parse(data=nt, format="nt").de_skolemize() + + try: + graph.de_skolemize() + except BaseException as ex: + pytest.fail(f"Unexpected error: {ex}") diff --git a/test/test_issues/test_issue535.py b/test/test_issues/test_issue535.py index 03f75d601..80a639694 100644 --- a/test/test_issues/test_issue535.py +++ b/test/test_issues/test_issue535.py @@ -1,8 +1,8 @@ -from rdflib import ConjunctiveGraph, URIRef +from rdflib import Dataset, URIRef def test_nquads_default_graph(): - ds = ConjunctiveGraph() + ds = Dataset(default_union=True) data = """ . diff --git a/test/test_literal/test_literal.py b/test/test_literal/test_literal.py index a28e67e12..7e31fb040 100644 --- a/test/test_literal/test_literal.py +++ b/test/test_literal/test_literal.py @@ -848,21 +848,22 @@ def unlexify(s: str) -> str: ("0000-00-00", XSD.date, None), ("NOT A VALID HEX STRING", XSD.hexBinary, None), ("NOT A VALID BASE64 STRING", XSD.base64Binary, None), + # xsd:gYear and xsd:gYearMonth also do not get converted + ("1921-05", XSD.gYearMonth, None), + ("0001-01", XSD.gYearMonth, None), + ("0001-12", XSD.gYearMonth, None), + ("2002-01", XSD.gYearMonth, None), + ("9999-01", XSD.gYearMonth, None), + ("9999-12", XSD.gYearMonth, None), + ("1921", XSD.gYear, None), + ("2000", XSD.gYear, None), + ("0001", XSD.gYear, None), + ("9999", XSD.gYear, None), + ("1982", XSD.gYear, None), + ("2002", XSD.gYear, None), # these literals get converted to python types ("1921-05-01", XSD.date, datetime.date), ("1921-05-01T00:00:00", XSD.dateTime, datetime.datetime), - ("1921-05", XSD.gYearMonth, datetime.date), - ("0001-01", XSD.gYearMonth, datetime.date), - ("0001-12", XSD.gYearMonth, datetime.date), - ("2002-01", XSD.gYearMonth, datetime.date), - ("9999-01", XSD.gYearMonth, datetime.date), - ("9999-12", XSD.gYearMonth, datetime.date), - ("1921", XSD.gYear, datetime.date), - ("2000", XSD.gYear, datetime.date), - ("0001", XSD.gYear, datetime.date), - ("9999", XSD.gYear, datetime.date), - ("1982", XSD.gYear, datetime.date), - ("2002", XSD.gYear, datetime.date), ("1921-05-01T00:00:00+00:30", XSD.dateTime, datetime.datetime), ("1921-05-01T00:00:00-00:30", XSD.dateTime, datetime.datetime), ("true", XSD.boolean, bool), diff --git a/test/test_n3.py b/test/test_n3.py index f3d7eeb07..40f871868 100644 --- a/test/test_n3.py +++ b/test/test_n3.py @@ -4,7 +4,7 @@ import pytest -from rdflib.graph import ConjunctiveGraph, Graph +from rdflib.graph import Dataset, Graph from rdflib.plugins.parsers.notation3 import BadSyntax, exponent_syntax from rdflib.term import Literal, URIRef from test import TEST_DIR @@ -44,7 +44,7 @@ n3:predicate :p; n3:object :y ] a log:Truth}. -# Needs more thought ... ideally, we have the implcit AND rules of +# Needs more thought ... ideally, we have the implicit AND rules of # juxtaposition (introduction and elimination) { @@ -125,9 +125,9 @@ def test_base_serialize(self): ) s = g.serialize(base="http://example.com/", format="n3", encoding="latin-1") assert b"" in s - g2 = ConjunctiveGraph() - g2.parse(data=s, publicID="http://example.com/", format="n3") - assert list(g) == list(g2) + g2 = Dataset() + g2.parse(data=s, format="n3") + assert list(g) == list(g2.triples((None, None, None))) def test_issue23(self): input = """ "this word is in \\u201Cquotes\\u201D".""" @@ -195,24 +195,24 @@ def test_dot_in_prefix(self): ) def test_model(self): - g = ConjunctiveGraph() + g = Dataset() g.parse(data=test_data, format="n3") i = 0 - for s, p, o in g: + for s, p, o, c in g: if isinstance(s, Graph): i += 1 assert i == 3 - assert len(list(g.contexts())) == 13 + assert len(list(g.graphs())) == 13 g.close() def test_quoted_serialization(self): - g = ConjunctiveGraph() + g = Dataset() g.parse(data=test_data, format="n3") g.serialize(format="n3") def test_parse(self): - g = ConjunctiveGraph() + g = Dataset() try: g.parse( "http://groups.csail.mit.edu/dig/2005/09/rein/examples/troop42-policy.n3", @@ -229,14 +229,14 @@ def test_single_quoted_literals(self): for data in test_data: # N3 doesn't accept single quotes around string literals - g = ConjunctiveGraph() + g = Dataset() with pytest.raises(BadSyntax): g.parse(data=data, format="n3") - g = ConjunctiveGraph() + g = Dataset() g.parse(data=data, format="turtle") assert len(g) == 1 - for _, _, o in g: + for _, _, o, c in g: assert o == Literal("o") def test_empty_prefix(self): @@ -251,6 +251,23 @@ def test_empty_prefix(self): g2 ), "Document with declared empty prefix must match default #" + @pytest.mark.parametrize( + "do_normalize_literal, expected_result", + [(True, {"1.0", "10000000000.0"}), (False, {"1e10", "1e0"})], + ) + def test_float_no_norm(self, do_normalize_literal, expected_result): + import rdflib + + original_normalize_literal = rdflib.NORMALIZE_LITERALS + try: + rdflib.NORMALIZE_LITERALS = do_normalize_literal + g1 = Graph() + g1.parse(data=":a :b 1e10, 1e0 .", format="n3") + values = set(str(o) for o in g1.objects()) + assert values == expected_result + finally: + rdflib.NORMALIZE_LITERALS = original_normalize_literal + class TestRegularExpressions: def test_exponents(self): diff --git a/test/test_namespace/test_definednamespace.py b/test/test_namespace/test_definednamespace.py index ea8e12969..5860e8eb2 100644 --- a/test/test_namespace/test_definednamespace.py +++ b/test/test_namespace/test_definednamespace.py @@ -299,14 +299,9 @@ def test_repr(dfns: Type[DefinedNamespace]) -> None: ns_uri = f"{prefix}{dfns_info.suffix}" logging.debug("ns_uri = %s", ns_uri) - repr_str: Optional[str] = None - - with ExitStack() as xstack: - if dfns_info.suffix is None: - xstack.enter_context(pytest.raises(AttributeError)) - repr_str = f"{dfns_info.dfns!r}" + repr_str: str = f"{dfns_info.dfns!r}" if dfns_info.suffix is None: - assert repr_str is None + assert "" in repr_str else: assert repr_str is not None repro = eval(repr_str) @@ -368,20 +363,15 @@ def test_contains( dfns_info = get_dfns_info(dfns) if dfns_info.suffix is not None: logging.debug("dfns_info = %s", dfns_info) - if dfns_info.has_attrs is False: + if dfns_info.has_attrs is False or dfns_info.suffix is None: is_defined = False - does_contain: Optional[bool] = None - with ExitStack() as xstack: - if dfns_info.suffix is None: - xstack.enter_context(pytest.raises(AttributeError)) - does_contain = attr_name in dfns - if dfns_info.suffix is not None: - if is_defined: - assert does_contain is True - else: - assert does_contain is False + + does_contain: bool = attr_name in dfns + + if is_defined: + assert does_contain is True else: - assert does_contain is None + assert does_contain is False @pytest.mark.parametrize( diff --git a/test/test_namespace/test_namespace.py b/test/test_namespace/test_namespace.py index 409d703f3..60d687424 100644 --- a/test/test_namespace/test_namespace.py +++ b/test/test_namespace/test_namespace.py @@ -232,7 +232,7 @@ def add_not_in_namespace(s): # a property name within the FOAF namespace assert FOAF.givenName == URIRef("http://xmlns.com/foaf/0.1/givenName") - # namescape can be used as str + # namespace can be used as str assert FOAF.givenName.startswith(FOAF) def test_contains_method(self): diff --git a/test/test_parsers/test_broken_parse_data_from_jena.py b/test/test_parsers/test_broken_parse_data_from_jena.py index 353593837..da25154a7 100644 --- a/test/test_parsers/test_broken_parse_data_from_jena.py +++ b/test/test_parsers/test_broken_parse_data_from_jena.py @@ -33,6 +33,6 @@ def xfail_broken_parse_data(request): @pytest.mark.parametrize("testfile", os.listdir(broken_parse_data)) @pytest.mark.usefixtures("xfail_broken_parse_data") def test_n3_serializer_roundtrip(testfile) -> None: - g1 = rdflib.ConjunctiveGraph() + g1 = rdflib.Dataset(default_union=True) g1.parse(os.path.join(broken_parse_data, testfile), format="n3") diff --git a/test/test_parsers/test_empty_xml_base.py b/test/test_parsers/test_empty_xml_base.py index 0f3f18694..0225c4c63 100644 --- a/test/test_parsers/test_empty_xml_base.py +++ b/test/test_parsers/test_empty_xml_base.py @@ -5,7 +5,7 @@ and RDF/XML dependence on it """ -from rdflib.graph import ConjunctiveGraph +from rdflib.graph import Dataset from rdflib.namespace import FOAF, RDF from rdflib.term import URIRef @@ -36,7 +36,7 @@ class TestEmptyBase: def test_empty_base_ref(self): - self.graph = ConjunctiveGraph() + self.graph = Dataset() self.graph.parse(data=test_data, publicID=baseUri, format="xml") assert ( len(list(self.graph)) > 0 @@ -50,7 +50,7 @@ def test_empty_base_ref(self): class TestRelativeBase: def test_relative_base_ref(self): - self.graph = ConjunctiveGraph() + self.graph = Dataset() self.graph.parse(data=test_data2, publicID=baseUri2, format="xml") assert ( len(self.graph) > 0 diff --git a/test/test_parsers/test_nquads.py b/test/test_parsers/test_nquads.py index ad17b5aee..ee14856ab 100644 --- a/test/test_parsers/test_nquads.py +++ b/test/test_parsers/test_nquads.py @@ -1,6 +1,7 @@ import os -from rdflib import ConjunctiveGraph, Namespace, URIRef +from rdflib import Dataset, Literal, URIRef +from rdflib.namespace import FOAF from test.data import TEST_DATA_DIR TEST_BASE = os.path.join(TEST_DATA_DIR, "nquads.rdflib") @@ -8,7 +9,7 @@ class TestNQuadsParser: def _load_example(self): - g = ConjunctiveGraph() + g = Dataset() nq_path = os.path.relpath( os.path.join(TEST_DATA_DIR, "nquads.rdflib/example.nquads"), os.curdir ) @@ -21,9 +22,9 @@ def test_01_simple_open(self): assert len(g.store) == 449 def test_02_contexts(self): - # There should be 16 separate contexts + # There should be 17 separate contexts - 16 Named + default g = self._load_example() - assert len([x for x in g.store.contexts()]) == 16 + assert len([x for x in g.store.contexts()]) == 17 def test_03_get_value(self): # is the name of entity E10009 "Arco Publications"? @@ -36,11 +37,11 @@ def test_03_get_value(self): g = self._load_example() s = URIRef("http://bibliographica.org/entity/E10009") - FOAF = Namespace("http://xmlns.com/foaf/0.1/") # noqa: N806 - assert g.value(s, FOAF.name).eq("Arco Publications") + for s, p, o, c in list(g.quads((s, FOAF.name, None, None))): + assert o == Literal("Arco Publications") def test_context_is_optional(self): - g = ConjunctiveGraph() + g = Dataset() nq_path = os.path.relpath( os.path.join(TEST_DATA_DIR, "nquads.rdflib/test6.nq"), os.curdir ) @@ -49,7 +50,7 @@ def test_context_is_optional(self): assert len(g) > 0 def test_serialize(self): - g = ConjunctiveGraph() + g = Dataset() uri1 = URIRef("http://example.org/mygraph1") uri2 = URIRef("http://example.org/mygraph2") @@ -63,7 +64,7 @@ def test_serialize(self): s = g.serialize(format="nquads", encoding="utf-8") assert len([x for x in s.split(b"\n") if x.strip()]) == 2 - g2 = ConjunctiveGraph() + g2 = Dataset() g2.parse(data=s, format="nquads") assert len(g) == len(g2) @@ -89,8 +90,8 @@ def teardown_method(self, method): def test_parse_shared_bnode_context(self): bnode_ctx = dict() - g = ConjunctiveGraph() - h = ConjunctiveGraph() + g = Dataset() + h = Dataset() g.parse(self.data, format="nquads", bnode_context=bnode_ctx) self.data.seek(0) h.parse(self.data, format="nquads", bnode_context=bnode_ctx) @@ -98,7 +99,7 @@ def test_parse_shared_bnode_context(self): def test_parse_shared_bnode_context_same_graph(self): bnode_ctx = dict() - g = ConjunctiveGraph() + g = Dataset() g.parse(self.data_obnodes, format="nquads", bnode_context=bnode_ctx) o1 = set(g.objects()) self.data_obnodes.seek(0) @@ -107,27 +108,27 @@ def test_parse_shared_bnode_context_same_graph(self): assert o1 == o2 def test_parse_distinct_bnode_context(self): - g = ConjunctiveGraph() + g = Dataset() g.parse(self.data, format="nquads", bnode_context=dict()) - s1 = set(g.subjects()) + s1 = set([x for x, p, o, c in list(g.quads((None, None, None, None)))]) self.data.seek(0) g.parse(self.data, format="nquads", bnode_context=dict()) - s2 = set(g.subjects()) + s2 = set([x for x, p, o, c in list(g.quads((None, None, None, None)))]) assert set() != (s2 - s1) def test_parse_distinct_bnode_contexts_between_graphs(self): - g = ConjunctiveGraph() - h = ConjunctiveGraph() + g = Dataset() + h = Dataset() g.parse(self.data, format="nquads") - s1 = set(g.subjects()) + s1 = sorted(set([x for x, p, o, c in list(g.quads((None, None, None, None)))])) self.data.seek(0) h.parse(self.data, format="nquads") - s2 = set(h.subjects()) + s2 = sorted(set([x for x, p, o, c in list(h.quads((None, None, None, None)))])) assert s1 != s2 def test_parse_distinct_bnode_contexts_named_graphs(self): - g = ConjunctiveGraph() - h = ConjunctiveGraph() + g = Dataset() + h = Dataset() g.parse(self.data, format="nquads") self.data.seek(0) h.parse(self.data, format="nquads") @@ -135,9 +136,17 @@ def test_parse_distinct_bnode_contexts_named_graphs(self): def test_parse_shared_bnode_contexts_named_graphs(self): bnode_ctx = dict() - g = ConjunctiveGraph() - h = ConjunctiveGraph() - g.parse(self.data, format="nquads", bnode_context=bnode_ctx) + g = Dataset() + h = Dataset() + g.parse( + TEST_DATA_DIR / "nquads.rdflib/bnode_context.nquads", + format="nquads", + bnode_context=bnode_ctx, + ) self.data.seek(0) - h.parse(self.data, format="nquads", bnode_context=bnode_ctx) + h.parse( + TEST_DATA_DIR / "nquads.rdflib/bnode_context.nquads", + format="nquads", + bnode_context=bnode_ctx, + ) assert set(h.contexts()) == set(g.contexts()) diff --git a/test/test_parsers/test_parser_hext.py b/test/test_parsers/test_parser_hext.py index c71bd1a49..17d19fa26 100644 --- a/test/test_parsers/test_parser_hext.py +++ b/test/test_parsers/test_parser_hext.py @@ -1,6 +1,6 @@ from pathlib import Path -from rdflib import BNode, ConjunctiveGraph, Dataset, Literal, URIRef +from rdflib import BNode, Dataset, Literal, URIRef from rdflib.compare import isomorphic from rdflib.graph import DATASET_DEFAULT_GRAPH_ID from rdflib.namespace import XSD @@ -97,7 +97,7 @@ def test_small_string_cg(): ["http://example.com/s01", "http://example.com/op1", "http://example.com/o2", "globalId", "", ""] ["http://example.com/s01", "http://example.com/op2", "http://example.com/o3", "globalId", "", ""] """ - d = ConjunctiveGraph(identifier=DATASET_DEFAULT_GRAPH_ID) + d = Dataset() d.parse(data=s, format="hext") expected_graph_names = ( @@ -140,7 +140,7 @@ def test_small_file_multigraph(): def test_small_file_multigraph_cg(): - d = ConjunctiveGraph() + d = Dataset() assert len(d) == 0 d.parse( Path(__file__).parent.parent / "data/test_parser_hext_multigraph.ndjson", @@ -185,14 +185,14 @@ def test_roundtrip(): print(f"Test {tests}: {f}") if f.name not in files_to_skip.keys(): try: - cg = ConjunctiveGraph().parse(f, format="nt") + cg = Dataset().parse(f, format="nt") # print(cg.serialize(format="n3")) except Exception: print("Skipping: could not NT parse") skipped += 1 skip = True if not skip: - cg2 = ConjunctiveGraph() + cg2 = Dataset() cg2.parse( data=cg.serialize(format="hext"), format="hext", diff --git a/test/test_parsers/test_trix_parse.py b/test/test_parsers/test_trix_parse.py index e6f2ae91b..e48cf9b07 100644 --- a/test/test_parsers/test_trix_parse.py +++ b/test/test_parsers/test_trix_parse.py @@ -1,6 +1,6 @@ import os -from rdflib.graph import ConjunctiveGraph +from rdflib.graph import Dataset from test.data import TEST_DATA_DIR @@ -12,7 +12,7 @@ def teardown_method(self): pass def testAperture(self): # noqa: N802 - g = ConjunctiveGraph() + g = Dataset() trix_path = os.path.relpath( os.path.join(TEST_DATA_DIR, "suites", "trix/trix-aperture.trix"), os.curdir @@ -24,12 +24,12 @@ def testAperture(self): # noqa: N802 t = sum(map(len, g.contexts())) assert t == 24 - assert len(c) == 4 + assert len(c) == 5 # print "Parsed %d triples"%t def testSpec(self): # noqa: N802 - g = ConjunctiveGraph() + g = Dataset() trix_path = os.path.relpath( os.path.join(TEST_DATA_DIR, "suites", "trix/trix-nokia-example.trix"), @@ -40,7 +40,7 @@ def testSpec(self): # noqa: N802 # print "Parsed %d triples"%len(g) def testNG4j(self): # noqa: N802 - g = ConjunctiveGraph() + g = Dataset() trix_path = os.path.relpath( os.path.join(TEST_DATA_DIR, "suites", "trix/trix-ng4j-test-01.trix"), diff --git a/test/test_serializers/test_nquads_default_graph.py b/test/test_serializers/test_nquads_default_graph.py new file mode 100644 index 000000000..c1699d235 --- /dev/null +++ b/test/test_serializers/test_nquads_default_graph.py @@ -0,0 +1,39 @@ +from rdflib import Dataset +from rdflib.compare import isomorphic + + +def test_nquads_default_graph(): + data = """ + @prefix rdf: . + @prefix rdfs: . + @prefix xsd: . + + { + "2012-04-09"^^xsd:date . + } + + { + a ; + "http://manu.sporny.org/about#manu" ; + "Gregg Kellogg" . + + a ; + "http://greggkellogg.net/foaf#me" ; + "Manu Sporny" . + } + """ + + ds = Dataset() + ds.parse(data=data, format="trig") + output = ds.serialize(format="nquads") + + # The internal RDFLib default graph identifier should not appear in the output. + assert "" not in output + + # Ensure dataset round-trip still works. + ds2 = Dataset() + ds2.parse(data=output, format="nquads") + for graph in ds.graphs(): + assert isomorphic(graph, ds2.graph(graph.identifier)), print( + f"{graph.identifier} not isomorphic" + ) diff --git a/test/test_serializers/test_prettyxml.py b/test/test_serializers/test_prettyxml.py index 6c798e825..aac19af50 100644 --- a/test/test_serializers/test_prettyxml.py +++ b/test/test_serializers/test_prettyxml.py @@ -1,6 +1,6 @@ from io import BytesIO -from rdflib.graph import ConjunctiveGraph +from rdflib.graph import Dataset from rdflib.namespace import RDF, RDFS from rdflib.plugins.serializers.rdfxml import PrettyXMLSerializer from rdflib.term import BNode, Literal, URIRef @@ -10,7 +10,7 @@ class SerializerTestBase: repeats = 8 def setup_method(self): - graph = ConjunctiveGraph() + graph = Dataset() graph.parse(data=self.test_content, format=self.test_content_format) self.source_graph = graph @@ -41,12 +41,12 @@ def _assert_equal_graphs(g1, g2): def _mangled_copy(g): "Makes a copy of the graph, replacing all bnodes with the bnode ``_blank``." - gcopy = ConjunctiveGraph() + gcopy = Dataset() def isbnode(v): return isinstance(v, BNode) - for s, p, o in g: + for s, p, o, c in g: if isbnode(s): s = _blank if isbnode(p): @@ -67,7 +67,7 @@ def serialize(source_graph, make_serializer, get_value=True, extra_args={}): def serialize_and_load(source_graph, make_serializer): stream = serialize(source_graph, make_serializer, False) stream.seek(0) - reparsed_graph = ConjunctiveGraph() + reparsed_graph = Dataset() reparsed_graph.parse(stream, format="xml") return reparsed_graph @@ -170,7 +170,7 @@ def test_subclass_of_objects(self): def test_pretty_xmlliteral(self): # given: - g = ConjunctiveGraph() + g = Dataset() g.add( ( BNode(), @@ -191,7 +191,7 @@ def test_pretty_xmlliteral(self): def test_pretty_broken_xmlliteral(self): # given: - g = ConjunctiveGraph() + g = Dataset() g.add((BNode(), RDF.value, Literal("""

None: NS = Namespace("example:") # noqa: N806 - graph = ConjunctiveGraph() + graph = Dataset(default_union=True) graph.bind("eg", NS) nodes = [NS.subj, NS.pred, NS.obj, NS.graph] nodes[tuple_index] = RDF.type @@ -68,7 +68,7 @@ def test_rdf_type(format: str, tuple_index: int, is_keyword: bool) -> None: assert str(RDF) not in data else: assert str(RDF) in data - parsed_graph = ConjunctiveGraph() + parsed_graph = Dataset(default_union=True) parsed_graph.parse(data=data, format=format) GraphHelper.assert_triple_sets_equals(graph, parsed_graph) diff --git a/test/test_serializers/test_serializer_hext.py b/test/test_serializers/test_serializer_hext.py index 2b0577bc1..de39e37dc 100644 --- a/test/test_serializers/test_serializer_hext.py +++ b/test/test_serializers/test_serializer_hext.py @@ -1,7 +1,7 @@ import json from pathlib import Path -from rdflib import ConjunctiveGraph, Dataset, Graph +from rdflib import Dataset, Graph def test_hext_graph(): @@ -90,7 +90,7 @@ def test_hext_graph(): def test_hext_cg(): """Tests ConjunctiveGraph data""" - d = ConjunctiveGraph() + d = Dataset() trig_data = """ PREFIX ex: PREFIX owl: diff --git a/test/test_serializers/test_serializer_longturtle.py b/test/test_serializers/test_serializer_longturtle.py index 847d506ab..65821784e 100644 --- a/test/test_serializers/test_serializer_longturtle.py +++ b/test/test_serializers/test_serializer_longturtle.py @@ -1,5 +1,5 @@ import difflib -from textwrap import dedent +from pathlib import Path from rdflib import Graph, Namespace from rdflib.namespace import GEO, SDO @@ -167,86 +167,14 @@ def test_longturtle(): g.bind("sdo", SDO) # run the long turtle serializer - output = g.serialize(format="longturtle") + output = g.serialize(format="longturtle", canon=True) # fix the target - target = dedent( - """ PREFIX cn: - PREFIX ex: - PREFIX geo: - PREFIX rdf: - PREFIX sdo: - PREFIX xsd: + current_dir = Path.cwd() # Get the current directory + target_file_path = current_dir / "test/data/longturtle" / "longturtle-target.ttl" - ex:nicholas - a sdo:Person ; - sdo:age 41 ; - sdo:alternateName - [ - sdo:name "Dr N.J. Car" ; - ] , - "N.J. Car" , - "Nick Car" ; - sdo:name - [ - a cn:CompoundName ; - sdo:hasPart - [ - a cn:CompoundName ; - rdf:value "Nicholas" ; - ] , - [ - a cn:CompoundName ; - rdf:value "John" ; - ] , - [ - a cn:CompoundName ; - sdo:hasPart - [ - a cn:CompoundName ; - rdf:value "Car" ; - ] , - [ - a cn:CompoundName ; - rdf:value "Maxov" ; - ] ; - ] ; - ] ; - sdo:worksFor ; - . - - - a sdo:Organization ; - sdo:location ; - . - - - a sdo:Place ; - sdo:address - [ - a sdo:PostalAddress ; - sdo:addressCountry - [ - sdo:identifier "au" ; - sdo:name "Australia" ; - ] ; - sdo:addressLocality "Shorncliffe" ; - sdo:addressRegion "QLD" ; - sdo:postalCode 4017 ; - sdo:streetAddress ( - 72 - "Yundah" - "Street" - ) ; - ] ; - sdo:geo - [ - sdo:polygon "POLYGON((153.082403 -27.325801, 153.08241 -27.32582, 153.082943 -27.325612, 153.083010 -27.325742, 153.083543 -27.325521, 153.083456 -27.325365, 153.082403 -27.325801))"^^geo:wktLiteral ; - ] ; - sdo:name "KurrawongAI HQ" ; - . - """ - ) + with open(target_file_path, encoding="utf-8") as file: + target = file.read() # compare output to target # - any differences will produce output diff --git a/test/test_serializers/test_serializer_longturtle_sort.py b/test/test_serializers/test_serializer_longturtle_sort.py new file mode 100644 index 000000000..044660e3e --- /dev/null +++ b/test/test_serializers/test_serializer_longturtle_sort.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 + +# Portions of this file contributed by NIST are governed by the +# following statement: +# +# This software was developed at the National Institute of Standards +# and Technology by employees of the Federal Government in the course +# of their official duties. Pursuant to Title 17 Section 105 of the +# United States Code, this software is not subject to copyright +# protection within the United States. NIST assumes no responsibility +# whatsoever for its use by other parties, and makes no guarantees, +# expressed or implied, about its quality, reliability, or any other +# characteristic. +# +# We would appreciate acknowledgement if the software is used. + +from __future__ import annotations + +import random +from collections import defaultdict +from typing import DefaultDict, List + +from rdflib import RDFS, BNode, Graph, Literal, Namespace, URIRef + +EX = Namespace("http://example.org/ex/") + + +def test_sort_semiblank_graph() -> None: + """ + This test reviews whether the output of the Turtle form is + consistent when involving repeated generates with blank nodes. + """ + + serialization_counter: DefaultDict[str, int] = defaultdict(int) + + first_graph_text: str = "" + + # Use a fixed sequence of once-but-no-longer random values for more + # consistent test results. + nonrandom_shuffler = random.Random(1234) + for x in range(1, 10): + graph = Graph() + graph.bind("ex", EX) + graph.bind("rdfs", RDFS) + + graph.add((EX.A, RDFS.comment, Literal("Thing A"))) + graph.add((EX.B, RDFS.comment, Literal("Thing B"))) + graph.add((EX.C, RDFS.comment, Literal("Thing C"))) + + nodes: List[URIRef] = [EX.A, EX.B, EX.C, EX.B] + nonrandom_shuffler.shuffle(nodes) + for node in nodes: + # Instantiate one bnode per URIRef node. + graph.add((BNode(), RDFS.seeAlso, node)) + + nesteds: List[URIRef] = [EX.A, EX.B, EX.C] + nonrandom_shuffler.shuffle(nesteds) + for nested in nesteds: + # Instantiate a nested node reference. + outer_node = BNode() + inner_node = BNode() + graph.add((outer_node, EX.has, inner_node)) + graph.add((inner_node, RDFS.seeAlso, nested)) + + graph_text = graph.serialize(format="longturtle", canon=True) + if first_graph_text == "": + first_graph_text = graph_text + + serialization_counter[graph_text] += 1 + + expected_serialization = """\ +PREFIX ex: +PREFIX rdfs: + +ex:A + rdfs:comment "Thing A" ; +. + +ex:C + rdfs:comment "Thing C" ; +. + +ex:B + rdfs:comment "Thing B" ; +. + +[] ex:has + [ + rdfs:seeAlso ex:A ; + ] ; +. + +[] rdfs:seeAlso ex:B ; +. + +[] ex:has + [ + rdfs:seeAlso ex:C ; + ] ; +. + +[] rdfs:seeAlso ex:A ; +. + +[] rdfs:seeAlso ex:C ; +. + +[] rdfs:seeAlso ex:B ; +. + +[] ex:has + [ + rdfs:seeAlso ex:B ; + ] ; +. + +""" + + assert expected_serialization.strip() == first_graph_text.strip() + assert 1 == len(serialization_counter) diff --git a/test/test_serializers/test_serializer_trix.py b/test/test_serializers/test_serializer_trix.py index bdfc91c81..37bc5912f 100644 --- a/test/test_serializers/test_serializer_trix.py +++ b/test/test_serializers/test_serializer_trix.py @@ -1,6 +1,6 @@ from io import BytesIO -from rdflib.graph import ConjunctiveGraph, Graph +from rdflib.graph import Dataset, Graph from rdflib.term import Literal, URIRef @@ -19,7 +19,7 @@ def test_serialize(): g2 = Graph(identifier=s2) g2.add((r2, label, Literal("label 3"))) - g = ConjunctiveGraph() + g = Dataset() for s, p, o in g1.triples((None, None, None)): g.addN([(s, p, o, g1)]) for s, p, o in g2.triples((None, None, None)): @@ -28,14 +28,14 @@ def test_serialize(): g.add((r3, label, Literal(4))) r = g.serialize(format="trix", encoding="utf-8") - g3 = ConjunctiveGraph() + g3 = Dataset() g3.parse(BytesIO(r), format="trix") for q in g3.quads((None, None, None)): # TODO: Fix once getGraph/getContext is in conjunctive graph - if isinstance(q[3].identifier, URIRef): - tg = Graph(store=g.store, identifier=q[3].identifier) + if isinstance(q[3], URIRef): + tg = Graph(store=g.store, identifier=q[3]) else: # BNode, this is a bit ugly # we cannot match the bnode to the right graph automagically @@ -74,7 +74,7 @@ def test_issue_250(): """ - graph = ConjunctiveGraph() + graph = Dataset() graph.bind(None, "http://defaultnamespace/") sg = graph.serialize(format="trix") assert 'xmlns="http://defaultnamespace/"' not in sg, sg diff --git a/test/test_serializers/test_serializer_turtle_base_namespace.py b/test/test_serializers/test_serializer_turtle_base_namespace.py new file mode 100644 index 000000000..f0971611d --- /dev/null +++ b/test/test_serializers/test_serializer_turtle_base_namespace.py @@ -0,0 +1,34 @@ +from rdflib import Graph, Namespace, URIRef + +# https://github.com/RDFLib/rdflib/issues/3237 +# Test that the ns1 prefix is not generated when the base is set. +mns = Namespace("http://my-namespace.net/") + + +def test_turtle(): + g = Graph(base="http://my-base.net/") + g.add((mns.foo, URIRef("http://my-base.net/my-predicate"), mns.bar)) + result = g.serialize(format="text/turtle") + assert ( + result + == """@base . + + . + +""" + ) + + +def test_longturtle(): + g = Graph(base="http://my-base.net/") + g.add((mns.foo, URIRef("http://my-base.net/my-predicate"), mns.bar)) + result = g.serialize(format="longturtle", canon=True) + assert ( + result + == """BASE + + + ; +. +""" + ), print(result) diff --git a/test/test_serializers/test_serializer_xml.py b/test/test_serializers/test_serializer_xml.py index eda0b3d43..535b24c85 100644 --- a/test/test_serializers/test_serializer_xml.py +++ b/test/test_serializers/test_serializer_xml.py @@ -1,6 +1,6 @@ from io import BytesIO -from rdflib.graph import ConjunctiveGraph +from rdflib.graph import Dataset from rdflib.namespace import RDFS from rdflib.plugins.serializers.rdfxml import XMLSerializer from rdflib.term import BNode, URIRef @@ -10,7 +10,7 @@ class SerializerTestBase: repeats = 8 def setup_method(self): - graph = ConjunctiveGraph() + graph = Dataset(default_union=True) graph.parse(data=self.test_content, format=self.test_content_format) self.source_graph = graph @@ -40,13 +40,13 @@ def _assert_equal_graphs(g1, g2): def _mangled_copy(g): - "Makes a copy of the graph, replacing all bnodes with the bnode ``_blank``." - gcopy = ConjunctiveGraph() + """Makes a copy of the graph, replacing all bnodes with the bnode ``_blank``.""" + gcopy = Dataset() def isbnode(v): return isinstance(v, BNode) - for s, p, o in g: + for s, p, o, c in g: if isbnode(s): s = _blank if isbnode(p): @@ -67,8 +67,8 @@ def serialize(source_graph, make_serializer, get_value=True, extra_args={}): def serialize_and_load(source_graph, make_serializer): stream = serialize(source_graph, make_serializer, False) stream.seek(0) - reparsed_graph = ConjunctiveGraph() - reparsed_graph.parse(stream, publicID=None, format="xml") + reparsed_graph = Dataset(default_union=True) + reparsed_graph.parse(stream, format="xml") return reparsed_graph @@ -173,7 +173,7 @@ def test_result_fragments_with_base(self): ' + WHERE {?s ?p ?o} + """ + results = bool(dataset.query(query)) + assert results diff --git a/test/test_sparql/test_initbindings.py b/test/test_sparql/test_initbindings.py index 0cb55f344..55f5853a3 100644 --- a/test/test_sparql/test_initbindings.py +++ b/test/test_sparql/test_initbindings.py @@ -1,8 +1,8 @@ -from rdflib import ConjunctiveGraph, Literal, URIRef, Variable +from rdflib import Dataset, Literal, URIRef, Variable from rdflib.plugins.sparql import prepareQuery from test.utils.namespace import EGDC -g = ConjunctiveGraph() +g = Dataset() def test_str(): @@ -272,7 +272,7 @@ def test_prepare(): def test_data(): - data = ConjunctiveGraph() + data = Dataset() data += [ (URIRef("urn:a"), URIRef("urn:p"), Literal("a")), (URIRef("urn:b"), URIRef("urn:p"), Literal("b")), @@ -297,7 +297,7 @@ def test_ask(): assert a == b, "ask: %r != %r" % (a, b) -g2 = ConjunctiveGraph() +g2 = Dataset() g2.bind("", EGDC) g2.add((EGDC["s1"], EGDC["p"], EGDC["o1"])) g2.add((EGDC["s2"], EGDC["p"], EGDC["o2"])) diff --git a/test/test_sparql/test_optional.py b/test/test_sparql/test_optional.py new file mode 100644 index 000000000..75fd71a1a --- /dev/null +++ b/test/test_sparql/test_optional.py @@ -0,0 +1,37 @@ +from rdflib import Graph, Literal, URIRef, Variable + + +def test_binding_with_optional_clause() -> None: + """ + Optional clauses should bind variables if feasible. + + See https://github.com/RDFLib/rdflib/issues/2957 + """ + g = Graph().parse( + data=""" + prefix ex: + ex:document ex:subject "Nice cars" . + ex:someCar ex:type "Car" . + """ + ) + result = g.query( + """prefix ex: + select ?subject ?car + where { + $this ex:subject ?subject. + optional + { + # an offending subselect clause + select ?car + where { + ?car ex:type "Car". + } + } + }""" + ) + assert len(result.bindings) == 1 + (first,) = result.bindings + assert first.get(Variable("car")) == URIRef("https://www.example.org/someCar") + assert first.get(Variable("subject")) == Literal( + "Nice cars" + ), "optional clause didnt bind" diff --git a/test/test_sparql/test_sparql.py b/test/test_sparql/test_sparql.py index a42f7ffa5..74d7d9b72 100644 --- a/test/test_sparql/test_sparql.py +++ b/test/test_sparql/test_sparql.py @@ -9,7 +9,7 @@ import rdflib.plugins.sparql import rdflib.plugins.sparql.operators import rdflib.plugins.sparql.parser -from rdflib import BNode, ConjunctiveGraph, Graph, Literal, URIRef +from rdflib import BNode, Dataset, Graph, Literal, URIRef from rdflib.compare import isomorphic from rdflib.namespace import RDF, RDFS, Namespace from rdflib.plugins.sparql import prepareQuery, sparql @@ -182,11 +182,11 @@ def test_bindings(): def test_named_filter_graph_query(): - g = ConjunctiveGraph() - g.namespace_manager.bind("rdf", RDF) - g.namespace_manager.bind("rdfs", RDFS) + g = Dataset(default_union=True) + g.bind("rdf", RDF) + g.bind("rdfs", RDFS) ex = Namespace("https://ex.com/") - g.namespace_manager.bind("ex", ex) + g.bind("ex", ex) g.get_context(ex.g1).parse( format="turtle", data=f""" diff --git a/test/test_sparql/test_update.py b/test/test_sparql/test_update.py index 17c7967fa..4b16aa7de 100644 --- a/test/test_sparql/test_update.py +++ b/test/test_sparql/test_update.py @@ -4,7 +4,9 @@ import pytest -from rdflib.graph import ConjunctiveGraph, Dataset, Graph +from rdflib import Literal, Namespace, URIRef, Variable +from rdflib.compare import isomorphic +from rdflib.graph import DATASET_DEFAULT_GRAPH_ID, ConjunctiveGraph, Dataset, Graph from test.data import TEST_DATA_DIR from test.utils import GraphHelper from test.utils.graph import GraphSource @@ -90,3 +92,161 @@ def test_load_into_named( ) GraphHelper.assert_collection_graphs_equal(expected_graph, actual_graph) + + +def test_reevaluation_between_updates_modify() -> None: + """ + during an update the values should be bound once and then deleted and inserted + once per valid binding. + + See https://github.com/RDFLib/rdflib/issues/3246 + """ + ex = Namespace("http://example.com/") + + g = Graph() + g.bind("ex", ex) + + g.add((ex.foo, ex.value, Literal(1))) + g.add((ex.foo, ex.value, Literal(11))) + + g.add((ex.bar, ex.value, Literal(3))) + + g.update( + """ + DELETE { + ex:bar ex:value ?oldValue . + } + INSERT { + ex:bar ex:value ?newValue . + } + WHERE { + ex:foo ex:value ?instValue . + OPTIONAL { ex:bar ex:value ?oldValue . } + BIND(COALESCE(?oldValue, 0) + ?instValue AS ?newValue) + } + """ + ) + + result = g.query("SELECT ?x WHERE { ex:bar ex:value ?x }") + values = {b.get(Variable("x")) for b in result} # type: ignore + assert values == {Literal(4), Literal(14)} + + +def test_reevaluation_between_updates_insert() -> None: + """ + during an update the values should be bound once and then deleted and inserted + once per valid binding. + + See https://github.com/RDFLib/rdflib/issues/3246 + """ + ex = Namespace("http://example.com/") + + g = Graph() + g.bind("ex", ex) + + g.add((ex.foo, ex.value, Literal(1))) + g.add((ex.foo, ex.value, Literal(11))) + + g.add((ex.bar, ex.value, Literal(3))) + + g.update( + """ + INSERT { + ex:bar ex:value ?newValue . + } + WHERE { + ex:foo ex:value ?instValue . + OPTIONAL { ex:bar ex:value ?oldValue . } + BIND(COALESCE(?oldValue, 0) + ?instValue AS ?newValue) + } + """ + ) + + result = g.query("SELECT ?x WHERE { ex:bar ex:value ?x }") + values = {b.get(Variable("x")) for b in result} # type: ignore + assert values == {Literal(3), Literal(4), Literal(14)} + + +def test_inserts_in_named_graph(): + trig_data = """ + @prefix ex: . + @prefix rdf: . + + # Named graph 1 + ex:graph1 { + ex:person1 ex:name "Alice" ; + ex:age 30 . + } + + # Named graph 2 + ex:graph2 { + ex:person1 ex:worksFor ex:company1 . + ex:company1 ex:industry "Technology" . + } + """ + ds = Dataset().parse(data=trig_data, format="trig") + ds.update( + """ + INSERT { + GRAPH { + ?s ?p ?o + } + + ?s ?p ?o + } + WHERE { + GRAPH ?g { + ?s ?p ?o + } + } + """ + ) + + expected_trig = """ + @prefix ex: . + @prefix xsd: . + + { + ex:person1 ex:age 30 ; + ex:name "Alice" ; + ex:worksFor ex:company1 . + + ex:company1 ex:industry "Technology" . + } + + { + ex:person1 ex:age 30 ; + ex:name "Alice" ; + ex:worksFor ex:company1 . + + ex:company1 ex:industry "Technology" . + } + + ex:graph1 { + ex:person1 ex:age 30 ; + ex:name "Alice" . + } + + ex:graph2 { + ex:person1 ex:worksFor ex:company1 . + + ex:company1 ex:industry "Technology" . + } + """ + expected_ds = Dataset().parse(data=expected_trig, format="trig") + + # There should be exactly 4 graphs, including the default graph. + # SPARQL Update inserts into the default graph should go into the default graph, + # not to a new graph with a blank node label. + # See https://github.com/RDFLib/rdflib/issues/3080 + expected_graph_names = [ + DATASET_DEFAULT_GRAPH_ID, + URIRef("urn:graph"), + URIRef("http://example.org/graph1"), + URIRef("http://example.org/graph2"), + ] + assert set(expected_graph_names) == set(graph.identifier for graph in ds.graphs()) + + for graph in ds.graphs(): + expected_graph = expected_ds.graph(graph.identifier) + assert isomorphic(graph, expected_graph) diff --git a/test/test_store/test_store_sparqlupdatestore_mock.py b/test/test_store/test_store_sparqlupdatestore_mock.py index 5d7e13eb8..054f746e1 100644 --- a/test/test_store/test_store_sparqlupdatestore_mock.py +++ b/test/test_store/test_store_sparqlupdatestore_mock.py @@ -1,6 +1,6 @@ from typing import ClassVar -from rdflib.graph import ConjunctiveGraph +from rdflib.graph import Dataset from rdflib.plugins.stores.sparqlstore import SPARQLUpdateStore from test.utils.http import MethodName, MockHTTPResponse from test.utils.httpservermock import ServedBaseHTTPServerMock @@ -33,7 +33,7 @@ def teardown_method(self): pass def test_graph_update(self): - graph = ConjunctiveGraph("SPARQLUpdateStore") + graph = Dataset("SPARQLUpdateStore") graph.open((self.query_endpoint, self.update_endpoint)) update_statement = ( f"INSERT DATA {{ {EGDO['subj']} {EGDO['pred']} {EGDO['obj']}. }}" @@ -58,7 +58,7 @@ def test_graph_update(self): assert "application/sparql-update" in req.headers.get("content-type") def test_update_encoding(self): - graph = ConjunctiveGraph("SPARQLUpdateStore") + graph = Dataset("SPARQLUpdateStore") graph.open((self.query_endpoint, self.update_endpoint)) update_statement = ( f"INSERT DATA {{ {EGDO['subj']} {EGDO['pred']} {EGDO['obj']}. }}" diff --git a/test/test_tools/test_chunk_serializer.py b/test/test_tools/test_chunk_serializer.py index d683ca606..9d68c0c04 100644 --- a/test/test_tools/test_chunk_serializer.py +++ b/test/test_tools/test_chunk_serializer.py @@ -84,7 +84,7 @@ def test_chunk_by_size(tmp_path: Path): (TEST_DATA_DIR / "defined_namespaces/mf.ttl", 100, ..., False, True, 1), ], ) -def test_chuking( +def test_chunking( tmp_path: Path, test_graph_path: Path, max_triples: Union[ellipsis, int], diff --git a/test/test_trig.py b/test/test_trig.py index 1c158fa86..afcf2c4cf 100644 --- a/test/test_trig.py +++ b/test/test_trig.py @@ -16,7 +16,7 @@ def test_empty(): def test_repeat_triples(): - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() g.get_context("urn:a").add( (rdflib.URIRef("urn:1"), rdflib.URIRef("urn:2"), rdflib.URIRef("urn:3")) ) @@ -33,7 +33,7 @@ def test_repeat_triples(): def test_same_subject(): - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() g.get_context("urn:a").add( (rdflib.URIRef("urn:1"), rdflib.URIRef("urn:p1"), rdflib.URIRef("urn:o1")) ) @@ -54,7 +54,7 @@ def test_same_subject(): def test_remember_namespace(): - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() g.add(TRIPLE + (rdflib.URIRef("http://example.com/graph1"),)) # In 4.2.0 the first serialization would fail to include the # prefix for the graph but later serialize() calls would work. @@ -65,14 +65,14 @@ def test_remember_namespace(): def test_graph_qname_syntax(): - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() g.add(TRIPLE + (rdflib.URIRef("http://example.com/graph1"),)) out = g.serialize(format="trig", encoding="latin-1") assert b"ns1:graph1 {" not in out def test_graph_uri_syntax(): - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() # getQName will not abbreviate this, so it should serialize as # a '<...>' term. g.add(TRIPLE + (rdflib.URIRef("http://example.com/foo."),)) @@ -81,7 +81,7 @@ def test_graph_uri_syntax(): def test_blank_graph_identifier(): - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() g.add(TRIPLE + (rdflib.BNode(),)) out = g.serialize(format="trig", encoding="latin-1") graph_label_line = out.splitlines()[-4] @@ -94,7 +94,7 @@ def test_graph_parsing(): data = """ . """ - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() g.parse(data=data, format="trig") assert len(list(g.contexts())) == 1 @@ -104,7 +104,7 @@ def test_graph_parsing(): { . } """ - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() g.parse(data=data, format="trig") assert len(list(g.contexts())) == 1 @@ -118,7 +118,7 @@ def test_graph_parsing(): . } """ - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() g.parse(data=data, format="trig") assert len(list(g.contexts())) == 2 @@ -133,7 +133,7 @@ def test_round_trips(): . } """ - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() for i in range(5): g.parse(data=data, format="trig") data = g.serialize(format="trig") @@ -154,7 +154,7 @@ def test_default_graph_serializes_without_name(): { . } """ - g = rdflib.ConjunctiveGraph() + g = rdflib.Dataset() g.parse(data=data, format="trig") data = g.serialize(format="trig", encoding="latin-1") @@ -174,7 +174,7 @@ def test_prefixes(): } """ - cg = rdflib.ConjunctiveGraph() + cg = rdflib.Dataset() cg.parse(data=data, format="trig") data = cg.serialize(format="trig", encoding="latin-1") diff --git a/test/test_turtle_quoting.py b/test/test_turtle_quoting.py index aa523f57b..7cdd63a24 100644 --- a/test/test_turtle_quoting.py +++ b/test/test_turtle_quoting.py @@ -12,7 +12,7 @@ import pytest -from rdflib.graph import ConjunctiveGraph, Graph +from rdflib.graph import Dataset, Graph from rdflib.plugins.parsers import ntriples from rdflib.term import Literal, URIRef from test.utils.namespace import EGDC @@ -147,7 +147,7 @@ def test_parse_correctness( data = f' "{quoted}" .' else: data = f' "{quoted}".' - graph = ConjunctiveGraph() + graph = Dataset(default_union=True) graph.parse(data=data, format=format) objs = list(graph.objects()) assert len(objs) == 1 diff --git a/test/test_util.py b/test/test_util.py index 63c085033..890697475 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -9,7 +9,7 @@ import pytest from rdflib import XSD, util -from rdflib.graph import ConjunctiveGraph, Graph, QuotedGraph +from rdflib.graph import Dataset, Graph, QuotedGraph from rdflib.namespace import RDF, RDFS from rdflib.term import BNode, IdentifiedNode, Literal, Node, URIRef from rdflib.util import _coalesce, _iri2uri, find_roots, get_tree @@ -262,7 +262,7 @@ def parse_n3(term_n3): "@prefix xsd: .\n" " %s.\n" % term_n3 ) - g = ConjunctiveGraph() + g = Dataset(default_union=True) g.parse(data=prepstr, format="n3") return [t for t in g.triples((None, None, None))][0][2] diff --git a/test_reports/rdflib_w3c_sparql10-HEAD.ttl b/test_reports/rdflib_w3c_sparql10-HEAD.ttl index 78997b01c..b8369a94d 100644 --- a/test_reports/rdflib_w3c_sparql10-HEAD.ttl +++ b/test_reports/rdflib_w3c_sparql10-HEAD.ttl @@ -1795,7 +1795,7 @@ earl:assertedBy ; earl:mode earl:automatic ; earl:result [ a earl:TestResult ; - earl:outcome earl:failed ] ; + earl:outcome earl:passed ] ; earl:subject ; earl:test . @@ -1859,7 +1859,7 @@ earl:assertedBy ; earl:mode earl:automatic ; earl:result [ a earl:TestResult ; - earl:outcome earl:failed ] ; + earl:outcome earl:passed ] ; earl:subject ; earl:test . @@ -1907,7 +1907,7 @@ earl:assertedBy ; earl:mode earl:automatic ; earl:result [ a earl:TestResult ; - earl:outcome earl:failed ] ; + earl:outcome earl:passed ] ; earl:subject ; earl:test . @@ -2787,7 +2787,7 @@ earl:assertedBy ; earl:mode earl:automatic ; earl:result [ a earl:TestResult ; - earl:outcome earl:failed ] ; + earl:outcome earl:passed ] ; earl:subject ; earl:test .