import pathlib
from typing import (
    IO,
    Any,
    Iterable,
    Iterator,
    List,
    Optional,
    Set,
    Tuple,
    Union,
    overload,
)

from rdflib import query
from rdflib.collection import Collection
from rdflib.paths import Path
from rdflib.resource import Resource
from rdflib.term import BNode, Identifier, Node

class Graph(Node):
    base: Any = ...
    context_aware: bool = ...
    formula_aware: bool = ...
    default_union: bool = ...
    def __init__(
        self,
        store: str = ...,
        identifier: Optional[Any] = ...,
        namespace_manager: Optional[Any] = ...,
        base: Optional[Any] = ...,
    ) -> None: ...
    store: Any = ...
    identifier: Any = ...
    namespace_manager: Any = ...
    def toPython(self) -> str: ...
    def destroy(self, configuration: Any) -> None: ...
    def commit(self) -> None: ...
    def rollback(self) -> None: ...
    def open(self, configuration: Any, create: bool = ...) -> Any: ...
    def close(self, commit_pending_transaction: bool = ...) -> None: ...
    def add(self, triple: Any) -> None: ...
    def addN(self, quads: Any) -> None: ...
    def remove(self, triple: Any) -> None: ...
    def triples(
        self,
        triple: Tuple[
            Optional[Union[str, Identifier]],
            Optional[Union[str, Identifier]],
            Optional[Identifier],
        ],
    ) -> Iterator[Tuple[Identifier, Identifier, Identifier]]: ...
    def __getitem__(
        self, item: slice | Path | Node
    ) -> Iterator[
        Tuple[Identifier, Identifier, Identifier] | Tuple[Identifier, identifier] | Node
    ]: ...
    def __contains__(self, triple: Any) -> bool: ...
    def __add__(self, other: Any) -> Graph: ...
    def set(self, triple: Any) -> None: ...
    def subjects(
        self, predicate: Optional[Any] = ..., object: Optional[Any] = ...
    ) -> Iterable[Node]: ...
    def predicates(
        self, subject: Optional[Any] = ..., object: Optional[Any] = ...
    ) -> Iterable[Node]: ...
    def objects(
        self, subject: Optional[Any] = ..., predicate: Optional[Any] = ...
    ) -> Iterable[Identifier]: ...
    def subject_predicates(self, object: Optional[Any] = ...) -> None: ...
    def subject_objects(self, predicate: Optional[Any] = ...) -> None: ...
    def predicate_objects(self, subject: Optional[Any] = ...) -> None: ...
    def triples_choices(self, triple: Any, context: Optional[Any] = ...) -> None: ...
    def value(
        self,
        subject: Optional[Any] = ...,
        predicate: Any = ...,
        object: Optional[Any] = ...,
        default: Optional[Any] = ...,
        any: bool = ...,
    ) -> Any: ...
    def label(self, subject: Any, default: str = ...) -> Any: ...
    def preferredLabel(
        self,
        subject: Any,
        lang: Optional[Any] = ...,
        default: Optional[Any] = ...,
        labelProperties: Any = ...,
    ) -> List[Tuple[Any, Any]]: ...
    def comment(self, subject: Any, default: str = ...) -> Any: ...
    def items(self, list: Any) -> Iterator[Any]: ...
    def transitiveClosure(
        self, func: Any, arg: Any, seen: Optional[Any] = ...
    ) -> Iterator[Any]: ...
    def transitive_objects(
        self, subject: Any, property: Any, remember: Optional[Any] = ...
    ) -> Iterator[Any]: ...
    def transitive_subjects(
        self, predicate: Any, object: Any, remember: Optional[Any] = ...
    ) -> Iterator[Any]: ...
    def seq(self, subject: Any) -> Seq | None: ...
    def qname(self, uri: Any) -> Any: ...
    def compute_qname(self, uri: Any, generate: bool = ...) -> Any: ...
    def bind(
        self, prefix: Any, namespace: Any, override: bool = ..., replace: bool = ...
    ) -> Any: ...
    def namespaces(self) -> Iterator[Tuple[Any, Any]]: ...
    def absolutize(self, uri: Any, defrag: int = ...) -> Any: ...

    # no destination and non-None positional encoding
    @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 parse(
        self,
        source: Optional[Any] = ...,
        publicID: Optional[Any] = ...,
        format: Optional[str] = ...,
        location: Optional[Any] = ...,
        file: Optional[Any] = ...,
        data: Optional[Any] = ...,
        **args: Any,
    ) -> "Graph": ...
    def load(self, source: Any, publicID: Optional[Any] = ..., format: str = ...) -> "Graph": ...
    def query(
        self,
        query_object: Any,
        processor: str = ...,
        result: str = ...,
        initNs: Optional[Any] = ...,
        initBindings: Optional[Any] = ...,
        use_store_provided: bool = ...,
        **kwargs: Any,
    ) -> query.Result: ...
    def update(
        self,
        update_object: Any,
        processor: str = ...,
        initNs: Optional[Any] = ...,
        initBindings: Optional[Any] = ...,
        use_store_provided: bool = ...,
        **kwargs: Any,
    ) -> Any: ...
    def n3(self) -> str: ...
    def isomorphic(self, other: Any) -> bool: ...
    def connected(self) -> bool: ...
    def all_nodes(self) -> Set[Any]: ...
    def collection(self, identifier: Any) -> Collection: ...
    def resource(self, identifier: Any) -> Resource: ...
    def skolemize(
        self,
        new_graph: Optional[Any] = ...,
        bnode: Optional[Any] = ...,
        authority: Optional[Any] = ...,
        basepath: Optional[Any] = ...,
    ) -> Graph: ...
    def de_skolemize(
        self, new_graph: Optional[Any] = ..., uriref: Optional[Any] = ...
    ) -> Graph: ...

class ConjunctiveGraph(Graph):
    context_aware: bool = ...
    default_union: bool = ...
    default_context: Any = ...
    def __init__(
        self,
        store: str = ...,
        identifier: Optional[Any] = ...,
        default_graph_base: Optional[Any] = ...,
    ) -> None: ...
    def add(self, triple_or_quad: Any) -> None: ...
    def addN(self, quads: Any) -> None: ...
    def remove(self, triple_or_quad: Any) -> None: ...
    # def triples(self, triple_or_quad: Tuple[Optional[Union[str, BNode]], Optional[Union[str, BNode]], Optional[BNode]], context: Tuple[Optional[Union[str, BNode]], Optional[Union[str, BNode]], Optional[BNode]]) -> Iterator[Tuple[Identifier, Identifier, Identifier]]: ...
    def quads(self, triple_or_quad: Optional[Any] = ...) -> None: ...
    def triples_choices(self, triple: Any, context: Optional[Any] = ...) -> None: ...
    def contexts(self, triple: Optional[Any] = ...) -> None: ...
    def get_context(
        self,
        identifier: Node | str | None,
        quoted: bool = ...,
        base: Optional[str] = ...,
    ) -> Graph: ...
    def remove_context(self, context: Any) -> None: ...
    def context_id(self, uri: Any, context_id: Optional[Any] = ...) -> Any: ...
    def parse(
        self,
        source: Optional[Any] = ...,
        publicID: Optional[Any] = ...,
        format: Optional[str] = ...,
        location: Optional[Any] = ...,
        file: Optional[Any] = ...,
        data: Optional[Any] = ...,
        **args: Any,
    ) -> Graph: ...

class Seq:
    def __init__(self, graph: Graph, subject: Any) -> None: ...
    def toPython(self) -> Seq: ...
