diff --git a/pyproject.toml b/pyproject.toml index 88ade542e..4112758d3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,6 +105,11 @@ pep8-naming = ["-N802", "-N806", "-N815"] pycodestyle = ["-E402"] [tool.flakeheaven.exceptions."test/utils/namespace/_*"] pep8-naming = ["-N815"] +[tool.flakeheaven.exceptions."rdflib/plugins/parsers/rdfxml.py"] +pep8-naming = ["-N802"] +[tool.flakeheaven.exceptions."rdflib/plugins/parsers/trix.py"] +pep8-naming = ["-N802"] + [tool.black] diff --git a/rdflib/plugins/parsers/jsonld.py b/rdflib/plugins/parsers/jsonld.py index 60eca8a99..eb7972ff1 100644 --- a/rdflib/plugins/parsers/jsonld.py +++ b/rdflib/plugins/parsers/jsonld.py @@ -460,20 +460,23 @@ def _to_object( term: Optional[Term], node: Any, inlist: bool = False, - ): + ) -> Optional[Node]: if isinstance(node, tuple): value, lang = node if value is None: - return + # type error: Return value expected + return # type: ignore[return-value] if lang and " " in lang: - return + # type error: Return value expected + return # type: ignore[return-value] return Literal(value, lang=lang) if isinstance(node, dict): node_list = context.get_list(node) if node_list is not None: if inlist and not self.allow_lists_of_lists: - return + # type error: Return value expected + return # type: ignore[return-value] listref = self._add_list(dataset, graph, context, term, node_list) if listref: return listref @@ -483,7 +486,8 @@ def _to_object( if term.type == JSON: node = self._to_typed_json_value(node) elif node is None: - return + # type error: Return value expected + return # type: ignore[return-value] elif term.type == ID and isinstance(node, str): node = {ID: context.resolve(node)} elif term.type == VOCAB and isinstance(node, str): @@ -492,7 +496,8 @@ def _to_object( node = {TYPE: term.type, VALUE: node} else: if node is None: - return + # type error: Return value expected + return # type: ignore[return-value] if isinstance(node, float): return Literal(node, datatype=XSD.double) @@ -516,7 +521,8 @@ def _to_object( return None if lang: if " " in lang: - return + # type error: Return value expected + return # type: ignore[return-value] return Literal(value, lang=lang) elif datatype: return Literal(value, datatype=context.expand(datatype)) @@ -549,7 +555,7 @@ def _add_list( context: Context, term: Optional[Term], node_list: Any, - ): + ) -> IdentifiedNode: if not isinstance(node_list, list): node_list = [node_list] diff --git a/rdflib/plugins/parsers/rdfxml.py b/rdflib/plugins/parsers/rdfxml.py index a7933a56f..1f8e7e688 100644 --- a/rdflib/plugins/parsers/rdfxml.py +++ b/rdflib/plugins/parsers/rdfxml.py @@ -1,8 +1,9 @@ """ An RDF/XML parser for RDFLib """ +from __future__ import annotations -from typing import Any +from typing import TYPE_CHECKING, Any, Dict, List, NoReturn, Optional, Tuple from urllib.parse import urldefrag, urljoin from xml.sax import handler, make_parser, xmlreader from xml.sax.handler import ErrorHandler @@ -13,7 +14,13 @@ from rdflib.namespace import RDF, is_ncname from rdflib.parser import InputSource, Parser from rdflib.plugins.parsers.RDFVOC import RDFVOC -from rdflib.term import BNode, Literal, URIRef +from rdflib.term import BNode, Identifier, Literal, URIRef + +if TYPE_CHECKING: + # from xml.sax.expatreader import ExpatLocator + from xml.sax.xmlreader import AttributesImpl, Locator + + from rdflib.graph import _ObjectType, _SubjectType, _TripleType __all__ = ["create_parser", "BagID", "ElementHandler", "RDFXMLHandler", "RDFXMLParser"] @@ -127,42 +134,46 @@ def next_li(self): class RDFXMLHandler(handler.ContentHandler): - def __init__(self, store): + def __init__(self, store: Graph): self.store = store self.preserve_bnode_ids = False self.reset() - def reset(self): + def reset(self) -> None: document_element = ElementHandler() document_element.start = self.document_element_start document_element.end = lambda name, qname: None - self.stack = [ + self.stack: List[Optional[ElementHandler]] = [ None, document_element, ] - self.ids = {} # remember IDs we have already seen - self.bnode = {} - self._ns_contexts = [{}] # contains uri -> prefix dicts - self._current_context = self._ns_contexts[-1] + self.ids: Dict[str, int] = {} # remember IDs we have already seen + self.bnode: Dict[str, Identifier] = {} + self._ns_contexts: List[Dict[str, Optional[str]]] = [ + {} + ] # contains uri -> prefix dicts + self._current_context: Dict[str, Optional[str]] = self._ns_contexts[-1] # ContentHandler methods - def setDocumentLocator(self, locator): + def setDocumentLocator(self, locator: Locator): self.locator = locator - def startDocument(self): + def startDocument(self) -> None: pass - def startPrefixMapping(self, prefix, namespace): + def startPrefixMapping(self, prefix: Optional[str], namespace: str) -> None: self._ns_contexts.append(self._current_context.copy()) self._current_context[namespace] = prefix self.store.bind(prefix, namespace or "", override=False) - def endPrefixMapping(self, prefix): + def endPrefixMapping(self, prefix: Optional[str]) -> None: self._current_context = self._ns_contexts[-1] del self._ns_contexts[-1] - def startElementNS(self, name, qname, attrs): + def startElementNS( + self, name: Tuple[Optional[str], str], qname, attrs: AttributesImpl + ) -> None: stack = self.stack stack.append(ElementHandler()) current = self.current @@ -191,29 +202,29 @@ def startElementNS(self, name, qname, attrs): current.language = language current.start(name, qname, attrs) - def endElementNS(self, name, qname): + def endElementNS(self, name: Tuple[Optional[str], str], qname) -> None: self.current.end(name, qname) self.stack.pop() - def characters(self, content): + def characters(self, content: str) -> None: char = self.current.char if char: char(content) - def ignorableWhitespace(self, content): + def ignorableWhitespace(self, content) -> None: pass - def processingInstruction(self, target, data): + def processingInstruction(self, target, data) -> None: pass - def add_reified(self, sid, spo): + def add_reified(self, sid: Identifier, spo: _TripleType): s, p, o = spo self.store.add((sid, RDF.type, RDF.Statement)) self.store.add((sid, RDF.subject, s)) self.store.add((sid, RDF.predicate, p)) self.store.add((sid, RDF.object, o)) - def error(self, message): + def error(self, message: str) -> NoReturn: locator = self.locator info = "%s:%s:%s: " % ( locator.getSystemId(), @@ -222,38 +233,44 @@ def error(self, message): ) raise ParserError(info + message) - def get_current(self): + def get_current(self) -> Optional[ElementHandler]: return self.stack[-2] # Create a read only property called current so that self.current # give the current element handler. current = property(get_current) - def get_next(self): + def get_next(self) -> Optional[ElementHandler]: return self.stack[-1] # Create a read only property that gives the element handler to be # used for the next element. next = property(get_next) - def get_parent(self): + def get_parent(self) -> Optional[ElementHandler]: return self.stack[-3] # Create a read only property that gives the current parent # element handler parent = property(get_parent) - def absolutize(self, uri): - result = urljoin(self.current.base, uri, allow_fragments=1) + def absolutize(self, uri: str) -> URIRef: + # type error: Argument "allow_fragments" to "urljoin" has incompatible type "int"; expected "bool" + result = urljoin(self.current.base, uri, allow_fragments=1) # type: ignore[arg-type] if uri and uri[-1] == "#" and result[-1] != "#": result = "%s#" % result return URIRef(result) - def convert(self, name, qname, attrs): + def convert( + self, name: Tuple[Optional[str], str], qname, attrs: AttributesImpl + ) -> Tuple[URIRef, Dict[URIRef, str]]: if name[0] is None: - name = URIRef(name[1]) + # type error: Incompatible types in assignment (expression has type "URIRef", variable has type "Tuple[Optional[str], str]") + name = URIRef(name[1]) # type: ignore[assignment] else: - name = URIRef("".join(name)) + # type error: Incompatible types in assignment (expression has type "URIRef", variable has type "Tuple[Optional[str], str]") + # type error: Argument 1 to "join" of "str" has incompatible type "Tuple[Optional[str], str]"; expected "Iterable[str]" + name = URIRef("".join(name)) # type: ignore[assignment, arg-type] atts = {} for (n, v) in attrs.items(): if n[0] is None: @@ -264,12 +281,16 @@ def convert(self, name, qname, attrs): pass elif att in UNQUALIFIED: # if not RDFNS[att] in atts: - atts[RDFNS[att]] = v # type: ignore[misc] + # type error: Variable "att" is not valid as a type + atts[RDFNS[att]] = v # type: ignore[misc, valid-type] else: atts[URIRef(att)] = v - return name, atts + # type error: Incompatible return value type (got "Tuple[Tuple[Optional[str], str], Dict[Any, Any]]", expected "Tuple[URIRef, Dict[URIRef, str]]") + return name, atts # type: ignore[return-value] - def document_element_start(self, name, qname, attrs): + def document_element_start( + self, name: Tuple[str, str], qname, attrs: AttributesImpl + ) -> None: if name[0] and URIRef("".join(name)) == RDFVOC.RDF: # Cheap hack so 2to3 doesn't turn it into __next__ next = getattr(self, "next") @@ -281,8 +302,11 @@ def document_element_start(self, name, qname, attrs): # TODO... set end to something that sets start such that # another element will cause error - def node_element_start(self, name, qname, attrs): - name, atts = self.convert(name, qname, attrs) + def node_element_start( + self, name: Tuple[str, str], qname, attrs: AttributesImpl + ) -> None: + # type error: Incompatible types in assignment (expression has type "URIRef", variable has type "Tuple[str, str]") + name, atts = self.convert(name, qname, attrs) # type: ignore[assignment] current = self.current absolutize = self.absolutize @@ -292,8 +316,9 @@ def node_element_start(self, name, qname, attrs): next.end = self.property_element_end if name in NODE_ELEMENT_EXCEPTIONS: - self.error("Invalid node element URI: %s" % name) - + # type error: Not all arguments converted during string formatting + self.error("Invalid node element URI: %s" % name) # type: ignore[str-format] + subject: _SubjectType if RDFVOC.ID in atts: if RDFVOC.about in atts or RDFVOC.nodeID in atts: self.error("Can have at most one of rdf:ID, rdf:about, and rdf:nodeID") @@ -327,8 +352,10 @@ def node_element_start(self, name, qname, attrs): subject = BNode() if name != RDFVOC.Description: # S1 - self.store.add((subject, RDF.type, absolutize(name))) + # error: Argument 1 has incompatible type "Tuple[str, str]"; expected "str" + self.store.add((subject, RDF.type, absolutize(name))) # type: ignore[arg-type] + object: _ObjectType language = current.language for att in atts: if not att.startswith(str(RDFNS)): @@ -336,7 +363,8 @@ def node_element_start(self, name, qname, attrs): try: object = Literal(atts[att], language) except Error as e: - self.error(e.msg) + # type error: Argument 1 to "error" of "RDFXMLHandler" has incompatible type "Optional[str]"; expected "str" + self.error(e.msg) # type: ignore[arg-type] elif att == RDF.type: # S2 predicate = RDF.type object = absolutize(atts[RDF.type]) @@ -344,18 +372,20 @@ def node_element_start(self, name, qname, attrs): continue elif att in PROPERTY_ATTRIBUTE_EXCEPTIONS: # S3 self.error("Invalid property attribute URI: %s" % att) - continue # for when error does not throw an exception + # type error: Statement is unreachable + continue # type: ignore[unreachable] # for when error does not throw an exception else: predicate = absolutize(att) try: object = Literal(atts[att], language) except Error as e: - self.error(e.msg) + # type error: Argument 1 to "error" of "RDFXMLHandler" has incompatible type "Optional[str]"; expected "str" + self.error(e.msg) # type: ignore[arg-type] self.store.add((subject, predicate, object)) current.subject = subject - def node_element_end(self, name, qname): + def node_element_end(self, name: Tuple[str, str], qname) -> None: # repeat node-elements are only allowed # at at top-level @@ -367,25 +397,32 @@ def node_element_end(self, name, qname): self.parent.object = self.current.subject - def property_element_start(self, name, qname, attrs): - name, atts = self.convert(name, qname, attrs) + def property_element_start( + self, name: Tuple[str, str], qname, attrs: AttributesImpl + ) -> None: + # type error: Incompatible types in assignment (expression has type "URIRef", variable has type "Tuple[str, str]") + name, atts = self.convert(name, qname, attrs) # type: ignore[assignment] current = self.current absolutize = self.absolutize # Cheap hack so 2to3 doesn't turn it into __next__ next = getattr(self, "next") - object = None + object: Optional[_ObjectType] = None current.data = None current.list = None - if not name.startswith(str(RDFNS)): - current.predicate = absolutize(name) + # type error: "Tuple[str, str]" has no attribute "startswith" + if not name.startswith(str(RDFNS)): # type: ignore[attr-defined] + # type error: Argument 1 has incompatible type "Tuple[str, str]"; expected "str" + current.predicate = absolutize(name) # type: ignore[arg-type] elif name == RDFVOC.li: current.predicate = current.next_li() elif name in PROPERTY_ELEMENT_EXCEPTIONS: - self.error("Invalid property element URI: %s" % name) + # type error: Not all arguments converted during string formatting + self.error("Invalid property element URI: %s" % name) # type: ignore[str-format] else: - current.predicate = absolutize(name) + # type error: Argument 1 has incompatible type "Tuple[str, str]"; expected "str" + current.predicate = absolutize(name) # type: ignore[arg-type] id = atts.get(RDFVOC.ID, None) if id is not None: @@ -467,12 +504,13 @@ def property_element_start(self, name, qname, attrs): self.error("""Invalid property attribute URI: %s""" % att) else: predicate = absolutize(att) - + o: _ObjectType if att == RDF.type: o = URIRef(atts[att]) else: if datatype is not None: - language = None + # type error: Statement is unreachable + language = None # type: ignore[unreachable] o = Literal(atts[att], language, datatype) if object is None: @@ -485,12 +523,12 @@ def property_element_start(self, name, qname, attrs): current.data = None current.object = object - def property_element_char(self, data): + def property_element_char(self, data: str) -> None: current = self.current if current.data is not None: current.data += data - def property_element_end(self, name, qname): + def property_element_end(self, name: Tuple[str, str], qname) -> None: current = self.current if current.data is not None and current.object is None: literalLang = current.language @@ -509,7 +547,7 @@ def property_element_end(self, name, qname): ) current.subject = None - def list_node_element_end(self, name, qname): + def list_node_element_end(self, name: Tuple[str, str], qname) -> None: current = self.current if self.parent.list == RDF.nil: list = BNode() @@ -527,7 +565,9 @@ def list_node_element_end(self, name, qname): self.store.add((list, RDF.first, current.subject)) self.parent.list = list - def literal_element_start(self, name, qname, attrs): + def literal_element_start( + self, name: Tuple[str, str], qname, attrs: AttributesImpl + ) -> None: current = self.current self.next.start = self.literal_element_start self.next.char = self.literal_element_char @@ -554,14 +594,15 @@ def literal_element_start(self, name, qname, attrs): current.declared[name[0]] = self._current_context[name[0]] name = current.declared[name[0]] + ":" + name[1] else: - name = name[1] + # type error: Incompatible types in assignment (expression has type "str", variable has type "Tuple[str, str]") + name = name[1] # type: ignore[assignment] current.object += " %s=%s" % (name, quoteattr(value)) current.object += ">" - def literal_element_char(self, data): + def literal_element_char(self, data: str) -> None: self.current.object += escape(data) - def literal_element_end(self, name, qname): + def literal_element_end(self, name: Tuple[str, str], qname) -> None: if name[0]: prefix = self._current_context[name[0]] if prefix: @@ -583,7 +624,8 @@ def create_parser(target: InputSource, store: Graph) -> xmlreader.XMLReader: pass # Not present in Jython (at least) parser.setFeature(handler.feature_namespaces, 1) rdfxml = RDFXMLHandler(store) - rdfxml.setDocumentLocator(target) + # type error: Argument 1 to "setDocumentLocator" of "RDFXMLHandler" has incompatible type "InputSource"; expected "Locator" + rdfxml.setDocumentLocator(target) # type: ignore[arg-type] # rdfxml.setDocumentLocator(_Locator(self.url, self.parser)) parser.setContentHandler(rdfxml) parser.setErrorHandler(ErrorHandler()) diff --git a/rdflib/plugins/parsers/trix.py b/rdflib/plugins/parsers/trix.py index 5526d10ea..d1205ac8e 100644 --- a/rdflib/plugins/parsers/trix.py +++ b/rdflib/plugins/parsers/trix.py @@ -1,7 +1,9 @@ """ A TriX parser for RDFLib """ -from typing import Any +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Dict, List, NoReturn, Optional, Tuple from xml.sax import handler, make_parser from xml.sax.handler import ErrorHandler @@ -10,7 +12,11 @@ from rdflib.namespace import Namespace from rdflib.parser import InputSource, Parser from rdflib.store import Store -from rdflib.term import BNode, Literal, URIRef +from rdflib.term import BNode, Identifier, Literal, URIRef + +if TYPE_CHECKING: + # from xml.sax.expatreader import ExpatLocator + from xml.sax.xmlreader import AttributesImpl, Locator, XMLReader __all__ = ["create_parser", "TriXHandler", "TriXParser"] @@ -22,34 +28,36 @@ class TriXHandler(handler.ContentHandler): """An Sax Handler for TriX. See http://sw.nokia.com/trix/""" - def __init__(self, store): + def __init__(self, store: Store): self.store = store self.preserve_bnode_ids = False self.reset() - def reset(self): - self.bnode = {} - self.graph = None - self.triple = None + def reset(self) -> None: + self.bnode: Dict[str, BNode] = {} + self.graph: Optional[Graph] = None + self.triple: Optional[List[Identifier]] = None self.state = 0 self.lang = None self.datatype = None # ContentHandler methods - def setDocumentLocator(self, locator): + def setDocumentLocator(self, locator: Locator): self.locator = locator - def startDocument(self): + def startDocument(self) -> None: pass - def startPrefixMapping(self, prefix, namespace): + def startPrefixMapping(self, prefix: Optional[str], namespace: str) -> None: pass - def endPrefixMapping(self, prefix): + def endPrefixMapping(self, prefix: Optional[str]) -> None: pass - def startElementNS(self, name, qname, attrs): + def startElementNS( + self, name: Tuple[Optional[str], str], qname, attrs: AttributesImpl + ) -> None: if name[0] != str(TRIXNS): self.error( @@ -138,7 +146,9 @@ def startElementNS(self, name, qname, attrs): self.chars = "" - def endElementNS(self, name, qname): + def endElementNS(self, name: Tuple[Optional[str], str], qname) -> None: + if TYPE_CHECKING: + assert self.triple is not None if name[0] != str(TRIXNS): self.error( "Only elements in the TriX namespace are allowed. %s!=%s" @@ -191,8 +201,9 @@ def endElementNS(self, name, qname): "Triple has wrong length, got %d elements: %s" % (len(self.triple), self.triple) ) - - self.graph.add(self.triple) + # type error: Item "None" of "Optional[Graph]" has no attribute "add" + # type error: Argument 1 to "add" of "Graph" has incompatible type "List[Identifier]"; expected "Tuple[Node, Node, Node]" + self.graph.add(self.triple) # type: ignore[union-attr, arg-type] # self.store.store.add(self.triple,context=self.graph) # self.store.addN([self.triple+[self.graph]]) self.state = 2 @@ -212,7 +223,7 @@ def endElementNS(self, name, qname): else: self.error("Unexpected close element") - def get_bnode(self, label): + def get_bnode(self, label: str) -> BNode: if self.preserve_bnode_ids: bn = BNode(label) else: @@ -223,16 +234,16 @@ def get_bnode(self, label): self.bnode[label] = bn return bn - def characters(self, content): + def characters(self, content: str) -> None: self.chars += content - def ignorableWhitespace(self, content): + def ignorableWhitespace(self, content) -> None: pass - def processingInstruction(self, target, data): + def processingInstruction(self, target, data) -> None: pass - def error(self, message): + def error(self, message: str) -> NoReturn: locator = self.locator info = "%s:%s:%s: " % ( locator.getSystemId(), @@ -242,7 +253,7 @@ def error(self, message): raise ParserError(info + message) -def create_parser(store: Store): +def create_parser(store: Store) -> XMLReader: parser = make_parser() try: diff --git a/rdflib/plugins/sparql/parserutils.py b/rdflib/plugins/sparql/parserutils.py index b6b915087..2fec95aa0 100644 --- a/rdflib/plugins/sparql/parserutils.py +++ b/rdflib/plugins/sparql/parserutils.py @@ -231,7 +231,7 @@ class Comp(TokenConverter): Returns CompValue / Expr objects - depending on whether evalFn is set. """ - def __init__(self, name, expr): + def __init__(self, name: str, expr): self.expr = expr TokenConverter.__init__(self, expr) self.setName(name)