Skip to content

Commit d556375

Browse files
committed
Add type hints
This commit only adds type hints and comments and does not make any changes that should affect runtime. The type hints added here derive from work done for RDFLib#1418.
1 parent 1729243 commit d556375

File tree

18 files changed

+350
-144
lines changed

18 files changed

+350
-144
lines changed

rdflib/graph.py

Lines changed: 112 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
from typing import Optional, Union, Type, cast, overload, Generator, Tuple
1+
from typing import (
2+
IO,
3+
Any,
4+
Iterable,
5+
Optional,
6+
Union,
7+
Type,
8+
cast,
9+
overload,
10+
Generator,
11+
Tuple,
12+
)
213
import logging
314
from warnings import warn
415
import random
@@ -21,7 +32,7 @@
2132
import tempfile
2233
import pathlib
2334

24-
from io import BytesIO, BufferedIOBase
35+
from io import BytesIO
2536
from urllib.parse import urlparse
2637

2738
assert Literal # avoid warning
@@ -313,15 +324,19 @@ class Graph(Node):
313324
"""
314325

315326
def __init__(
316-
self, store="default", identifier=None, namespace_manager=None, base=None
327+
self,
328+
store: Union[Store, str] = "default",
329+
identifier: Optional[Union[Node, str]] = None,
330+
namespace_manager: Optional[NamespaceManager] = None,
331+
base: Optional[str] = None,
317332
):
318333
super(Graph, self).__init__()
319334
self.base = base
320-
self.__identifier = identifier or BNode()
321-
335+
self.__identifier: Node
336+
self.__identifier = identifier or BNode() # type: ignore[assignment]
322337
if not isinstance(self.__identifier, Node):
323-
self.__identifier = URIRef(self.__identifier)
324-
338+
self.__identifier = URIRef(self.__identifier) # type: ignore[unreachable]
339+
self.__store: Store
325340
if not isinstance(store, Store):
326341
# TODO: error handling
327342
self.__store = store = plugin.get(store, Store)()
@@ -404,7 +419,7 @@ def close(self, commit_pending_transaction=False):
404419
"""
405420
return self.__store.close(commit_pending_transaction=commit_pending_transaction)
406421

407-
def add(self, triple):
422+
def add(self, triple: Tuple[Node, Node, Node]):
408423
"""Add a triple with self as context"""
409424
s, p, o = triple
410425
assert isinstance(s, Node), "Subject %s must be an rdflib term" % (s,)
@@ -413,7 +428,7 @@ def add(self, triple):
413428
self.__store.add((s, p, o), self, quoted=False)
414429
return self
415430

416-
def addN(self, quads):
431+
def addN(self, quads: Iterable[Tuple[Node, Node, Node, Any]]):
417432
"""Add a sequence of triple with context"""
418433

419434
self.__store.addN(
@@ -434,7 +449,9 @@ def remove(self, triple):
434449
self.__store.remove(triple, context=self)
435450
return self
436451

437-
def triples(self, triple):
452+
def triples(
453+
self, triple: Tuple[Optional[Node], Union[None, Path, Node], Optional[Node]]
454+
):
438455
"""Generator over the triple store
439456
440457
Returns triples that match the given triple pattern. If triple pattern
@@ -652,17 +669,17 @@ def set(self, triple):
652669
self.add((subject, predicate, object_))
653670
return self
654671

655-
def subjects(self, predicate=None, object=None):
672+
def subjects(self, predicate=None, object=None) -> Iterable[Node]:
656673
"""A generator of subjects with the given predicate and object"""
657674
for s, p, o in self.triples((None, predicate, object)):
658675
yield s
659676

660-
def predicates(self, subject=None, object=None):
677+
def predicates(self, subject=None, object=None) -> Iterable[Node]:
661678
"""A generator of predicates with the given subject and object"""
662679
for s, p, o in self.triples((subject, None, object)):
663680
yield p
664681

665-
def objects(self, subject=None, predicate=None):
682+
def objects(self, subject=None, predicate=None) -> Iterable[Node]:
666683
"""A generator of objects with the given subject and predicate"""
667684
for s, p, o in self.triples((subject, predicate, None)):
668685
yield o
@@ -1011,53 +1028,45 @@ def absolutize(self, uri, defrag=1):
10111028
# no destination and non-None positional encoding
10121029
@overload
10131030
def serialize(
1014-
self, destination: None, format: str, base: Optional[str], encoding: str, **args
1031+
self,
1032+
destination: None,
1033+
format: str,
1034+
base: Optional[str],
1035+
encoding: str,
1036+
**args,
10151037
) -> bytes:
10161038
...
10171039

10181040
# no destination and non-None keyword encoding
10191041
@overload
10201042
def serialize(
10211043
self,
1022-
*,
10231044
destination: None = ...,
10241045
format: str = ...,
10251046
base: Optional[str] = ...,
1047+
*,
10261048
encoding: str,
10271049
**args,
10281050
) -> bytes:
10291051
...
10301052

1031-
# no destination and None positional encoding
1053+
# no destination and None encoding
10321054
@overload
10331055
def serialize(
10341056
self,
1035-
destination: None,
1036-
format: str,
1037-
base: Optional[str],
1038-
encoding: None,
1039-
**args,
1040-
) -> str:
1041-
...
1042-
1043-
# no destination and None keyword encoding
1044-
@overload
1045-
def serialize(
1046-
self,
1047-
*,
10481057
destination: None = ...,
10491058
format: str = ...,
10501059
base: Optional[str] = ...,
1051-
encoding: None = None,
1060+
encoding: None = ...,
10521061
**args,
10531062
) -> str:
10541063
...
10551064

1056-
# non-none destination
1065+
# non-None destination
10571066
@overload
10581067
def serialize(
10591068
self,
1060-
destination: Union[str, BufferedIOBase, pathlib.PurePath],
1069+
destination: Union[str, pathlib.PurePath, IO[bytes]],
10611070
format: str = ...,
10621071
base: Optional[str] = ...,
10631072
encoding: Optional[str] = ...,
@@ -1069,21 +1078,21 @@ def serialize(
10691078
@overload
10701079
def serialize(
10711080
self,
1072-
destination: Union[str, BufferedIOBase, pathlib.PurePath, None] = None,
1073-
format: str = "turtle",
1074-
base: Optional[str] = None,
1075-
encoding: Optional[str] = None,
1081+
destination: Optional[Union[str, pathlib.PurePath, IO[bytes]]] = ...,
1082+
format: str = ...,
1083+
base: Optional[str] = ...,
1084+
encoding: Optional[str] = ...,
10761085
**args,
10771086
) -> Union[bytes, str, "Graph"]:
10781087
...
10791088

10801089
def serialize(
10811090
self,
1082-
destination: Union[str, BufferedIOBase, pathlib.PurePath, None] = None,
1091+
destination: Optional[Union[str, pathlib.PurePath, IO[bytes]]] = None,
10831092
format: str = "turtle",
10841093
base: Optional[str] = None,
10851094
encoding: Optional[str] = None,
1086-
**args,
1095+
**args: Any,
10871096
) -> Union[bytes, str, "Graph"]:
10881097
"""Serialize the Graph to destination
10891098
@@ -1104,7 +1113,7 @@ def serialize(
11041113
base = self.base
11051114

11061115
serializer = plugin.get(format, Serializer)(self)
1107-
stream: BufferedIOBase
1116+
stream: IO[bytes]
11081117
if destination is None:
11091118
stream = BytesIO()
11101119
if encoding is None:
@@ -1114,7 +1123,7 @@ def serialize(
11141123
serializer.serialize(stream, base=base, encoding=encoding, **args)
11151124
return stream.getvalue()
11161125
if hasattr(destination, "write"):
1117-
stream = cast(BufferedIOBase, destination)
1126+
stream = cast(IO[bytes], destination)
11181127
serializer.serialize(stream, base=base, encoding=encoding, **args)
11191128
else:
11201129
if isinstance(destination, pathlib.PurePath):
@@ -1149,10 +1158,10 @@ def parse(
11491158
self,
11501159
source=None,
11511160
publicID=None,
1152-
format=None,
1161+
format: Optional[str] = None,
11531162
location=None,
11541163
file=None,
1155-
data=None,
1164+
data: Optional[Union[str, bytes, bytearray]] = None,
11561165
**args,
11571166
):
11581167
"""
@@ -1537,7 +1546,12 @@ class ConjunctiveGraph(Graph):
15371546
All queries are carried out against the union of all graphs.
15381547
"""
15391548

1540-
def __init__(self, store="default", identifier=None, default_graph_base=None):
1549+
def __init__(
1550+
self,
1551+
store: Union[Store, str] = "default",
1552+
identifier: Optional[Union[Node, str]] = None,
1553+
default_graph_base: Optional[str] = None,
1554+
):
15411555
super(ConjunctiveGraph, self).__init__(store, identifier=identifier)
15421556
assert self.store.context_aware, (
15431557
"ConjunctiveGraph must be backed by" " a context aware store."
@@ -1555,7 +1569,31 @@ def __str__(self):
15551569
)
15561570
return pattern % self.store.__class__.__name__
15571571

1558-
def _spoc(self, triple_or_quad, default=False):
1572+
@overload
1573+
def _spoc(
1574+
self,
1575+
triple_or_quad: Union[
1576+
Tuple[Node, Node, Node, Optional[Any]], Tuple[Node, Node, Node]
1577+
],
1578+
default: bool = False,
1579+
) -> Tuple[Node, Node, Node, Optional[Graph]]:
1580+
...
1581+
1582+
@overload
1583+
def _spoc(
1584+
self,
1585+
triple_or_quad: None,
1586+
default: bool = False,
1587+
) -> Tuple[None, None, None, Optional[Graph]]:
1588+
...
1589+
1590+
def _spoc(
1591+
self,
1592+
triple_or_quad: Optional[
1593+
Union[Tuple[Node, Node, Node, Optional[Any]], Tuple[Node, Node, Node]]
1594+
],
1595+
default: bool = False,
1596+
) -> Tuple[Optional[Node], Optional[Node], Optional[Node], Optional[Graph]]:
15591597
"""
15601598
helper method for having methods that support
15611599
either triples or quads
@@ -1564,9 +1602,9 @@ def _spoc(self, triple_or_quad, default=False):
15641602
return (None, None, None, self.default_context if default else None)
15651603
if len(triple_or_quad) == 3:
15661604
c = self.default_context if default else None
1567-
(s, p, o) = triple_or_quad
1605+
(s, p, o) = triple_or_quad # type: ignore[misc]
15681606
elif len(triple_or_quad) == 4:
1569-
(s, p, o, c) = triple_or_quad
1607+
(s, p, o, c) = triple_or_quad # type: ignore[misc]
15701608
c = self._graph(c)
15711609
return s, p, o, c
15721610

@@ -1577,7 +1615,7 @@ def __contains__(self, triple_or_quad):
15771615
return True
15781616
return False
15791617

1580-
def add(self, triple_or_quad):
1618+
def add(self, triple_or_quad: Union[Tuple[Node, Node, Node, Optional[Any]], Tuple[Node, Node, Node]]) -> "ConjunctiveGraph": # type: ignore[override]
15811619
"""
15821620
Add a triple or quad to the store.
15831621
@@ -1591,15 +1629,23 @@ def add(self, triple_or_quad):
15911629
self.store.add((s, p, o), context=c, quoted=False)
15921630
return self
15931631

1594-
def _graph(self, c):
1632+
@overload
1633+
def _graph(self, c: Union[Graph, Node, str]) -> Graph:
1634+
...
1635+
1636+
@overload
1637+
def _graph(self, c: None) -> None:
1638+
...
1639+
1640+
def _graph(self, c: Optional[Union[Graph, Node, str]]) -> Optional[Graph]:
15951641
if c is None:
15961642
return None
15971643
if not isinstance(c, Graph):
15981644
return self.get_context(c)
15991645
else:
16001646
return c
16011647

1602-
def addN(self, quads):
1648+
def addN(self, quads: Iterable[Tuple[Node, Node, Node, Any]]):
16031649
"""Add a sequence of triples with context"""
16041650

16051651
self.store.addN(
@@ -1689,13 +1735,19 @@ def contexts(self, triple=None):
16891735
else:
16901736
yield self.get_context(context)
16911737

1692-
def get_context(self, identifier, quoted=False, base=None):
1738+
def get_context(
1739+
self,
1740+
identifier: Optional[Union[Node, str]],
1741+
quoted: bool = False,
1742+
base: Optional[str] = None,
1743+
) -> Graph:
16931744
"""Return a context graph for the given identifier
16941745
16951746
identifier must be a URIRef or BNode.
16961747
"""
1748+
# TODO: FIXME - why is ConjunctiveGraph passed as namespace_manager?
16971749
return Graph(
1698-
store=self.store, identifier=identifier, namespace_manager=self, base=base
1750+
store=self.store, identifier=identifier, namespace_manager=self, base=base # type: ignore[arg-type]
16991751
)
17001752

17011753
def remove_context(self, context):
@@ -1747,6 +1799,7 @@ def parse(
17471799
context = Graph(store=self.store, identifier=g_id)
17481800
context.remove((None, None, None)) # hmm ?
17491801
context.parse(source, publicID=publicID, format=format, **args)
1802+
# TODO: FIXME: This should not return context, but self.
17501803
return context
17511804

17521805
def __reduce__(self):
@@ -1977,7 +2030,7 @@ class QuotedGraph(Graph):
19772030
def __init__(self, store, identifier):
19782031
super(QuotedGraph, self).__init__(store, identifier)
19792032

1980-
def add(self, triple):
2033+
def add(self, triple: Tuple[Node, Node, Node]):
19812034
"""Add a triple with self as context"""
19822035
s, p, o = triple
19832036
assert isinstance(s, Node), "Subject %s must be an rdflib term" % (s,)
@@ -1987,7 +2040,7 @@ def add(self, triple):
19872040
self.store.add((s, p, o), self, quoted=True)
19882041
return self
19892042

1990-
def addN(self, quads):
2043+
def addN(self, quads: Tuple[Node, Node, Node, Any]) -> "QuotedGraph": # type: ignore[override]
19912044
"""Add a sequence of triple with context"""
19922045

19932046
self.store.addN(
@@ -2261,7 +2314,7 @@ class BatchAddGraph(object):
22612314
22622315
"""
22632316

2264-
def __init__(self, graph, batch_size=1000, batch_addn=False):
2317+
def __init__(self, graph: Graph, batch_size: int = 1000, batch_addn: bool = False):
22652318
if not batch_size or batch_size < 2:
22662319
raise ValueError("batch_size must be a positive number")
22672320
self.graph = graph
@@ -2278,7 +2331,10 @@ def reset(self):
22782331
self.count = 0
22792332
return self
22802333

2281-
def add(self, triple_or_quad):
2334+
def add(
2335+
self,
2336+
triple_or_quad: Union[Tuple[Node, Node, Node], Tuple[Node, Node, Node, Any]],
2337+
) -> "BatchAddGraph":
22822338
"""
22832339
Add a triple to the buffer
22842340
@@ -2294,7 +2350,7 @@ def add(self, triple_or_quad):
22942350
self.batch.append(triple_or_quad)
22952351
return self
22962352

2297-
def addN(self, quads):
2353+
def addN(self, quads: Iterable[Tuple[Node, Node, Node, Any]]):
22982354
if self.__batch_addn:
22992355
for q in quads:
23002356
self.add(q)

0 commit comments

Comments
 (0)