Skip to content

Instantly share code, notes, and snippets.

@aucampia
Created March 11, 2023 13:20
Show Gist options
  • Save aucampia/4bc97199a0cfcc308676e675a20b0f3a to your computer and use it in GitHub Desktop.
Save aucampia/4bc97199a0cfcc308676e675a20b0f3a to your computer and use it in GitHub Desktop.
compact diff for origin/iwana-20230311T1410-type_path
20230311T141834 iwana@teekai.zoic.eu.org:~/sw/d/github.com/iafork/rdflib.cleanish
$ git status
On branch iwana-20230311T1410-type_path
Your branch is up to date with 'origin/iwana-20230311T1410-type_path'.

nothing to commit, working tree clean
20230311T141844 iwana@teekai.zoic.eu.org:~/sw/d/github.com/iafork/rdflib.cleanish
$ git log -1
commit fd472efae4b3a985b4617a2d958d8167923ded03 (HEAD -> iwana-20230311T1410-type_path, origin/iwana-20230311T1410-type_path)
Author: Iwan Aucamp <aucampia@gmail.com>
Date:   Sat Mar 11 13:13:15 2023 +0000

    feat: add typing to `rdflib.path`
    
    There are some deprecation warnings coming from here as `evalPath` is used internally.
    I want to fix them, but I want type checking to ensure I don't mess up,
    so this just adds type checking, will fix the deprecation warnings in a
    seperate PR.
20230311T141849 iwana@teekai.zoic.eu.org:~/sw/d/github.com/iafork/rdflib.cleanish
$ PYLOGGING_LEVEL=INFO task run -- git difftool -y -x $(readlink -f devtools/diffrtpy.py) upstream/main | tee /var/tmp/compact.diff
task: [venv:run] poetry run git difftool -y -x /home/iwana/sw/d/github.com/iafork/rdflib.cleanish/devtools/diffrtpy.py upstream/main
--- a/rdflib/_type_checking.py
+++ b/rdflib/_type_checking.py
@@ -4,5 +4,6 @@
if sys.version_info >= (3, 8):
from typing import Literal as PyLiteral
else:
from typing_extensions import Literal as PyLiteral
_NamespaceSetString = PyLiteral["core", "rdflib", "none"]
+_MulPathMod = PyLiteral["*", "+", "?"]
--- a/rdflib/paths.py
+++ b/rdflib/paths.py
@@ -1,13 +1,27 @@
+from __future__ import annotations
+
__doc__ = "\n\nThis module implements the SPARQL 1.1 Property path operators, as\ndefined in:\n\nhttp://www.w3.org/TR/sparql11-query/#propertypaths\n\nIn SPARQL the syntax is as follows:\n\n+--------------------+-------------------------------------------------+\n|Syntax | Matches |\n+====================+=================================================+\n|iri | An IRI. A path of length one. |\n+--------------------+-------------------------------------------------+\n|^elt | Inverse path (object to subject). |\n+--------------------+-------------------------------------------------+\n|elt1 / elt2 | A sequence path of elt1 followed by elt2. |\n+--------------------+-------------------------------------------------+\n|elt1 | elt2 | A alternative path of elt1 or elt2 |\n| | (all possibilities are tried). |\n+--------------------+-------------------------------------------------+\n|elt* | A path that connects the subject and object |\n| | of the path by zero or more matches of elt. |\n+--------------------+-------------------------------------------------+\n|elt+ | A path that connects the subject and object |\n| | of the path by one or more matches of elt. |\n+--------------------+-------------------------------------------------+\n|elt? | A path that connects the subject and object |\n| | of the path by zero or one matches of elt. |\n+--------------------+-------------------------------------------------+\n|!iri or | Negated property set. An IRI which is not one of|\n|!(iri\\ :sub:`1`\\ \\| | iri\\ :sub:`1`...iri\\ :sub:`n`. |\n|... \\|iri\\ :sub:`n`)| !iri is short for !(iri). |\n+--------------------+-------------------------------------------------+\n|!^iri or | Negated property set where the excluded matches |\n|!(^iri\\ :sub:`1`\\ \\|| are based on reversed path. That is, not one of |\n|...\\|^iri\\ :sub:`n`)| iri\\ :sub:`1`...iri\\ :sub:`n` as reverse paths. |\n| | !^iri is short for !(^iri). |\n+--------------------+-------------------------------------------------+\n|!(iri\\ :sub:`1`\\ \\| | A combination of forward and reverse |\n|...\\|iri\\ :sub:`j`\\ | properties in a negated property set. |\n|\\|^iri\\ :sub:`j+1`\\ | |\n|\\|... \\|^iri\\ | |\n|:sub:`n`)| | |\n+--------------------+-------------------------------------------------+\n|(elt) | A group path elt, brackets control precedence. |\n+--------------------+-------------------------------------------------+\n\nThis module is used internally by the SPARQL engine, but the property paths\ncan also be used to query RDFLib Graphs directly.\n\nWhere possible the SPARQL syntax is mapped to Python operators, and property\npath objects can be constructed from existing URIRefs.\n\n>>> from rdflib import Graph, Namespace\n>>> from rdflib.namespace import FOAF\n\n>>> ~FOAF.knows\nPath(~http://xmlns.com/foaf/0.1/knows)\n\n>>> FOAF.knows/FOAF.name\nPath(http://xmlns.com/foaf/0.1/knows / http://xmlns.com/foaf/0.1/name)\n\n>>> FOAF.name|FOAF.givenName\nPath(http://xmlns.com/foaf/0.1/name | http://xmlns.com/foaf/0.1/givenName)\n\nModifiers (?, \\*, +) are done using \\* (the multiplication operator) and\nthe strings '\\*', '?', '+', also defined as constants in this file.\n\n>>> FOAF.knows*OneOrMore\nPath(http://xmlns.com/foaf/0.1/knows+)\n\nThe path objects can also be used with the normal graph methods.\n\nFirst some example data:\n\n>>> g=Graph()\n\n>>> g=g.parse(data='''\n... @prefix : <ex:> .\n...\n... :a :p1 :c ; :p2 :f .\n... :c :p2 :e ; :p3 :g .\n... :g :p3 :h ; :p2 :j .\n... :h :p3 :a ; :p2 :g .\n...\n... :q :px :q .\n...\n... ''', format='n3') # doctest: +ELLIPSIS\n\n>>> e = Namespace('ex:')\n\nGraph contains:\n\n>>> (e.a, e.p1/e.p2, e.e) in g\nTrue\n\nGraph generator functions, triples, subjects, objects, etc. :\n\n>>> list(g.objects(e.c, (e.p3*OneOrMore)/e.p2)) # doctest: +NORMALIZE_WHITESPACE\n[rdflib.term.URIRef('ex:j'), rdflib.term.URIRef('ex:g'),\n rdflib.term.URIRef('ex:f')]\n\nA more complete set of tests:\n\n>>> list(eval_path(g, (None, e.p1/e.p2, None)))==[(e.a, e.e)]\nTrue\n>>> list(eval_path(g, (e.a, e.p1|e.p2, None)))==[(e.a,e.c), (e.a,e.f)]\nTrue\n>>> list(eval_path(g, (e.c, ~e.p1, None))) == [ (e.c, e.a) ]\nTrue\n>>> list(eval_path(g, (e.a, e.p1*ZeroOrOne, None))) == [(e.a, e.a), (e.a, e.c)]\nTrue\n>>> list(eval_path(g, (e.c, e.p3*OneOrMore, None))) == [\n... (e.c, e.g), (e.c, e.h), (e.c, e.a)]\nTrue\n>>> list(eval_path(g, (e.c, e.p3*ZeroOrMore, None))) == [(e.c, e.c),\n... (e.c, e.g), (e.c, e.h), (e.c, e.a)]\nTrue\n>>> list(eval_path(g, (e.a, -e.p1, None))) == [(e.a, e.f)]\nTrue\n>>> list(eval_path(g, (e.a, -(e.p1|e.p2), None))) == []\nTrue\n>>> list(eval_path(g, (e.g, -~e.p2, None))) == [(e.g, e.j)]\nTrue\n>>> list(eval_path(g, (e.e, ~(e.p1/e.p2), None))) == [(e.e, e.a)]\nTrue\n>>> list(eval_path(g, (e.a, e.p1/e.p3/e.p3, None))) == [(e.a, e.h)]\nTrue\n\n>>> list(eval_path(g, (e.q, e.px*OneOrMore, None)))\n[(rdflib.term.URIRef('ex:q'), rdflib.term.URIRef('ex:q'))]\n\n>>> list(eval_path(g, (None, e.p1|e.p2, e.c)))\n[(rdflib.term.URIRef('ex:a'), rdflib.term.URIRef('ex:c'))]\n\n>>> list(eval_path(g, (None, ~e.p1, e.a))) == [ (e.c, e.a) ]\nTrue\n>>> list(eval_path(g, (None, e.p1*ZeroOrOne, e.c))) # doctest: +NORMALIZE_WHITESPACE\n[(rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:c')),\n (rdflib.term.URIRef('ex:a'), rdflib.term.URIRef('ex:c'))]\n\n>>> list(eval_path(g, (None, e.p3*OneOrMore, e.a))) # doctest: +NORMALIZE_WHITESPACE\n[(rdflib.term.URIRef('ex:h'), rdflib.term.URIRef('ex:a')),\n (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:a')),\n (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:a'))]\n\n>>> list(eval_path(g, (None, e.p3*ZeroOrMore, e.a))) # doctest: +NORMALIZE_WHITESPACE\n[(rdflib.term.URIRef('ex:a'), rdflib.term.URIRef('ex:a')),\n (rdflib.term.URIRef('ex:h'), rdflib.term.URIRef('ex:a')),\n (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:a')),\n (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:a'))]\n\n>>> list(eval_path(g, (None, -e.p1, e.f))) == [(e.a, e.f)]\nTrue\n>>> list(eval_path(g, (None, -(e.p1|e.p2), e.c))) == []\nTrue\n>>> list(eval_path(g, (None, -~e.p2, e.j))) == [(e.g, e.j)]\nTrue\n>>> list(eval_path(g, (None, ~(e.p1/e.p2), e.a))) == [(e.e, e.a)]\nTrue\n>>> list(eval_path(g, (None, e.p1/e.p3/e.p3, e.h))) == [(e.a, e.h)]\nTrue\n\n>>> list(eval_path(g, (e.q, e.px*OneOrMore, None)))\n[(rdflib.term.URIRef('ex:q'), rdflib.term.URIRef('ex:q'))]\n\n>>> list(eval_path(g, (e.c, (e.p2|e.p3)*ZeroOrMore, e.j)))\n[(rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:j'))]\n\nNo vars specified:\n\n>>> sorted(list(eval_path(g, (None, e.p3*OneOrMore, None)))) #doctest: +NORMALIZE_WHITESPACE\n[(rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:a')),\n (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:g')),\n (rdflib.term.URIRef('ex:c'), rdflib.term.URIRef('ex:h')),\n (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:a')),\n (rdflib.term.URIRef('ex:g'), rdflib.term.URIRef('ex:h')),\n (rdflib.term.URIRef('ex:h'), rdflib.term.URIRef('ex:a'))]\n\n"
import warnings
from functools import total_ordering
-from typing import TYPE_CHECKING, Callable, Iterator, Optional, Tuple, Union
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Callable,
+ Generator,
+ Iterator,
+ List,
+ Optional,
+ Set,
+ Tuple,
+ Union,
+)
from rdflib.term import Node, URIRef
if TYPE_CHECKING:
- from rdflib.graph import Graph, _ObjectType, _SubjectType
+ from rdflib._type_checking import _MulPathMod
+ from rdflib.graph import Graph, _ObjectType, _PredicateType, _SubjectType
from rdflib.namespace import NamespaceManager
ZeroOrMore = "*"
OneOrMore = "+"
ZeroOrOne = "?"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment