From 9c70f51598566732e6d770e5ac05fb0e60e1d564 Mon Sep 17 00:00:00 2001 From: Iwan Aucamp Date: Sun, 12 Mar 2023 10:22:47 +0100 Subject: feat: add type hints to `rdflib.collection` (#2263) This change makes RDFLib safer to use and change, as changes and usage can be validated using static analysers like mypy. This change does not have a runtime impact. --- rdflib/collection.py | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/rdflib/collection.py b/rdflib/collection.py index 5246184d..b9c76107 100644 --- a/rdflib/collection.py +++ b/rdflib/collection.py @@ -1,5 +1,12 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Iterable, Iterator, List, Optional + from rdflib.namespace import RDF -from rdflib.term import BNode, Literal +from rdflib.term import BNode, Node + +if TYPE_CHECKING: + from rdflib.graph import Graph __all__ = ["Collection"] @@ -9,6 +16,7 @@ class Collection(object): See "Emulating container types": https://docs.python.org/reference/datamodel.html#emulating-container-types + >>> from rdflib.term import Literal >>> from rdflib.graph import Graph >>> from pprint import pprint >>> listname = BNode() @@ -43,13 +51,14 @@ class Collection(object): True """ - def __init__(self, graph, uri, seq=[]): + def __init__(self, graph: Graph, uri: Node, seq: List[Node] = []): self.graph = graph self.uri = uri or BNode() self += seq - def n3(self): + def n3(self) -> str: """ + >>> from rdflib.term import Literal >>> from rdflib.graph import Graph >>> listname = BNode() >>> g = Graph('Memory') @@ -73,13 +82,14 @@ class Collection(object): "2"^^ "3"^^ ) """ - return "( %s )" % (" ".join([i.n3() for i in self])) + # type error: "Node" has no attribute "n3" + return "( %s )" % (" ".join([i.n3() for i in self])) # type: ignore[attr-defined] - def _get_container(self, index): + def _get_container(self, index: int) -> Optional[Node]: """Gets the first, rest holding node at index.""" assert isinstance(index, int) graph = self.graph - container = self.uri + container: Optional[Node] = self.uri i = 0 while i < index: i += 1 @@ -88,11 +98,11 @@ class Collection(object): break return container - def __len__(self): + def __len__(self) -> int: """length of items in collection.""" return len(list(self.graph.items(self.uri))) - def index(self, item): + def index(self, item: Node) -> int: """ Returns the 0-based numerical index of the item in the list """ @@ -112,7 +122,7 @@ class Collection(object): assert len(newlink) == 1, "Malformed RDF Collection: %s" % self.uri listname = newlink[0] - def __getitem__(self, key): + def __getitem__(self, key: int) -> Node: """TODO""" c = self._get_container(key) if c: @@ -124,7 +134,7 @@ class Collection(object): else: raise IndexError(key) - def __setitem__(self, key, value): + def __setitem__(self, key: int, value: Node) -> None: """TODO""" c = self._get_container(key) if c: @@ -132,7 +142,7 @@ class Collection(object): else: raise IndexError(key) - def __delitem__(self, key): + def __delitem__(self, key: int) -> None: """ >>> from rdflib.namespace import RDF, RDFS >>> from rdflib import Graph @@ -184,7 +194,8 @@ class Collection(object): elif key == len(self) - 1: # the tail priorlink = self._get_container(key - 1) - self.graph.set((priorlink, RDF.rest, RDF.nil)) + # type error: Argument 1 to "set" of "Graph" has incompatible type "Tuple[Optional[Node], URIRef, URIRef]"; expected "Tuple[Node, Node, Any]" + self.graph.set((priorlink, RDF.rest, RDF.nil)) # type: ignore[arg-type] graph.remove((current, None, None)) else: next = self._get_container(key + 1) @@ -193,11 +204,11 @@ class Collection(object): graph.remove((current, None, None)) graph.set((prior, RDF.rest, next)) - def __iter__(self): + def __iter__(self) -> Iterator[Node]: """Iterator over items in Collections""" return self.graph.items(self.uri) - def _end(self): + def _end(self) -> Node: # find end of list container = self.uri while True: @@ -207,8 +218,9 @@ class Collection(object): else: container = rest - def append(self, item): + def append(self, item: Node) -> Collection: """ + >>> from rdflib.term import Literal >>> from rdflib.graph import Graph >>> listname = BNode() >>> g = Graph() @@ -231,7 +243,7 @@ class Collection(object): self.graph.add((end, RDF.rest, RDF.nil)) return self - def __iadd__(self, other): + def __iadd__(self, other: Iterable[Node]): end = self._end() self.graph.remove((end, RDF.rest, None)) @@ -247,7 +259,7 @@ class Collection(object): return self def clear(self): - container = self.uri + container: Optional[Node] = self.uri graph = self.graph while container: rest = graph.value(container, RDF.rest) -- cgit v1.2.1