Skip to content

Commit

Permalink
Additional fixes
Browse files Browse the repository at this point in the history
Changed type hints based on more information discovered in mean time.
  • Loading branch information
aucampia committed May 21, 2022
1 parent da12e20 commit 4a7ea04
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 53 deletions.
105 changes: 73 additions & 32 deletions rdflib/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,29 @@
from rdflib.resource import Resource
from rdflib.serializer import Serializer
from rdflib.store import Store
from rdflib.term import (
BNode,
Genid,
IdentifiedNode,
Identifier,
Literal,
Node,
RDFLibGenid,
URIRef,
)
from rdflib.term import BNode, Genid, IdentifiedNode, Literal, Node, RDFLibGenid, URIRef

_SubjectType = IdentifiedNode
_PredicateType = IdentifiedNode
_ObjectType = Identifier
_SubjectType = Node
_PredicateType = Node
_ObjectType = Node

_TripleType = Tuple["_SubjectType", "_PredicateType", "_ObjectType"]
_QuadType = Tuple["_SubjectType", "_PredicateType", "_ObjectType", "Graph"]
_OptionalQuadType = Tuple[
"_SubjectType", "_PredicateType", "_ObjectType", Optional["Graph"]
]
_OptionalIdentifiedQuadType = Tuple[
"_SubjectType", "_PredicateType", "_ObjectType", Optional["Node"]
]
_TriplePatternType = Tuple[
Optional["_SubjectType"], Optional["_PredicateType"], Optional["_ObjectType"]
]
_QuadPatternType = Tuple[
Optional["_SubjectType"],
Optional["_PredicateType"],
Optional["_ObjectType"],
Optional["Graph"],
]
_GraphT = TypeVar("_GraphT", bound="Graph")

assert Literal # avoid warning
Expand Down Expand Up @@ -455,7 +458,7 @@ def add(self, triple: "_TripleType"):
self.__store.add((s, p, o), self, quoted=False)
return self

def addN(self, quads: Iterable["_QuadType"]):
def addN(self, quads: Iterable["_QuadType"]): # noqa: N802
"""Add a sequence of triple with context"""

self.__store.addN(
Expand Down Expand Up @@ -523,7 +526,9 @@ def triples(
for _s, _o in p.eval(self, s, o):
yield _s, p, _o
else:
for (_s, _p, _o), cg in self.__store.triples((s, p, o), context=self):
# type error: Argument 1 to "triples" of "Store" has incompatible type "Tuple[Optional[Node], Optional[Node], Optional[Node]]"; expected "Tuple[Optional[IdentifiedNode], Optional[IdentifiedNode], Optional[Node]]"
# NOTE on type error: This is because the store typing is too narrow, willbe fixed in subsequent PR.
for (_s, _p, _o), cg in self.__store.triples((s, p, o), context=self): # type: ignore [arg-type]
yield _s, _p, _o

def __getitem__(self, item):
Expand Down Expand Up @@ -1671,11 +1676,21 @@ def __str__(self):
def _spoc(
self,
triple_or_quad: Union[
Tuple["_SubjectType", "_PredicateType", "_ObjectType", Optional[Any]],
"_TripleType",
Tuple[
Optional["_SubjectType"],
Optional["_PredicateType"],
Optional["_ObjectType"],
Optional[Any],
],
"_TriplePatternType",
],
default: bool = False,
) -> Tuple["_SubjectType", "_PredicateType", "_ObjectType", Optional[Graph]]:
) -> Tuple[
Optional["_SubjectType"],
Optional["_PredicateType"],
Optional["_ObjectType"],
Optional[Graph],
]:
...

@overload
Expand All @@ -1690,8 +1705,13 @@ def _spoc(
self,
triple_or_quad: Optional[
Union[
Tuple["_SubjectType", "_PredicateType", "_ObjectType", Optional[Any]],
"_TripleType",
Tuple[
Optional["_SubjectType"],
Optional["_PredicateType"],
Optional["_ObjectType"],
Optional[Any],
],
"_TriplePatternType",
]
],
default: bool = False,
Expand Down Expand Up @@ -1739,7 +1759,8 @@ def add(

_assertnode(s, p, o)

self.store.add((s, p, o), context=c, quoted=False)
# type error: Argument "context" to "add" of "Store" has incompatible type "Optional[Graph]"; expected "Graph"
self.store.add((s, p, o), context=c, quoted=False) # type: ignore[arg-type]
return self

@overload
Expand All @@ -1758,7 +1779,7 @@ def _graph(self, c: Optional[Union[Graph, Node, str]]) -> Optional[Graph]:
else:
return c

def addN(self, quads: Iterable["_QuadType"]):
def addN(self, quads: Iterable["_QuadType"]): # noqa: N802
"""Add a sequence of triples with context"""

self.store.addN(
Expand Down Expand Up @@ -1809,14 +1830,24 @@ def triples(self, triple_or_quad, context=None):
for (s, p, o), cg in self.store.triples((s, p, o), context=context):
yield s, p, o

def quads(self, triple_or_quad=None):
def quads(
self,
triple_or_quad: Union[
"_TriplePatternType",
"_QuadPatternType",
None,
] = None,
) -> Generator[_OptionalQuadType, None, None]:
"""Iterate over all the quads in the entire conjunctive graph"""

s, p, o, c = self._spoc(triple_or_quad)

for (s, p, o), cg in self.store.triples((s, p, o), context=c):
# type error: Argument 1 to "triples" of "Store" has incompatible type "Tuple[Optional[Node], Optional[Node], Optional[Node]]"; expected "Tuple[Optional[IdentifiedNode], Optional[IdentifiedNode], Optional[Node]]"
# NOTE on type error: This is because the store typing is too narrow, willbe fixed in subsequent PR.
for (s, p, o), cg in self.store.triples((s, p, o), context=c): # type: ignore[arg-type]
for ctx in cg:
yield s, p, o, ctx
# type error: Incompatible types in "yield" (actual type "Tuple[Optional[Node], Optional[Node], Optional[Node], Any]", expected type "Tuple[Node, Node, Node, Optional[Graph]]")
yield s, p, o, ctx # type: ignore[misc]

def triples_choices(self, triple, context=None):
"""Iterate over all the triples in the entire conjunctive graph"""
Expand Down Expand Up @@ -2146,17 +2177,27 @@ def contexts(self, triple=None):

graphs = contexts

def quads(self, quad):
# 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]
self,
quad: Union[
"_TriplePatternType",
"_QuadPatternType",
None,
] = None,
) -> Generator[_OptionalIdentifiedQuadType, None, None]:
for s, p, o, c in super(Dataset, self).quads(quad):
if c.identifier == self.default_context:
# type error: Item "None" of "Optional[Graph]" has no attribute "identifier"
if c.identifier == self.default_context: # type: ignore[union-attr]
yield s, p, o, None
else:
yield s, p, o, c.identifier
# type error: Item "None" of "Optional[Graph]" has no attribute "identifier" [union-attr]
yield s, p, o, c.identifier # type: ignore[union-attr]

# type error: Return type "Generator[Tuple[Node, URIRef, Node, Optional[IdentifiedNode]], None, None]" of "__iter__" incompatible with return type "Generator[Tuple[IdentifiedNode, IdentifiedNode, Union[IdentifiedNode, Literal]], None, None]" in supertype "Graph"
def __iter__( # type: ignore[override]
self,
) -> Generator[Tuple[Node, URIRef, Node, Optional[IdentifiedNode]], None, None]:
) -> Generator[_OptionalIdentifiedQuadType, None, None]:
"""Iterates over all quads in the store"""
return self.quads((None, None, None, None))

Expand All @@ -2182,7 +2223,7 @@ def add(self, triple: "_TripleType"):
self.store.add((s, p, o), self, quoted=True)
return self

def addN(self, quads: Iterable["_QuadType"]) -> "QuotedGraph":
def addN(self, quads: Iterable["_QuadType"]) -> "QuotedGraph": # noqa: N802
"""Add a sequence of triple with context"""

self.store.addN(
Expand Down Expand Up @@ -2332,7 +2373,7 @@ def close(self):
def add(self, triple):
raise ModificationException()

def addN(self, quads):
def addN(self, quads): # noqa: N802
raise ModificationException()

def remove(self, triple):
Expand Down Expand Up @@ -2505,7 +2546,7 @@ def add(
self.batch.append(triple_or_quad)
return self

def addN(self, quads: Iterable["_QuadType"]):
def addN(self, quads: Iterable["_QuadType"]): # noqa: N802
if self.__batch_addn:
for q in quads:
self.add(q)
Expand Down
2 changes: 1 addition & 1 deletion rdflib/plugins/parsers/ntriples.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from rdflib.exceptions import ParserError as ParseError
from rdflib.parser import InputSource, Parser
from rdflib.term import BNode as bNode
from rdflib.term import Literal, Node
from rdflib.term import Literal
from rdflib.term import URIRef as URI

if TYPE_CHECKING:
Expand Down
6 changes: 4 additions & 2 deletions rdflib/plugins/serializers/rdfxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ def serialize(

subject: IdentifiedNode
# Write out subjects that can not be inline
for subject in store.subjects():
# type error: Incompatible types in assignment (expression has type "Node", variable has type "IdentifiedNode")
for subject in store.subjects(): # type: ignore[assignment]
if (None, None, subject) in store:
if (subject, None, subject) in store:
self.subject(subject, 1)
Expand All @@ -218,7 +219,8 @@ def serialize(
# write out BNodes last (to ensure they can be inlined where possible)
bnodes = set()

for subject in store.subjects():
# type error: Incompatible types in assignment (expression has type "Node", variable has type "IdentifiedNode")
for subject in store.subjects(): # type: ignore[assignment]
if isinstance(subject, BNode):
bnodes.add(subject)
continue
Expand Down
14 changes: 7 additions & 7 deletions rdflib/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
Any,
Callable,
Iterable,
Iterator,
List,
Optional,
Set,
Expand Down Expand Up @@ -409,13 +410,13 @@ def find_roots(

def get_tree(
graph: "Graph",
root: "IdentifiedNode",
root: "Node",
prop: "URIRef",
mapper: Callable[["IdentifiedNode"], "IdentifiedNode"] = lambda x: x,
mapper: Callable[["Node"], "Node"] = lambda x: x,
sortkey: Optional[Callable[[Any], Any]] = None,
done: Optional[Set["IdentifiedNode"]] = None,
done: Optional[Set["Node"]] = None,
dir: str = "down",
) -> Optional[Tuple[IdentifiedNode, List[Any]]]:
) -> Optional[Tuple[Node, List[Any]]]:
"""
Return a nested list/tuple structure representing the tree
built by the transitive property given, starting from the root given
Expand All @@ -442,12 +443,11 @@ def get_tree(
done.add(root)
tree = []

branches: Iterable[IdentifiedNode]
branches: Iterator[Node]
if dir == "down":
branches = graph.subjects(prop, root)
else:
# type error: Incompatible types in assignment (expression has type "Iterable[Node]", variable has type "Iterable[IdentifiedNode]")
branches = graph.objects(root, prop) # type: ignore[assignment]
branches = graph.objects(root, prop)

for branch in branches:
t = get_tree(graph, branch, prop, mapper, sortkey, done, dir)
Expand Down
2 changes: 0 additions & 2 deletions test/test_graph/test_canonicalization.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import unittest
from collections import Counter
from io import StringIO
from test.testutils import GraphHelper
from test.utils import GraphHelper
from typing import TYPE_CHECKING, Set

Expand All @@ -12,7 +11,6 @@
from rdflib.compare import to_canonical_graph, to_isomorphic
from rdflib.namespace import FOAF
from rdflib.plugins.stores.memory import Memory
from rdflib.term import Node

if TYPE_CHECKING:
from rdflib.graph import _TripleType
Expand Down
1 change: 0 additions & 1 deletion test/test_graph/test_diff.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import unittest
from test.testutils import GraphHelper
from test.utils import GraphHelper
from typing import TYPE_CHECKING, Set
from unittest.case import expectedFailure
Expand Down
2 changes: 1 addition & 1 deletion test/test_namespace/test_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ def test_expand_curie_exception_messages(self) -> None:
assert str(e.value) == "Argument must be a string, not BNode."

with pytest.raises(TypeError) as e:
assert g.namespace_manager.expand_curie(Graph()) == None
assert g.namespace_manager.expand_curie(Graph()) == None # type: ignore[arg-type]
assert str(e.value) == "Argument must be a string, not Graph."

@pytest.mark.parametrize(
Expand Down
6 changes: 4 additions & 2 deletions test/test_roundtrip.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,12 @@ def roundtrip(
#
# So we have to scrub the literals' string datatype declarations...
for c in g2.contexts():
for s, p, o in c.triples((None, None, None)):
# type error: Incompatible types in assignment (expression has type "Node", variable has type "str")
for s, p, o in c.triples((None, None, None)): # type: ignore[assignment]
if type(o) == rdflib.Literal and o.datatype == XSD.string:
c.remove((s, p, o))
c.add((s, p, rdflib.Literal(str(o))))
# type error: Argument 1 to "add" of "Graph" has incompatible type "Tuple[str, Node, Literal]"; expected "Tuple[Node, Node, Node]"
c.add((s, p, rdflib.Literal(str(o)))) # type: ignore[arg-type]

if logger.isEnabledFor(logging.DEBUG):
both, first, second = rdflib.compare.graph_diff(g1, g2)
Expand Down
7 changes: 5 additions & 2 deletions test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@

from typing import Set, Tuple

import rdflib

# TODO Bug - rdflib.plugins.sparql.prepareQuery() will run fine if this
# test is run, but mypy can't tell the symbol is exposed.
import rdflib.plugins.sparql.processor
from rdflib.term import Node


def test_rdflib_query_exercise() -> None:
Expand Down Expand Up @@ -56,8 +59,8 @@ def test_rdflib_query_exercise() -> None:
graph.add((kb_https_uriref, predicate_q, literal_two))
graph.add((kb_bnode, predicate_p, literal_one))

expected_nodes_using_predicate_q: Set[rdflib.IdentifiedNode] = {kb_https_uriref}
computed_nodes_using_predicate_q: Set[rdflib.IdentifiedNode] = set()
expected_nodes_using_predicate_q: Set[Node] = {kb_https_uriref}
computed_nodes_using_predicate_q: Set[Node] = set()
for triple in graph.triples((None, predicate_q, None)):
computed_nodes_using_predicate_q.add(triple[0])
assert expected_nodes_using_predicate_q == computed_nodes_using_predicate_q
Expand Down
9 changes: 6 additions & 3 deletions test/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,15 @@ def quad_set(
"""
result: GHQuadSet = set()
for sn, pn, on, gn in graph.quads((None, None, None, None)):
gn_id: Identifier
if isinstance(graph, Dataset):
assert isinstance(gn, Identifier)
gn_id = gn
# type error: Subclass of "Graph" and "Identifier" cannot exist: would have incompatible method signatures
assert isinstance(gn, Identifier) # type: ignore[unreachable]
gn_id = gn # type: ignore[unreachable]
elif isinstance(graph, ConjunctiveGraph):
assert isinstance(gn, Graph)
gn_id = gn.identifier
# type error: Incompatible types in assignment (expression has type "Node", variable has type "Identifier")
gn_id = gn.identifier # type: ignore[assignment]
else:
raise ValueError(f"invalid graph type {type(graph)}: {graph!r}")
s, p, o = cls.nodes((sn, pn, on), exclude_blanks)
Expand Down

0 comments on commit 4a7ea04

Please sign in to comment.