Skip to content

client

RDF4J client module.

Classes:

Attributes:

ObjectType module-attribute

ObjectType = Union[URIRef, Literal, None]

PredicateType module-attribute

PredicateType = Union[URIRef, None]

SubjectType module-attribute

SubjectType = Union[URIRef, None]

GraphStoreManager

GraphStoreManager(identifier: str, http_client: Client)

An RDF4J Graph Store Protocol Client.

Parameters:

  • identifier

    (str) –

    The identifier of the repository.

  • http_client

    (Client) –

    The httpx.Client instance.

Methods:

  • add

    Add statements to the specified graph.

  • clear

    Clear all statements in the specified graph.

  • get

    Fetch all statements in the specified graph.

  • overwrite

    Overwrite statements in the specified graph.

Attributes:

Source code in rdflib/contrib/rdf4j/client.py
def __init__(self, identifier: str, http_client: httpx.Client):
    self._identifier = identifier
    self._http_client = http_client
    self._content_type = "application/n-triples"

http_client property

http_client

identifier property

identifier

Repository identifier.

add

add(graph_name: URIRef | str, data: str | bytes | BinaryIO | Graph)

Add statements to the specified graph.

Parameters:

  • graph_name

    (URIRef | str) –

    The graph name of the graph.

    For the default graph, use DATASET_DEFAULT_GRAPH_ID.

  • data

    (str | bytes | BinaryIO | Graph) –

    The RDF data to add.

Source code in rdflib/contrib/rdf4j/client.py
def add(self, graph_name: URIRef | str, data: str | bytes | BinaryIO | Graph):
    """Add statements to the specified graph.

    Parameters:
        graph_name: The graph name of the graph.

            For the default graph, use
            [`DATASET_DEFAULT_GRAPH_ID`][rdflib.graph.DATASET_DEFAULT_GRAPH_ID].

        data: The RDF data to add.
    """
    if not graph_name:
        raise ValueError("Graph name must be provided.")
    validate_graph_name(graph_name)
    stream, should_close = rdf_payload_to_stream(data)
    headers = {
        "Content-Type": self._content_type,
    }
    params = self._build_graph_name_params(graph_name) or None
    try:
        response = self.http_client.post(
            self._build_url(graph_name),
            headers=headers,
            params=params,
            content=stream,
        )
        response.raise_for_status()
    finally:
        if should_close:
            stream.close()

clear

clear(graph_name: URIRef | str)

Clear all statements in the specified graph.

Parameters:

Source code in rdflib/contrib/rdf4j/client.py
def clear(self, graph_name: URIRef | str):
    """Clear all statements in the specified graph.

    Parameters:
        graph_name: The graph name of the graph.

            For the default graph, use
            [`DATASET_DEFAULT_GRAPH_ID`][rdflib.graph.DATASET_DEFAULT_GRAPH_ID].
    """
    if not graph_name:
        raise ValueError("Graph name must be provided.")
    validate_graph_name(graph_name)
    params = self._build_graph_name_params(graph_name) or None
    response = self.http_client.delete(self._build_url(graph_name), params=params)
    response.raise_for_status()

get

get(graph_name: URIRef | str) -> Graph

Fetch all statements in the specified graph.

Parameters:

Returns:

  • Graph

    A Graph object containing all statements in the graph.

Source code in rdflib/contrib/rdf4j/client.py
def get(self, graph_name: URIRef | str) -> Graph:
    """Fetch all statements in the specified graph.

    Parameters:
        graph_name: The graph name of the graph.

            For the default graph, use
            [`DATASET_DEFAULT_GRAPH_ID`][rdflib.graph.DATASET_DEFAULT_GRAPH_ID].

    Returns:
        A [`Graph`][rdflib.graph.Graph] object containing all statements in the
            graph.
    """
    if not graph_name:
        raise ValueError("Graph name must be provided.")
    validate_graph_name(graph_name)
    headers = {
        "Accept": self._content_type,
    }
    params = self._build_graph_name_params(graph_name) or None

    response = self.http_client.get(
        self._build_url(graph_name),
        headers=headers,
        params=params,
    )
    response.raise_for_status()

    return Graph(identifier=graph_name).parse(
        data=response.text, format=self._content_type
    )

overwrite

overwrite(graph_name: URIRef | str, data: str | bytes | BinaryIO | Graph)

Overwrite statements in the specified graph.

Parameters:

  • graph_name

    (URIRef | str) –

    The graph name of the graph.

    For the default graph, use DATASET_DEFAULT_GRAPH_ID.

  • data

    (str | bytes | BinaryIO | Graph) –

    The RDF data to overwrite with.

Source code in rdflib/contrib/rdf4j/client.py
def overwrite(self, graph_name: URIRef | str, data: str | bytes | BinaryIO | Graph):
    """Overwrite statements in the specified graph.

    Parameters:
        graph_name: The graph name of the graph.

            For the default graph, use
            [`DATASET_DEFAULT_GRAPH_ID`][rdflib.graph.DATASET_DEFAULT_GRAPH_ID].

        data: The RDF data to overwrite with.
    """
    if not graph_name:
        raise ValueError("Graph name must be provided.")
    validate_graph_name(graph_name)
    stream, should_close = rdf_payload_to_stream(data)
    headers = {
        "Content-Type": self._content_type,
    }
    params = self._build_graph_name_params(graph_name) or None
    try:
        response = self.http_client.put(
            self._build_url(graph_name),
            headers=headers,
            params=params,
            content=stream,
        )
        response.raise_for_status()
    finally:
        if should_close:
            stream.close()

NamespaceListingResult dataclass

NamespaceListingResult(prefix: str, namespace: str)

RDF4J namespace and prefix name result.

Attributes:

namespace instance-attribute

namespace: str

prefix instance-attribute

prefix: str

RDF4JClient

RDF4JClient(base_url: str, auth: tuple[str, str] | str | None = None, timeout: float | Timeout = 30.0, **kwargs: Any)

RDF4J client.

This client and its inner management objects perform HTTP requests via httpx and may raise httpx-specific exceptions. Errors documented by RDF4J in its protocol specification are mapped to specific exceptions in this library where applicable. Error mappings are documented on each management method. The underlying httpx client is reused across requests, and connection pooling is handled automatically by httpx.

Parameters:

  • base_url

    (str) –

    The base URL of the RDF4J server.

  • auth

    (tuple[str, str] | str | None, default: None ) –

    Authentication credentials. Can be a tuple (username, password) for basic auth, or a string for token-based auth (e.g., “GDB “) which is added as the Authorization header.

  • timeout

    (float | Timeout, default: 30.0 ) –

    Request timeout in seconds or an httpx.Timeout for fine-grained control (default: 30.0).

  • kwargs

    (Any, default: {} ) –

    Additional keyword arguments to pass to the httpx.Client.

Methods:

Attributes:

Source code in rdflib/contrib/rdf4j/client.py
def __init__(
    self,
    base_url: str,
    auth: tuple[str, str] | str | None = None,
    timeout: float | httpx.Timeout = 30.0,
    **kwargs: Any,
):
    if not base_url.endswith("/"):
        base_url += "/"

    httpx_auth: tuple[str, str] | None = None
    if isinstance(auth, tuple):
        httpx_auth = auth
    elif isinstance(auth, str):
        headers = kwargs.get("headers", {})
        headers["Authorization"] = auth
        kwargs["headers"] = headers

    self._http_client = httpx.Client(
        base_url=base_url, auth=httpx_auth, timeout=timeout, **kwargs
    )
    self._repository_manager = RepositoryManager(self.http_client)
    try:
        protocol_version = self.protocol
    except httpx.RequestError as err:
        self.close()
        raise RDF4JUnsupportedProtocolError(
            f"Failed to check protocol version: {err}"
        ) from err
    if protocol_version < 12:
        self.close()
        raise RDF4JUnsupportedProtocolError(
            f"RDF4J server protocol version {protocol_version} is not supported. Minimum required version is 12."
        )

http_client property

http_client

protocol property

protocol: float

The RDF4J REST API protocol version.

Returns:

  • float

    The protocol version number.

repositories property

repositories: RepositoryManager

Server-level repository management operations.

__enter__

__enter__()
Source code in rdflib/contrib/rdf4j/client.py
def __enter__(self):
    return self

__exit__

__exit__(exc_type, exc_val, exc_tb)
Source code in rdflib/contrib/rdf4j/client.py
def __exit__(self, exc_type, exc_val, exc_tb):
    self.close()

close

close()

Close the underlying httpx.Client.

Source code in rdflib/contrib/rdf4j/client.py
def close(self):
    """Close the underlying httpx.Client."""
    self.http_client.close()

RDF4JNamespaceManager

RDF4JNamespaceManager(identifier: str, http_client: Client)

A namespace manager for RDF4J repositories.

Parameters:

  • identifier

    (str) –

    The identifier of the repository.

  • http_client

    (Client) –

    The httpx.Client instance.

Methods:

  • clear

    Clear all namespace declarations in the repository.

  • get

    Get the namespace URI for a given prefix.

  • list

    List all namespace declarations in the repository.

  • remove

    Remove the namespace declaration for a given prefix.

  • set

    Set the namespace URI for a given prefix.

Attributes:

Source code in rdflib/contrib/rdf4j/client.py
def __init__(self, identifier: str, http_client: httpx.Client):
    self._identifier = identifier
    self._http_client = http_client

http_client property

http_client

identifier property

identifier

Repository identifier.

clear

clear()

Clear all namespace declarations in the repository.

Source code in rdflib/contrib/rdf4j/client.py
def clear(self):
    """Clear all namespace declarations in the repository."""
    headers = {
        "Accept": "application/sparql-results+json",
    }
    response = self.http_client.delete(
        f"/repositories/{self.identifier}/namespaces", headers=headers
    )
    response.raise_for_status()

get

get(prefix: str) -> str | None

Get the namespace URI for a given prefix.

Parameters:

  • prefix

    (str) –

    The prefix to lookup.

Returns:

  • str | None

    The namespace URI or None if not found.

Source code in rdflib/contrib/rdf4j/client.py
def get(self, prefix: str) -> str | None:
    """Get the namespace URI for a given prefix.

    Parameters:
        prefix: The prefix to lookup.

    Returns:
        The namespace URI or `None` if not found.
    """
    if not prefix:
        raise ValueError("Prefix cannot be empty.")
    headers = {
        "Accept": "text/plain",
    }
    try:
        response = self.http_client.get(
            f"/repositories/{self.identifier}/namespaces/{prefix}", headers=headers
        )
        response.raise_for_status()
        return response.text
    except httpx.HTTPStatusError as err:
        if err.response.status_code == 404:
            return None
        raise

list

List all namespace declarations in the repository.

Returns:

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def list(self) -> list[NamespaceListingResult]:
    """List all namespace declarations in the repository.

    Returns:
        list[NamespaceListingResult]: List of namespace and prefix name results.

    Raises:
        RepositoryResponseFormatError: If the response format is unrecognized.
    """
    headers = {
        "Accept": "application/sparql-results+json",
    }
    response = self.http_client.get(
        f"/repositories/{self.identifier}/namespaces", headers=headers
    )
    response.raise_for_status()

    try:
        data = response.json()
        results = data["results"]["bindings"]
        return [
            NamespaceListingResult(
                prefix=row["prefix"]["value"],
                namespace=row["namespace"]["value"],
            )
            for row in results
        ]
    except (KeyError, ValueError) as err:
        raise RepositoryResponseFormatError(f"Unrecognised response format: {err}")

remove

remove(prefix: str)

Remove the namespace declaration for a given prefix.

Parameters:

  • prefix

    (str) –

    The prefix to remove.

Source code in rdflib/contrib/rdf4j/client.py
def remove(self, prefix: str):
    """Remove the namespace declaration for a given prefix.

    Parameters:
        prefix: The prefix to remove.
    """
    if not prefix:
        raise ValueError("Prefix cannot be empty.")
    response = self.http_client.delete(
        f"/repositories/{self.identifier}/namespaces/{prefix}"
    )
    response.raise_for_status()

set

set(prefix: str, namespace: str)

Set the namespace URI for a given prefix.

Note

If the prefix was previously mapped to a different namespace, this will be overwritten.

Parameters:

  • prefix

    (str) –

    The prefix to set.

  • namespace

    (str) –

    The namespace URI to set.

Source code in rdflib/contrib/rdf4j/client.py
def set(self, prefix: str, namespace: str):
    """Set the namespace URI for a given prefix.

    !!! note
        If the prefix was previously mapped to a different namespace, this will be
        overwritten.

    Parameters:
        prefix: The prefix to set.
        namespace: The namespace URI to set.
    """
    if not prefix:
        raise ValueError("Prefix cannot be empty.")
    if not namespace:
        raise ValueError("Namespace cannot be empty.")
    headers = {
        "Content-Type": "text/plain",
    }
    response = self.http_client.put(
        f"/repositories/{self.identifier}/namespaces/{prefix}",
        headers=headers,
        content=namespace,
    )
    response.raise_for_status()

Repository

Repository(identifier: str, http_client: Client)

RDF4J repository client.

Parameters:

  • identifier

    (str) –

    The identifier of the repository.

  • http_client

    (Client) –

    The httpx.Client instance.

Methods:

  • delete

    Deletes statements from the repository matching the filtering parameters.

  • get

    Get RDF statements from the repository matching the filtering parameters.

  • graph_names

    Get a list of all graph names in the repository.

  • health

    Repository health check.

  • overwrite

    Upload and overwrite statements in the repository.

  • query

    Execute a SPARQL query against the repository.

  • size

    The number of statements in the repository or in the specified graph name.

  • transaction

    Create a new transaction for the repository.

  • update

    Execute a SPARQL update operation on the repository.

  • upload

    Upload and append statements to the repository.

Attributes:

Source code in rdflib/contrib/rdf4j/client.py
def __init__(self, identifier: str, http_client: httpx.Client):
    self._identifier = identifier
    self._http_client = http_client
    self._namespace_manager: RDF4JNamespaceManager | None = None
    self._graph_store_manager: GraphStoreManager | None = None

graphs property

Graph store manager for the repository.

http_client property

http_client

identifier property

identifier

Repository identifier.

namespaces property

Namespace manager for the repository.

delete

delete(subj: SubjectType = None, pred: PredicateType = None, obj: ObjectType = None, graph_name: URIRef | Iterable[URIRef] | str | None = None) -> None

Deletes statements from the repository matching the filtering parameters.

Note

The terms for subj, pred, obj or graph_name cannot be BNodes.

Parameters:

  • subj

    (SubjectType, default: None ) –

    Subject of the statement to filter by, or None to match all.

  • pred

    (PredicateType, default: None ) –

    Predicate of the statement to filter by, or None to match all.

  • obj

    (ObjectType, default: None ) –

    Object of the statement to filter by, or None to match all.

  • graph_name

    (URIRef | Iterable[URIRef] | str | None, default: None ) –

    Graph name(s) to restrict to.

    The default value None queries all graphs.

    To query just the default graph, use DATASET_DEFAULT_GRAPH_ID.

Source code in rdflib/contrib/rdf4j/client.py
def delete(
    self,
    subj: SubjectType = None,
    pred: PredicateType = None,
    obj: ObjectType = None,
    graph_name: URIRef | Iterable[URIRef] | str | None = None,
) -> None:
    """Deletes statements from the repository matching the filtering parameters.

    !!! Note
        The terms for `subj`, `pred`, `obj` or `graph_name` cannot be
        [`BNodes`][rdflib.term.BNode].

    Parameters:
        subj: Subject of the statement to filter by, or `None` to match all.
        pred: Predicate of the statement to filter by, or `None` to match all.
        obj: Object of the statement to filter by, or `None` to match all.
        graph_name: Graph name(s) to restrict to.

            The default value `None` queries all graphs.

            To query just the default graph, use
            [`DATASET_DEFAULT_GRAPH_ID`][rdflib.graph.DATASET_DEFAULT_GRAPH_ID].
    """
    validate_no_bnodes(subj, pred, obj, graph_name)
    params: dict[str, str] = {}
    build_context_param(params, graph_name)
    build_spo_param(params, subj, pred, obj)

    response = self.http_client.delete(
        f"/repositories/{self.identifier}/statements",
        params=params,
    )
    response.raise_for_status()

get

get(subj: SubjectType = None, pred: PredicateType = None, obj: ObjectType = None, graph_name: URIRef | Iterable[URIRef] | str | None = None, infer: bool = True, content_type: str | None = None) -> Graph | Dataset

Get RDF statements from the repository matching the filtering parameters.

Note

The terms for subj, pred, obj or graph_name cannot be BNodes.

Parameters:

  • subj

    (SubjectType, default: None ) –

    Subject of the statement to filter by, or None to match all.

  • pred

    (PredicateType, default: None ) –

    Predicate of the statement to filter by, or None to match all.

  • obj

    (ObjectType, default: None ) –

    Object of the statement to filter by, or None to match all.

  • graph_name

    (URIRef | Iterable[URIRef] | str | None, default: None ) –

    Graph name(s) to restrict to.

    The default value None queries all graphs.

    To query just the default graph, use DATASET_DEFAULT_GRAPH_ID.

  • infer

    (bool, default: True ) –

    Specifies whether inferred statements should be included in the result.

  • content_type

    (str | None, default: None ) –

    The content type of the response. A triple-based format returns a Graph, while a quad-based format returns a Dataset.

Returns:

Source code in rdflib/contrib/rdf4j/client.py
def get(
    self,
    subj: SubjectType = None,
    pred: PredicateType = None,
    obj: ObjectType = None,
    graph_name: URIRef | Iterable[URIRef] | str | None = None,
    infer: bool = True,
    content_type: str | None = None,
) -> Graph | Dataset:
    """Get RDF statements from the repository matching the filtering parameters.

    !!! Note
        The terms for `subj`, `pred`, `obj` or `graph_name` cannot be
        [`BNodes`][rdflib.term.BNode].

    Parameters:
        subj: Subject of the statement to filter by, or `None` to match all.
        pred: Predicate of the statement to filter by, or `None` to match all.
        obj: Object of the statement to filter by, or `None` to match all.
        graph_name: Graph name(s) to restrict to.

            The default value `None` queries all graphs.

            To query just the default graph, use
            [`DATASET_DEFAULT_GRAPH_ID`][rdflib.graph.DATASET_DEFAULT_GRAPH_ID].

        infer: Specifies whether inferred statements should be included in the
            result.
        content_type: The content type of the response.
            A triple-based format returns a [Graph][rdflib.graph.Graph], while a
            quad-based format returns a [`Dataset`][rdflib.graph.Dataset].

    Returns:
        A [`Graph`][rdflib.graph.Graph] or [`Dataset`][rdflib.graph.Dataset] object
            with the repository namespace prefixes bound to it.
    """
    validate_no_bnodes(subj, pred, obj, graph_name)
    if content_type is None:
        content_type = "application/n-quads"
    headers = {"Accept": content_type}
    params: dict[str, str] = {}
    build_context_param(params, graph_name)
    build_spo_param(params, subj, pred, obj)
    build_infer_param(params, infer=infer)

    response = self.http_client.get(
        f"/repositories/{self.identifier}/statements",
        headers=headers,
        params=params,
    )
    response.raise_for_status()
    triple_formats = [
        "application/n-triples",
        "text/turtle",
        "application/rdf+xml",
    ]
    try:
        if content_type in triple_formats:
            retval = Graph().parse(data=response.text, format=content_type)
        else:
            retval = Dataset().parse(data=response.text, format=content_type)
        for result in self.namespaces.list():
            retval.bind(result.prefix, result.namespace, replace=True)
        return retval
    except Exception as err:
        raise RDFLibParserError(f"Error parsing RDF: {err}") from err

graph_names

graph_names() -> list[IdentifiedNode]

Get a list of all graph names in the repository.

Returns:

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def graph_names(self) -> list[IdentifiedNode]:
    """Get a list of all graph names in the repository.

    Returns:
        A list of graph names.

    Raises:
        RepositoryResponseFormatError: Fails to parse the repository graph names.
    """
    headers = {
        "Accept": "application/sparql-results+json",
    }
    response = self.http_client.get(
        f"/repositories/{self.identifier}/contexts", headers=headers
    )
    response.raise_for_status()
    try:
        values: list[IdentifiedNode] = []
        for row in response.json()["results"]["bindings"]:
            value = row["contextID"]["value"]
            value_type = row["contextID"]["type"]
            if value_type == "uri":
                values.append(URIRef(value))
            elif value_type == "bnode":
                values.append(BNode(value))
            else:
                raise ValueError(f"Invalid graph name type: {value_type}")
        return values
    except Exception as err:
        raise RepositoryResponseFormatError(
            f"Failed to parse repository graph names: {err}"
        ) from err

health

health() -> bool

Repository health check.

Returns:

  • bool ( bool ) –

    True if the repository is healthy, otherwise an error is raised.

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def health(self) -> bool:
    """Repository health check.

    Returns:
        bool: True if the repository is healthy, otherwise an error is raised.

    Raises:
        RepositoryNotFoundError: If the repository is not found.
        RepositoryNotHealthyError: If the repository is not healthy.
    """
    headers = {
        "Content-Type": "application/sparql-query",
        "Accept": "application/sparql-results+json",
    }
    try:
        response = self.http_client.post(
            f"/repositories/{self._identifier}", headers=headers, content="ASK {}"
        )
        response.raise_for_status()
        return True
    except httpx.HTTPStatusError as err:
        if err.response.status_code == 404:
            raise RepositoryNotFoundError(
                f"Repository {self._identifier} not found."
            )
        raise RepositoryNotHealthyError(
            f"Repository {self._identifier} is not healthy. {err.response.status_code} - {err.response.text}"
        )

overwrite

overwrite(data: str | bytes | BinaryIO | Graph | Dataset, graph_name: URIRef | Iterable[URIRef] | str | None = None, base_uri: str | None = None, content_type: str | None = None)

Upload and overwrite statements in the repository.

Parameters:

  • data

    (str | bytes | BinaryIO | Graph | Dataset) –

    The RDF data to upload.

  • graph_name

    (URIRef | Iterable[URIRef] | str | None, default: None ) –

    Graph name(s) to restrict to.

    The default value None applies to all graphs.

    To apply to just the default graph, use DATASET_DEFAULT_GRAPH_ID.

  • base_uri

    (str | None, default: None ) –

    The base URI to resolve against for any relative URIs in the data.

  • content_type

    (str | None, default: None ) –

    The content type of the data. Defaults to application/n-quads when the value is None.

Source code in rdflib/contrib/rdf4j/client.py
def overwrite(
    self,
    data: str | bytes | BinaryIO | Graph | Dataset,
    graph_name: URIRef | Iterable[URIRef] | str | None = None,
    base_uri: str | None = None,
    content_type: str | None = None,
):
    """Upload and overwrite statements in the repository.

    Parameters:
        data: The RDF data to upload.
        graph_name: Graph name(s) to restrict to.

            The default value `None` applies to all graphs.

            To apply to just the default graph, use
            [`DATASET_DEFAULT_GRAPH_ID`][rdflib.graph.DATASET_DEFAULT_GRAPH_ID].

        base_uri: The base URI to resolve against for any relative URIs in the data.
        content_type: The content type of the data. Defaults to
            `application/n-quads` when the value is `None`.
    """
    stream, should_close = rdf_payload_to_stream(data)
    validate_graph_name(graph_name)
    try:
        headers = {"Content-Type": content_type or "application/n-quads"}
        params: dict[str, str] = {}
        build_context_param(params, graph_name)
        if base_uri is not None:
            params["baseURI"] = base_uri
        response = self.http_client.put(
            f"/repositories/{self.identifier}/statements",
            headers=headers,
            params=params,
            content=stream,
        )
        response.raise_for_status()
    finally:
        if should_close:
            stream.close()

query

query(query: str, **kwargs)

Execute a SPARQL query against the repository.

Note

A POST request is used by default. If any keyword arguments are provided, a GET request is used instead, and the arguments are passed as query parameters.

Parameters:

  • query

    (str) –

    The SPARQL query to execute.

  • **kwargs

    Additional keyword arguments to include as query parameters in the request. See RDF4J REST API - Execute SPARQL query for the list of supported query parameters.

Source code in rdflib/contrib/rdf4j/client.py
def query(self, query: str, **kwargs):
    """Execute a SPARQL query against the repository.

    !!! note
        A POST request is used by default. If any keyword arguments are provided,
        a GET request is used instead, and the arguments are passed as query parameters.

    Parameters:
        query: The SPARQL query to execute.
        **kwargs: Additional keyword arguments to include as query parameters
            in the request. See
            [RDF4J REST API - Execute SPARQL query](https://rdf4j.org/documentation/reference/rest-api/#tag/SPARQL/paths/~1repositories~1%7BrepositoryID%7D/get)
            for the list of supported query parameters.
    """
    headers = {"Content-Type": "application/sparql-query"}
    build_sparql_query_accept_header(query, headers)

    if not kwargs:
        response = self.http_client.post(
            f"/repositories/{self.identifier}", headers=headers, content=query
        )
    else:
        response = self.http_client.get(
            f"/repositories/{self.identifier}",
            headers=headers,
            params={"query": query, **kwargs},
        )
    response.raise_for_status()
    try:
        return Result.parse(
            io.BytesIO(response.content),
            content_type=response.headers["Content-Type"].split(";")[0],
        )
    except KeyError as err:
        raise RDFLibParserError(
            f"Failed to parse SPARQL query result {response.headers.get('Content-Type')}: {err}"
        ) from err

size

size(graph_name: URIRef | Iterable[URIRef] | str | None = None) -> int

The number of statements in the repository or in the specified graph name.

Parameters:

  • graph_name

    (URIRef | Iterable[URIRef] | str | None, default: None ) –

    Graph name(s) to restrict to.

    The default value None queries all graphs.

    To query just the default graph, use DATASET_DEFAULT_GRAPH_ID.

Returns:

  • int

    The number of statements.

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def size(self, graph_name: URIRef | Iterable[URIRef] | str | None = None) -> int:
    """The number of statements in the repository or in the specified graph name.

    Parameters:
        graph_name: Graph name(s) to restrict to.

            The default value `None` queries all graphs.

            To query just the default graph, use
            [`DATASET_DEFAULT_GRAPH_ID`][rdflib.graph.DATASET_DEFAULT_GRAPH_ID].

    Returns:
        The number of statements.

    Raises:
        RepositoryResponseFormatError: Fails to parse the repository size.
    """
    validate_graph_name(graph_name)
    params: dict[str, str] = {}
    build_context_param(params, graph_name)
    response = self.http_client.get(
        f"/repositories/{self.identifier}/size", params=params
    )
    response.raise_for_status()
    return self._to_size(response.text)

transaction

transaction()

Create a new transaction for the repository.

Warning

Transaction instances are not thread-safe. Do not share a single Transaction instance across multiple threads. Each thread should create its own transaction, or use appropriate synchronization if sharing is required.

Source code in rdflib/contrib/rdf4j/client.py
@contextlib.contextmanager
def transaction(self):
    """Create a new transaction for the repository.

    !!! warning

    Transaction instances are not thread-safe. Do not share a single
    Transaction instance across multiple threads. Each thread should create
    its own transaction, or use appropriate synchronization if sharing is
    required.
    """
    with Transaction.create(self) as txn:
        yield txn

update

update(query: str)

Execute a SPARQL update operation on the repository.

Parameters:

  • query

    (str) –

    The SPARQL update query to execute.

Source code in rdflib/contrib/rdf4j/client.py
def update(self, query: str):
    """Execute a SPARQL update operation on the repository.

    Parameters:
        query: The SPARQL update query to execute.
    """
    headers = {"Content-Type": "application/sparql-update"}
    response = self.http_client.post(
        f"/repositories/{self.identifier}/statements",
        headers=headers,
        content=query,
    )
    response.raise_for_status()

upload

upload(data: str | bytes | BinaryIO | Graph | Dataset, base_uri: str | None = None, content_type: str | None = None)

Upload and append statements to the repository.

Parameters:

  • data

    (str | bytes | BinaryIO | Graph | Dataset) –

    The RDF data to upload.

  • base_uri

    (str | None, default: None ) –

    The base URI to resolve against for any relative URIs in the data.

  • content_type

    (str | None, default: None ) –

    The content type of the data. Defaults to application/n-quads when the value is None.

Source code in rdflib/contrib/rdf4j/client.py
def upload(
    self,
    data: str | bytes | BinaryIO | Graph | Dataset,
    base_uri: str | None = None,
    content_type: str | None = None,
):
    """Upload and append statements to the repository.

    Parameters:
        data: The RDF data to upload.
        base_uri: The base URI to resolve against for any relative URIs in the data.
        content_type: The content type of the data. Defaults to
            `application/n-quads` when the value is `None`.
    """
    stream, should_close = rdf_payload_to_stream(data)
    try:
        headers = {"Content-Type": content_type or "application/n-quads"}
        params = {}
        if base_uri is not None:
            params["baseURI"] = base_uri
        response = self.http_client.post(
            f"/repositories/{self.identifier}/statements",
            headers=headers,
            params=params,
            content=stream,
        )
        response.raise_for_status()
    finally:
        if should_close:
            stream.close()

RepositoryListingResult dataclass

RepositoryListingResult(identifier: str, uri: str, readable: bool, writable: bool, title: str | None = None)

RDF4J repository listing result.

Parameters:

  • identifier

    (str) –

    Repository identifier.

  • uri

    (str) –

    Repository URI.

  • readable

    (bool) –

    Whether the repository is readable by the client.

  • writable

    (bool) –

    Whether the repository is writable by the client.

  • title

    (str | None, default: None ) –

    Repository title.

Attributes:

identifier instance-attribute

identifier: str

readable instance-attribute

readable: bool

title class-attribute instance-attribute

title: str | None = None

uri instance-attribute

uri: str

writable instance-attribute

writable: bool

RepositoryManager

RepositoryManager(http_client: Client)

A client to manage server-level repository operations.

Parameters:

  • http_client

    (Client) –

    The httpx.Client instance.

Methods:

  • create

    Create a new repository.

  • delete

    Delete a repository.

  • get

    Get a repository by ID.

  • list

    List all available repositories.

Attributes:

Source code in rdflib/contrib/rdf4j/client.py
def __init__(self, http_client: httpx.Client):
    self._http_client = http_client

http_client property

http_client

create

create(repository_id: str, data: str, content_type: str = 'text/turtle') -> Repository

Create a new repository.

Parameters:

  • repository_id

    (str) –

    The identifier of the repository.

  • data

    (str) –

    The repository configuration in RDF.

  • content_type

    (str, default: 'text/turtle' ) –

    The repository configuration content type.

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def create(
    self, repository_id: str, data: str, content_type: str = "text/turtle"
) -> Repository:
    """Create a new repository.

    Parameters:
        repository_id: The identifier of the repository.
        data: The repository configuration in RDF.
        content_type: The repository configuration content type.

    Raises:
        RepositoryAlreadyExistsError: If the repository already exists.
        RepositoryNotHealthyError: If the repository is not healthy.
    """
    try:
        headers = {"Content-Type": content_type}
        response = self.http_client.put(
            f"/repositories/{repository_id}", headers=headers, content=data
        )
        response.raise_for_status()
        return self.get(repository_id)
    except httpx.HTTPStatusError as err:
        if err.response.status_code == 409:
            raise RepositoryAlreadyExistsError(
                f"Repository {repository_id} already exists."
            )
        raise

delete

delete(repository_id: str) -> None

Delete a repository.

Parameters:

  • repository_id

    (str) –

    The identifier of the repository.

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def delete(self, repository_id: str) -> None:
    """Delete a repository.

    Parameters:
        repository_id: The identifier of the repository.

    Raises:
        RepositoryNotFoundError: If the repository is not found.
        RepositoryError: If the repository is not deleted successfully.
    """
    try:
        response = self.http_client.delete(f"/repositories/{repository_id}")
        response.raise_for_status()
        if response.status_code != 204:
            raise RepositoryError(
                f"Unexpected response status code when deleting repository {repository_id}: {response.status_code} - {response.text.strip()}"
            )
    except httpx.HTTPStatusError as err:
        if err.response.status_code == 404:
            raise RepositoryNotFoundError(f"Repository {repository_id} not found.")
        raise

get

Get a repository by ID.

Note

This performs a health check before returning the repository object.

Parameters:

  • repository_id

    (str) –

    The identifier of the repository.

Returns:

  • Repository ( Repository ) –

    The repository instance.

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def get(self, repository_id: str) -> Repository:
    """Get a repository by ID.

    !!! Note
        This performs a health check before returning the repository object.

    Parameters:
        repository_id: The identifier of the repository.

    Returns:
        Repository: The repository instance.

    Raises:
        RepositoryNotFoundError: If the repository is not found.
        RepositoryNotHealthyError: If the repository is not healthy.
    """
    repo = Repository(repository_id, self.http_client)
    repo.health()
    return repo

list

List all available repositories.

Returns:

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def list(self) -> list[RepositoryListingResult]:
    """List all available repositories.

    Returns:
        list[RepositoryListingResult]: List of repository results.

    Raises:
        RepositoryResponseFormatError: If the response format is unrecognized.
    """
    headers = {
        "Accept": "application/sparql-results+json",
    }
    response = self.http_client.get("/repositories", headers=headers)
    response.raise_for_status()

    try:
        data = response.json()
        results = data["results"]["bindings"]
        return [
            RepositoryListingResult(
                identifier=repo["id"]["value"],
                uri=repo["uri"]["value"],
                readable=repo["readable"]["value"],
                writable=repo["writable"]["value"],
                title=repo.get("title", {}).get("value"),
            )
            for repo in results
        ]
    except (KeyError, ValueError) as err:
        raise RepositoryResponseFormatError(f"Unrecognised response format: {err}")

Transaction

Transaction(repo: Repository, url: str)

An RDF4J transaction.

Warning

Transaction instances are not thread-safe. Do not share a single Transaction instance across multiple threads. Each thread should create its own transaction, or use appropriate synchronization if sharing is required.

Parameters:

Methods:

  • __enter__
  • __exit__
  • commit

    Commit the transaction.

  • create

    Create a new transaction for the repository.

  • delete

    Delete statements from the repository.

  • get

    Get RDF statements from the repository matching the filtering parameters.

  • ping

    Ping the transaction.

  • query

    Execute a SPARQL query against the repository.

  • rollback

    Roll back the transaction.

  • size

    The number of statements in the repository or in the specified graph name.

  • update

    Execute a SPARQL update operation on the repository.

  • upload

    Upload and append statements to the repository.

Attributes:

  • is_closed (bool) –

    Whether the transaction is closed.

  • repo

    The repository instance.

  • url

    The transaction URL.

Source code in rdflib/contrib/rdf4j/client.py
def __init__(self, repo: Repository, url: str):
    self._repo = repo
    self._url: str = url
    self._closed: bool = False

is_closed property

is_closed: bool

Whether the transaction is closed.

repo property

repo

The repository instance.

url property

url

The transaction URL.

__enter__

__enter__()
Source code in rdflib/contrib/rdf4j/client.py
def __enter__(self):
    return self

__exit__

__exit__(exc_type, exc_val, exc_tb)
Source code in rdflib/contrib/rdf4j/client.py
def __exit__(self, exc_type, exc_val, exc_tb):
    if not self.is_closed:
        if exc_type is None:
            self.commit()
        else:
            try:
                self.rollback()
            except Exception:
                pass

    # Propagate errors.
    return False

commit

commit()

Commit the transaction.

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def commit(self):
    """Commit the transaction.

    Raises:
        TransactionCommitError: If the transaction commit fails.
        TransactionClosedError: If the transaction is closed.
    """
    self._raise_for_closed()
    params = {"action": "COMMIT"}
    response = self.repo.http_client.put(self.url, params=params)
    if response.status_code != 200:
        raise TransactionCommitError(
            f"Transaction commit failed: {response.status_code} - {response.text}"
        )
    self._closed = True

create classmethod

Create a new transaction for the repository.

Parameters:

Returns:

Source code in rdflib/contrib/rdf4j/client.py
@classmethod
def create(cls, repo: Repository) -> Transaction:
    """Create a new transaction for the repository.

    Parameters:
        repo: The repository instance.

    Returns:
        A new Transaction instance.
    """
    response = repo.http_client.post(
        f"/repositories/{repo.identifier}/transactions"
    )
    response.raise_for_status()
    url = response.headers["Location"]
    return cls(repo, url)

delete

delete(data: str | bytes | BinaryIO | Graph | Dataset, base_uri: str | None = None, content_type: str | None = None) -> None

Delete statements from the repository.

Note

This function operates differently to Repository.delete as it does not use filter parameters. Instead, it expects a data payload. See the notes from graphdb.js#Deleting for more information.

Parameters:

  • data

    (str | bytes | BinaryIO | Graph | Dataset) –

    The RDF data to upload.

  • base_uri

    (str | None, default: None ) –

    The base URI to resolve against for any relative URIs in the data.

  • content_type

    (str | None, default: None ) –

    The content type of the data. Defaults to application/n-quads when the value is None.

Source code in rdflib/contrib/rdf4j/client.py
def delete(
    self,
    data: str | bytes | BinaryIO | Graph | Dataset,
    base_uri: str | None = None,
    content_type: str | None = None,
) -> None:
    """Delete statements from the repository.

    !!! Note
        This function operates differently to
        [`Repository.delete`][rdflib.contrib.rdf4j.client.Repository.delete]
        as it does not use filter parameters. Instead, it expects a data payload.
        See the notes from
        [graphdb.js#Deleting](https://github.com/Ontotext-AD/graphdb.js?tab=readme-ov-file#deleting-1)
        for more information.

    Parameters:
        data: The RDF data to upload.
        base_uri: The base URI to resolve against for any relative URIs in the data.
        content_type: The content type of the data. Defaults to
            `application/n-quads` when the value is `None`.
    """
    self._raise_for_closed()
    params: dict[str, str] = {"action": "DELETE"}
    stream, should_close = rdf_payload_to_stream(data)
    headers = {"Content-Type": content_type or "application/n-quads"}
    if base_uri is not None:
        params["baseURI"] = base_uri
    try:
        response = self.repo.http_client.put(
            self.url,
            headers=headers,
            params=params,
            content=stream,
        )
        response.raise_for_status()
    finally:
        if should_close:
            stream.close()

get

get(subj: SubjectType = None, pred: PredicateType = None, obj: ObjectType = None, graph_name: URIRef | Iterable[URIRef] | str | None = None, infer: bool = True, content_type: str | None = None) -> Graph | Dataset

Get RDF statements from the repository matching the filtering parameters.

Note

The terms for subj, pred, obj or graph_name cannot be BNodes.

Parameters:

  • subj

    (SubjectType, default: None ) –

    Subject of the statement to filter by, or None to match all.

  • pred

    (PredicateType, default: None ) –

    Predicate of the statement to filter by, or None to match all.

  • obj

    (ObjectType, default: None ) –

    Object of the statement to filter by, or None to match all.

  • graph_name

    (URIRef | Iterable[URIRef] | str | None, default: None ) –

    Graph name(s) to restrict to.

    The default value None queries all graphs.

    To query just the default graph, use DATASET_DEFAULT_GRAPH_ID.

  • infer

    (bool, default: True ) –

    Specifies whether inferred statements should be included in the result.

  • content_type

    (str | None, default: None ) –

    The content type of the response. A triple-based format returns a Graph, while a quad-based format returns a Dataset.

Returns:

Source code in rdflib/contrib/rdf4j/client.py
def get(
    self,
    subj: SubjectType = None,
    pred: PredicateType = None,
    obj: ObjectType = None,
    graph_name: URIRef | Iterable[URIRef] | str | None = None,
    infer: bool = True,
    content_type: str | None = None,
) -> Graph | Dataset:
    """Get RDF statements from the repository matching the filtering parameters.

    !!! Note
        The terms for `subj`, `pred`, `obj` or `graph_name` cannot be
        [`BNodes`][rdflib.term.BNode].

    Parameters:
        subj: Subject of the statement to filter by, or `None` to match all.
        pred: Predicate of the statement to filter by, or `None` to match all.
        obj: Object of the statement to filter by, or `None` to match all.
        graph_name: Graph name(s) to restrict to.

            The default value `None` queries all graphs.

            To query just the default graph, use
            [`DATASET_DEFAULT_GRAPH_ID`][rdflib.graph.DATASET_DEFAULT_GRAPH_ID].

        infer: Specifies whether inferred statements should be included in the
            result.
        content_type: The content type of the response.
            A triple-based format returns a [Graph][rdflib.graph.Graph], while a
            quad-based format returns a [`Dataset`][rdflib.graph.Dataset].

    Returns:
        A [`Graph`][rdflib.graph.Graph] or [`Dataset`][rdflib.graph.Dataset] object
            with the repository namespace prefixes bound to it.
    """
    self._raise_for_closed()
    validate_no_bnodes(subj, pred, obj, graph_name)
    if content_type is None:
        content_type = "application/n-quads"
    headers = {"Accept": content_type}
    params: dict[str, str] = {"action": "GET"}
    build_context_param(params, graph_name)
    build_spo_param(params, subj, pred, obj)
    build_infer_param(params, infer=infer)

    response = self.repo.http_client.put(
        self.url,
        headers=headers,
        params=params,
    )
    response.raise_for_status()
    triple_formats = [
        "application/n-triples",
        "text/turtle",
        "application/rdf+xml",
    ]
    try:
        if content_type in triple_formats:
            retval = Graph().parse(data=response.text, format=content_type)
        else:
            retval = Dataset().parse(data=response.text, format=content_type)
        for result in self.repo.namespaces.list():
            retval.bind(result.prefix, result.namespace, replace=True)
        return retval
    except Exception as err:
        raise RDFLibParserError(f"Error parsing RDF: {err}") from err

ping

ping()

Ping the transaction.

Raises:

  • RepositoryTransactionPingError

    If the transaction ping fails.

  • TransactionClosedError

    If the transaction is closed.

Source code in rdflib/contrib/rdf4j/client.py
def ping(self):
    """Ping the transaction.

    Raises:
        RepositoryTransactionPingError: If the transaction ping fails.
        TransactionClosedError: If the transaction is closed.
    """
    self._raise_for_closed()
    params = {"action": "PING"}
    response = self.repo.http_client.put(self.url, params=params)
    if response.status_code != 200:
        raise TransactionPingError(
            f"Transaction ping failed: {response.status_code} - {response.text}"
        )

query

query(query: str, **kwargs)

Execute a SPARQL query against the repository.

Parameters:

  • query

    (str) –

    The SPARQL query to execute.

  • **kwargs

    Additional keyword arguments to include as query parameters in the request. See RDF4J REST API - Execute SPARQL query for the list of supported query parameters.

Source code in rdflib/contrib/rdf4j/client.py
def query(self, query: str, **kwargs):
    """Execute a SPARQL query against the repository.

    Parameters:
        query: The SPARQL query to execute.
        **kwargs: Additional keyword arguments to include as query parameters
            in the request. See
            [RDF4J REST API - Execute SPARQL query](https://rdf4j.org/documentation/reference/rest-api/#tag/SPARQL/paths/~1repositories~1%7BrepositoryID%7D/get)
            for the list of supported query parameters.
    """
    self._raise_for_closed()
    headers: dict[str, str] = {}
    build_sparql_query_accept_header(query, headers)
    params = {"action": "QUERY", "query": query}
    response = self.repo.http_client.put(
        self.url, headers=headers, params={**params, **kwargs}
    )
    response.raise_for_status()
    try:
        return Result.parse(
            io.BytesIO(response.content),
            content_type=response.headers["Content-Type"].split(";")[0],
        )
    except KeyError as err:
        raise RDFLibParserError(
            f"Failed to parse SPARQL query result {response.headers.get('Content-Type')}: {err}"
        ) from err

rollback

rollback()

Roll back the transaction.

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def rollback(self):
    """Roll back the transaction.

    Raises:
        TransactionRollbackError: If the transaction rollback fails.
        TransactionClosedError: If the transaction is closed.
    """
    self._raise_for_closed()
    response = self.repo.http_client.delete(self.url)
    if response.status_code != 204:
        raise TransactionRollbackError(
            f"Transaction rollback failed: {response.status_code} - {response.text}"
        )
    self._closed = True

size

size(graph_name: URIRef | Iterable[URIRef] | str | None = None)

The number of statements in the repository or in the specified graph name.

Parameters:

  • graph_name

    (URIRef | Iterable[URIRef] | str | None, default: None ) –

    Graph name(s) to restrict to.

    The default value None queries all graphs.

    To query just the default graph, use DATASET_DEFAULT_GRAPH_ID.

Returns:

  • The number of statements.

Raises:

Source code in rdflib/contrib/rdf4j/client.py
def size(self, graph_name: URIRef | Iterable[URIRef] | str | None = None):
    """The number of statements in the repository or in the specified graph name.

    Parameters:
        graph_name: Graph name(s) to restrict to.

            The default value `None` queries all graphs.

            To query just the default graph, use
            [`DATASET_DEFAULT_GRAPH_ID`][rdflib.graph.DATASET_DEFAULT_GRAPH_ID].

    Returns:
        The number of statements.

    Raises:
        RepositoryResponseFormatError: Fails to parse the repository size.
    """
    self._raise_for_closed()
    validate_graph_name(graph_name)
    params = {"action": "SIZE"}
    build_context_param(params, graph_name)
    response = self.repo.http_client.put(self.url, params=params)
    response.raise_for_status()
    return self.repo._to_size(response.text)

update

update(query: str, **kwargs)

Execute a SPARQL update operation on the repository.

Parameters:

Source code in rdflib/contrib/rdf4j/client.py
def update(self, query: str, **kwargs):
    """Execute a SPARQL update operation on the repository.

    Parameters:
        query: The SPARQL update query to execute.
        **kwargs: Additional keyword arguments to include as query parameters
            See [RDF4J REST API - Execute a transaction action](https://rdf4j.org/documentation/reference/rest-api/#tag/Transactions/paths/~1repositories~1%7BrepositoryID%7D~1transactions~1%7BtransactionID%7D/put)
            for the list of supported query parameters.
    """
    self._raise_for_closed()
    params = {"action": "UPDATE", "update": query}
    response = self.repo.http_client.put(
        self.url,
        params={**params, **kwargs},
    )
    response.raise_for_status()

upload

upload(data: str | bytes | BinaryIO | Graph | Dataset, base_uri: str | None = None, content_type: str | None = None)

Upload and append statements to the repository.

Parameters:

  • data

    (str | bytes | BinaryIO | Graph | Dataset) –

    The RDF data to upload.

  • base_uri

    (str | None, default: None ) –

    The base URI to resolve against for any relative URIs in the data.

  • content_type

    (str | None, default: None ) –

    The content type of the data. Defaults to application/n-quads when the value is None.

Source code in rdflib/contrib/rdf4j/client.py
def upload(
    self,
    data: str | bytes | BinaryIO | Graph | Dataset,
    base_uri: str | None = None,
    content_type: str | None = None,
):
    """Upload and append statements to the repository.

    Parameters:
        data: The RDF data to upload.
        base_uri: The base URI to resolve against for any relative URIs in the data.
        content_type: The content type of the data. Defaults to
            `application/n-quads` when the value is `None`.
    """
    self._raise_for_closed()
    stream, should_close = rdf_payload_to_stream(data)
    headers = {"Content-Type": content_type or "application/n-quads"}
    params = {"action": "ADD"}
    if base_uri is not None:
        params["baseURI"] = base_uri
    try:
        response = self.repo.http_client.put(
            self.url,
            headers=headers,
            params=params,
            content=stream,
        )
        response.raise_for_status()
    finally:
        if should_close:
            stream.close()