Redundant deregistering of custom functions? · Issue #1492 · RDFLib/rdflib (original) (raw)

I'm running into an issue with a complex ontology project where a Javascript-based SPARQL function is being "unregistered" twice and causing the following stack trace when I run my unit tests:

../venv/lib/python3.9/site-packages/pyshacl/validate.py:419: in validate
    conforms, report_graph, report_text = validator.run()
../venv/lib/python3.9/site-packages/pyshacl/validate.py:265: in run
    unapply_functions(advanced['functions'], g)
../venv/lib/python3.9/site-packages/pyshacl/functions/__init__.py:108: in unapply_functions
    f.unapply(data_graph)
../venv/lib/python3.9/site-packages/pyshacl/functions/shacl_function.py:197: in unapply
    unregister_custom_function(self.node, self.execute_from_sparql)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

uri = rdflib.term.URIRef('http://datashapes.org/dash#toString'), func = <bound method SPARQLFunction.execute_from_sparql of <pyshacl.functions.shacl_function.SPARQLFunction object at 0x7f5b80852c40>>

    def unregister_custom_function(uri, func):
        if _CUSTOM_FUNCTIONS.get(uri, (None, None))[0] != func:
>           raise ValueError("This function is not registered as %s" % uri.n3())
E           ValueError: This function is not registered as <http://datashapes.org/dash#toString>

../venv/lib/python3.9/site-packages/rdflib/plugins/sparql/operators.py:616: ValueError

I believe what is happening is the dash graph is getting loaded multiple times because of redundant imports. This loads the dash:toString function multiple times, which is (correctly) idempotent. However, during cleanup (I am using pySHACL's implementation of SHACL-AF), pySHACL attempts to unregister the dash:toString function multiple times. After a function is unregistered the first time, the ValueError in https://github.com/RDFLib/rdflib/blob/master/rdflib/plugins/sparql/operators.py#L614-L617 gets thrown. I believe this should be idempotent as well --- if the function does not exist in the function lookup table, then a warning should be thrown rather than an exception. I could also see pySHACL catching the exception to avoid halting the cleanup.

I am happy to introduce a change PR --- either to RDFlib or pySHACL --- to address this, but I wanted to ask if my intended fix is appropriate. I'll see what I can do about creating a minimal reproducible example