Example #1
0
 def _run_pre_inference(self, target_graph, inference_option):
     try:
         if inference_option == 'rdfs':
             inferencer = owl_rl.DeductiveClosure(CustomRDFSSemantics)
         elif inference_option == 'owlrl':
             inferencer = owl_rl.DeductiveClosure(owl_rl.OWLRL_Semantics)
         elif inference_option == 'both' or inference_option == 'all'\
                 or inference_option == 'rdfsowlrl':
             inferencer = owl_rl.DeductiveClosure(CustomRDFSOWLRLSemantics)
         else:
             raise ReportableRuntimeError(
                 "Don't know how to do '{}' type inferencing.".format(
                     inference_option))
     except Exception as e:
         self.logger.error(
             "Error during creation of OWL-RL Deductive Closure")
         raise ReportableRuntimeError(
             "Error during creation of OWL-RL Deductive Closure\n"
             "{}".format(str(e.args[0])))
     try:
         inferencer.expand(target_graph)
     except Exception as e:
         self.logger.error("Error while running OWL-RL Deductive Closure")
         raise ReportableRuntimeError(
             "Error while running OWL-RL Deductive Closure\n"
             "{}".format(str(e.args[0])))
Example #2
0
 def _evaluate_xone_constraint(xone_c):
     nonlocal self, shape, target_graph, focus_value_nodes, _evaluation_path
     _reports = []
     _non_conformant = False
     sg = shape.sg.graph
     xone_list = list(sg.items(xone_c))
     if len(xone_list) < 1:
         raise ReportableRuntimeError("The list associated with sh:xone is not " "a valid RDF list.")
     xone_shapes = list()
     for x in xone_list:
         xone_shape = shape.get_other_shape(x)
         if not xone_shape:
             raise ReportableRuntimeError(
                 "Shape pointed to by sh:xone does not exist " "or is not a well-formed SHACL Shape."
             )
         xone_shapes.append(xone_shape)
     for f, value_nodes in focus_value_nodes.items():
         for v in value_nodes:
             passed_count = 0
             for xone_shape in xone_shapes:
                 try:
                     _is_conform, _r = xone_shape.validate(
                         target_graph, focus=v, _evaluation_path=_evaluation_path[:]
                     )
                 except ValidationFailure as e:
                     raise e
                 if _is_conform:
                     passed_count += 1
             if not (passed_count == 1):
                 _non_conformant = True
                 rept = self.make_v_result(target_graph, f, value_node=v)
                 _reports.append(rept)
     return _non_conformant, _reports
Example #3
0
 def _evaluate_or_constraint(or_c):
     nonlocal self, shape, target_graph, focus_value_nodes, _evaluation_path
     _reports = []
     _non_conformant = False
     sg = shape.sg.graph
     or_list = set(sg.items(or_c))
     if len(or_list) < 1:
         raise ReportableRuntimeError("The list associated with sh:or " "is not a valid RDF list.")
     or_shapes = set()
     for o in or_list:
         or_shape = shape.get_other_shape(o)
         if not or_shape:
             raise ReportableRuntimeError(
                 "Shape pointed to by sh:or does not exist or " "is not a well-formed SHACL Shape."
             )
         or_shapes.add(or_shape)
     for f, value_nodes in focus_value_nodes.items():
         for v in value_nodes:
             passed_any = False
             for or_shape in or_shapes:
                 try:
                     _is_conform, _r = or_shape.validate(
                         target_graph, focus=v, _evaluation_path=_evaluation_path[:]
                     )
                 except ValidationFailure as e:
                     raise e
                 passed_any = passed_any or _is_conform
             if not passed_any:
                 _non_conformant = True
                 rept = self.make_v_result(target_graph, f, value_node=v)
                 _reports.append(rept)
     return _non_conformant, _reports
Example #4
0
 def _evaluate_and_constraint(self, and_c, target_graph, f_v_dict):
     reports = []
     non_conformant = False
     sg = self.shape.sg.graph
     and_list = set(sg.items(and_c))
     if len(and_list) < 1:
         raise ReportableRuntimeError(
             "The list associated with sh:and is not a "
             "valid RDF list.")
     and_shapes = set()
     for a in and_list:
         and_shape = self.shape.get_other_shape(a)
         if not and_shape:
             raise ReportableRuntimeError(
                 "Shape pointed to by sh:and does not exist or "
                 "is not a well-formed SHACL Shape.")
         and_shapes.add(and_shape)
     for f, value_nodes in f_v_dict.items():
         for v in value_nodes:
             passed_all = True
             for and_shape in and_shapes:
                 try:
                     _is_conform, _r = and_shape.validate(target_graph,
                                                          focus=v)
                 except ValidationFailure as e:
                     raise e
                 passed_all = passed_all and _is_conform
             if not passed_all:
                 non_conformant = True
                 rept = self.make_v_result(target_graph, f, value_node=v)
                 reports.append(rept)
     return non_conformant, reports
Example #5
0
def compare_inferencing_reports(data_graph: GraphLike,
                                expected_graph: GraphLike,
                                expected_result: GraphLike):
    expected_object = set(expected_graph.objects(expected_result, RDF_object))
    if len(expected_object) < 1:
        raise ReportableRuntimeError(
            "Cannot check the expected result, the given expectedResult does not have an rdf:object."
        )
    expected_object = next(iter(expected_object))
    expected_subject = set(expected_graph.objects(expected_result,
                                                  RDF_subject))
    if len(expected_subject) < 1:
        raise ReportableRuntimeError(
            "Cannot check the expected result, the given expectedResult does not have an rdf:subject."
        )
    expected_subject = next(iter(expected_subject))
    expected_predicate = set(
        expected_graph.objects(expected_result, RDF_predicate))
    if len(expected_predicate) < 1:
        raise ReportableRuntimeError(
            "Cannot check the expected result, the given expectedResult does not have an rdf:predicate."
        )
    expected_predicate = next(iter(expected_predicate))
    if isinstance(expected_object, Literal):
        found_objs = set(
            data_graph.objects(expected_subject, expected_predicate))
        if len(found_objs) < 1:
            return False
        found = False
        for o in found_objs:
            if isinstance(o, Literal):
                found = 0 == order_graph_literal(expected_graph,
                                                 expected_object, data_graph,
                                                 o)
        return found

    elif isinstance(expected_object, BNode):
        found_objs = set(
            data_graph.objects(expected_subject, expected_predicate))
        if len(found_objs) < 1:
            return False
        found = False
        for o in found_objs:
            if isinstance(o, BNode):
                found = 0 == compare_blank_node(expected_graph,
                                                expected_object, data_graph, o)
        return found
    else:
        found_triples = set(
            data_graph.triples(
                (expected_subject, expected_predicate, expected_object)))
        if len(found_triples) < 1:
            return False
    return True
    def apply_to_shape_via_constraint(self, constraint, shape, **kwargs):
        """

        :param constraint:
        :type constraint: SPARQLConstraintComponent
        :param shape:
        :type shape: pyshacl.shape.Shape
        :param kwargs:
        :return:
        """
        must_be_ask_val = kwargs.pop('must_be_ask_val', False)
        if must_be_ask_val and not (isinstance(self, AskConstraintValidator)):
            # TODO:coverage: No test for this case, do we need to test this?
            raise ConstraintLoadError(
                "Validator not for NodeShape or a PropertyShape must be of type SPARQLAskValidator.",
                "https://www.w3.org/TR/shacl/#ConstraintComponent",
            )
        must_be_select_val = kwargs.pop('must_be_select_val', False)
        if must_be_select_val and not (isinstance(self,
                                                  SelectConstraintValidator)):
            # TODO:coverage: No test for this case, do we need to test this?
            raise ConstraintLoadError(
                "Validator for a NodeShape or a PropertyShape must be of type SPARQLSelectValidator.",
                "https://www.w3.org/TR/shacl/#ConstraintComponent",
            )
        bind_map = {}
        for m in constraint.mandatory_parameters:
            name = constraint.parameter_name(m)
            if name in invalid_parameter_names:
                # TODO:coverage: No test for this case
                raise ReportableRuntimeError(
                    "Parameter name {} cannot be used.".format(name))
            shape_params = set(shape.objects(m.path()))
            if len(shape_params) < 1:
                # TODO:coverage: No test for this case
                raise ReportableRuntimeError(
                    "Shape does not have mandatory parameter {}.".format(
                        str(m.path())))
            # TODO: Can shapes have more than one value for the predicate?
            # Just use one for now.
            bind_map[name] = next(iter(shape_params))
        for o in constraint.optional_parameters:
            name = constraint.parameter_name(o)
            if name in invalid_parameter_names:
                # TODO:coverage: No test for this case
                raise ReportableRuntimeError(
                    "Parameter name {} cannot be used.".format(name))
            shape_params = set(shape.objects(o.path()))
            if len(shape_params) > 0:
                # TODO: Can shapes have more than one value for the predicate?
                # Just use one for now.
                bind_map[name] = next(iter(shape_params))
        return BoundShapeValidatorComponent(constraint, shape, self, bind_map)
Example #7
0
def compare_validation_reports(report_graph, expected_graph, expected_result):
    expected_conforms = expected_graph.objects(expected_result, SH_conforms)
    expected_conforms = set(expected_conforms)
    if len(expected_conforms) < 1:  # pragma: no cover
        raise ReportableRuntimeError(
            "Cannot check the expected result, the given expectedResult does not have an sh:conforms."
        )
    expected_conforms = next(iter(expected_conforms))
    expected_result_nodes = expected_graph.objects(expected_result, SH_result)
    expected_result_nodes = set(expected_result_nodes)
    expected_result_node_count = len(expected_result_nodes)

    validation_reports = report_graph.subjects(RDF_type, SH_ValidationReport)
    validation_reports = set(validation_reports)
    if len(validation_reports) < 1:  # pragma: no cover
        raise ReportableRuntimeError(
            "Cannot check the validation report, the report graph does not contain a ValidationReport"
        )
    validation_report = next(iter(validation_reports))
    clean_validation_reports(report_graph, validation_report, expected_graph,
                             expected_result)
    eq = compare_blank_node(report_graph, validation_report, expected_graph,
                            expected_result)
    if eq != 0:
        return False
    report_conforms = report_graph.objects(validation_report, SH_conforms)
    report_conforms = set(report_conforms)
    if len(report_conforms) < 1:  # pragma: no cover
        raise ReportableRuntimeError(
            "Cannot check the validation report, the report graph does not have an sh:conforms."
        )
    report_conforms = next(iter(report_conforms))

    if bool(expected_conforms.value) != bool(report_conforms.value):
        # TODO:coverage: write a test for this
        log.error(
            "Expected Result Conforms value is different from Validation Report's Conforms value."
        )
        return False

    report_result_nodes = report_graph.objects(validation_report, SH_result)
    report_result_nodes = set(report_result_nodes)
    report_result_node_count = len(report_result_nodes)

    if expected_result_node_count != report_result_node_count:
        # TODO:coverage: write a test for this
        log.error(
            "Number of expected result's sh:result entries is different from Validation Report's sh:result entries.\n"
            "Expected {}, got {}.".format(expected_result_node_count,
                                          report_result_node_count))
        return False
    return True
Example #8
0
def compare_validation_reports(report_graph, expected_graph, expected_result):
    expected_conforms = expected_graph.objects(expected_result, SH_conforms)
    expected_conforms = set(expected_conforms)
    if len(expected_conforms) < 1:
        raise ReportableRuntimeError(
            "Cannot check the expected result, the given expectedResult does not have an sh:conforms."
        )
    expected_conforms = next(iter(expected_conforms))
    expected_result_nodes = expected_graph.objects(expected_result, SH_result)
    expected_result_nodes = set(expected_result_nodes)
    expected_result_node_count = len(expected_result_nodes)

    validation_reports = report_graph.subjects(RDF_type, SH_ValidationReport)
    validation_reports = set(validation_reports)
    if len(validation_reports) < 1:
        raise ReportableRuntimeError(
            "Cannot check the validation report, the report graph does not contain a ValidationReport"
        )
    validation_report = next(iter(validation_reports))
    clean_validation_reports(report_graph, validation_report, expected_graph,
                             expected_result)
    eq = compare_blank_node(report_graph, validation_report, expected_graph,
                            expected_result)
    if eq != 0:
        return False
    report_conforms = report_graph.objects(validation_report, SH_conforms)
    report_conforms = set(report_conforms)
    if len(report_conforms) < 1:
        raise ReportableRuntimeError(
            "Cannot check the validation report, the report graph does not have an sh:conforms."
        )
    report_conforms = next(iter(report_conforms))

    if bool(expected_conforms.value) != bool(report_conforms.value):
        log.error(
            "Expected Result Conforms value is different from Validation Report's Conforms value."
        )
        return False

    report_result_nodes = report_graph.objects(validation_report, SH_result)
    report_result_nodes = set(report_result_nodes)
    report_result_node_count = len(report_result_nodes)

    if expected_result_node_count != report_result_node_count:
        log.error(
            "Number of expected result's sh:result entries is different from Validation Report's sh:result entries.\n"
            "Expected {}, got {}.".format(expected_result_node_count,
                                          report_result_node_count))
        return False
    # Note it is not easily achievable with this method to compare actual result entries, because they are all blank nodes.
    return True
Example #9
0
 def _run_pre_inference(cls,
                        target_graph: GraphLike,
                        inference_option: str,
                        logger: Optional[logging.Logger] = None):
     """
     Note, this is the OWL/RDFS pre-inference,
     it is not the Advanced Spec SHACL-Rule inferencing step.
     :param target_graph:
     :param inference_option:
     :return:
     """
     if logger is None:
         logger = logging.getLogger(__name__)
     try:
         if inference_option == 'rdfs':
             inferencer = owlrl.DeductiveClosure(CustomRDFSSemantics)
         elif inference_option == 'owlrl':
             inferencer = owlrl.DeductiveClosure(owlrl.OWLRL_Semantics)
         elif inference_option == 'both' or inference_option == 'all' or inference_option == 'rdfsowlrl':
             inferencer = owlrl.DeductiveClosure(CustomRDFSOWLRLSemantics)
         else:
             raise ReportableRuntimeError(
                 "Don't know how to do '{}' type inferencing.".format(
                     inference_option))
     except Exception as e:  # pragma: no cover
         logger.error("Error during creation of OWL-RL Deductive Closure")
         if isinstance(e, ReportableRuntimeError):
             raise e
         raise ReportableRuntimeError(
             "Error during creation of OWL-RL Deductive Closure\n"
             "{}".format(str(e.args[0])))
     if isinstance(target_graph, (rdflib.Dataset, rdflib.ConjunctiveGraph)):
         named_graphs = [
             rdflib.Graph(target_graph.store,
                          i,
                          namespace_manager=target_graph.namespace_manager)
             if not isinstance(i, rdflib.Graph) else i
             for i in target_graph.store.contexts(None)
         ]
     else:
         named_graphs = [target_graph]
     try:
         for g in named_graphs:
             inferencer.expand(g)
     except Exception as e:  # pragma: no cover
         logger.error("Error while running OWL-RL Deductive Closure")
         raise ReportableRuntimeError(
             "Error while running OWL-RL Deductive Closure\n"
             "{}".format(str(e.args[0])))
Example #10
0
def check_dash_result(data_graph: GraphLike, report_graph: GraphLike,
                      expected_result_graph: GraphLike):
    DASH = rdflib.namespace.Namespace('http://datashapes.org/dash#')
    DASH_GraphValidationTestCase = DASH.term('GraphValidationTestCase')
    DASH_InferencingTestCase = DASH.term('InferencingTestCase')
    DASH_expectedResult = DASH.term('expectedResult')

    gv_test_cases = expected_result_graph.subjects(
        RDF_type, DASH_GraphValidationTestCase)
    gv_test_cases = set(gv_test_cases)
    inf_test_cases = expected_result_graph.subjects(RDF_type,
                                                    DASH_InferencingTestCase)
    inf_test_cases = set(inf_test_cases)

    if len(gv_test_cases) > 0:
        test_case = next(iter(gv_test_cases))
        expected_results = expected_result_graph.objects(
            test_case, DASH_expectedResult)
        expected_results = set(expected_results)
        if len(expected_results) < 1:  # pragma: no cover
            raise ReportableRuntimeError(
                "Cannot check the expected result, the given GraphValidationTestCase does not have an expectedResult."
            )
        expected_result = next(iter(expected_results))
        gv_res = compare_validation_reports(report_graph,
                                            expected_result_graph,
                                            expected_result)
    else:
        gv_res = True
    if len(inf_test_cases) > 0:
        test_case = next(iter(inf_test_cases))
        expected_results = expected_result_graph.objects(
            test_case, DASH_expectedResult)
        expected_results = set(expected_results)
        if len(expected_results) < 1:  # pragma: no cover
            raise ReportableRuntimeError(
                "Cannot check the expected result, the given InferencingTestCase does not have an expectedResult."
            )
        expected_result = next(iter(expected_results))
        inf_res = compare_inferencing_reports(data_graph,
                                              expected_result_graph,
                                              expected_result)
    else:
        inf_res = True
    if gv_res is None and inf_res is None:  # pragma: no cover
        raise ReportableRuntimeError(
            "Cannot check the expected result, the given expected result graph does not have a GraphValidationTestCase or InferencingTestCase."
        )
    return gv_res and inf_res
    def _evaluate_ltoe(self, lt, target_graph, f_v_dict):
        reports = []
        non_conformant = False
        for f, value_nodes in f_v_dict.items():
            value_node_set = set(value_nodes)
            compare_values = set(target_graph.objects(f, lt))

            for value_node in iter(value_node_set):
                if isinstance(value_node, rdflib.BNode):
                    raise ReportableRuntimeError(
                        "Cannot use sh:lessThanOrEquals to compare a BlankNode."
                    )
                value_is_string = False
                orig_value_node = value_node
                if isinstance(value_node, rdflib.URIRef):
                    value_node = str(value_node)
                    value_is_string = True
                elif isinstance(value_node, rdflib.Literal) and isinstance(
                        value_node.value, str):
                    value_node = value_node.value
                    value_is_string = True

                for compare_value in compare_values:
                    if isinstance(compare_value, rdflib.BNode):
                        raise ReportableRuntimeError(
                            "Cannot use sh:lessThanOrEquals to compare a BlankNode."
                        )
                    compare_is_string = False
                    if isinstance(compare_value, rdflib.URIRef):
                        compare_value = str(compare_value)
                        compare_is_string = True
                    elif isinstance(compare_value,
                                    rdflib.Literal) and isinstance(
                                        compare_value.value, str):
                        compare_value = compare_value.value
                        compare_is_string = True
                    if (value_is_string and not compare_is_string) or (
                            compare_is_string and not value_is_string):
                        non_conformant = True
                    elif not value_node <= compare_value:
                        non_conformant = True
                    else:
                        continue
                    rept = self.make_v_result(target_graph,
                                              f,
                                              value_node=orig_value_node)
                    reports.append(rept)
        return non_conformant, reports
Example #12
0
 def _evaluate_max_rule(self, m_val, f_v_dict):
     reports = []
     non_conformant = False
     assert isinstance(m_val, rdflib.Literal)
     max_is_string = isinstance(m_val.value, str)
     for f, value_nodes in f_v_dict.items():
         for v in value_nodes:
             flag = False
             if isinstance(v, rdflib.BNode):
                 # blank nodes cannot pass val comparison
                 pass
             elif isinstance(v, rdflib.URIRef):
                 # TODO: Don't know if URIRefs can be compared here
                 pass
             elif isinstance(v, rdflib.Literal):
                 v_is_string = isinstance(v.value, str)
                 if max_is_string and not v_is_string:
                     pass
                 elif v_is_string and not max_is_string:
                     pass
                 else:
                     flag = bool(m_val >= v)
             else:
                 raise ReportableRuntimeError(
                     "Not sure how to compare anything else.")
             if not flag:
                 non_conformant = True
                 rept = self.make_v_result(f, value_node=v)
                 reports.append(rept)
     return non_conformant, reports
Example #13
0
 def _evaluate_not_constraint(self, not_c, datagraph, focus_value_nodes,
                              potentially_recursive, _evaluation_path):
     """
     :type not_c: List[Node]
     :type datagraph: rdflib.Graph
     :type focus_value_nodes: dict
     :type potentially_recursive: List
     :type _evaluation_path: List
     """
     _reports = []
     _non_conformant = False
     not_shape = self.shape.get_other_shape(not_c)
     if not not_shape:
         raise ReportableRuntimeError(
             "Shape pointed to by sh:not does not exist or is not a well-formed SHACL Shape."
         )
     if not_shape in potentially_recursive:
         warn(ShapeRecursionWarning(_evaluation_path))
         return _non_conformant, _reports
     for f, value_nodes in focus_value_nodes.items():
         for v in value_nodes:
             try:
                 _is_conform, _r = not_shape.validate(
                     datagraph,
                     focus=v,
                     _evaluation_path=_evaluation_path[:])
             except ValidationFailure as e:
                 raise e
             if _is_conform:
                 # in this case, we _dont_ want to conform!
                 _non_conformant = True
                 rept = self.make_v_result(datagraph, f, value_node=v)
                 _reports.append(rept)
     return _non_conformant, _reports
Example #14
0
 def _evaluate_not_constraint(not_c):
     nonlocal self, shape, target_graph, focus_value_nodes, _evaluation_path
     _reports = []
     _non_conformant = False
     not_shape = shape.get_other_shape(not_c)
     if not not_shape:
         raise ReportableRuntimeError(
             "Shape pointed to by sh:not does not exist or is not " "a well-formed SHACL Shape."
         )
     if not_shape in potentially_recursive:
         warn(ShapeRecursionWarning(_evaluation_path))
         return _non_conformant, _reports
     for f, value_nodes in focus_value_nodes.items():
         for v in value_nodes:
             try:
                 _is_conform, _r = not_shape.validate(
                     target_graph, focus=v, _evaluation_path=_evaluation_path[:]
                 )
             except ValidationFailure as e:
                 raise e
             if _is_conform:
                 # in this case, we _dont_ want to conform!
                 _non_conformant = True
                 rept = self.make_v_result(target_graph, f, value_node=v)
                 _reports.append(rept)
     return _non_conformant, _reports
Example #15
0
 def apply(self, data_graph: 'GraphLike') -> int:
     focus_nodes = self.shape.focus_nodes(data_graph)  # uses target nodes to find focus nodes
     applicable_nodes = self.filter_conditions(focus_nodes, data_graph)
     all_added = 0
     iterate_limit = 100
     while True:
         if iterate_limit < 1:
             raise ReportableRuntimeError("sh:rule iteration exceeded iteration limit of 100.")
         iterate_limit -= 1
         added = 0
         to_add = []
         for a in applicable_nodes:
             s_set = nodes_from_node_expression(self.s, a, data_graph, self.shape.sg)
             p_set = nodes_from_node_expression(self.p, a, data_graph, self.shape.sg)
             o_set = nodes_from_node_expression(self.o, a, data_graph, self.shape.sg)
             new_triples = itertools.product(s_set, p_set, o_set)
             this_added = False
             for i in iter(new_triples):
                 if not this_added and i not in data_graph:
                     this_added = True
                 to_add.append(i)
             if this_added:
                 added += 1
         if added > 0:
             for i in to_add:
                 data_graph.add(cast(Tuple['Node', 'Node', 'Node'], i))
             all_added += added
             if self.iterate:
                 continue  # Jump up to iterate
             else:
                 break  # Don't iterate
         break
     return all_added
Example #16
0
def apply_rules(shapes_rules: Dict, data_graph: GraphLike, iterate=False) -> int:
    # short the shapes dict by shapes sh:order before execution
    sorted_shapes_rules: List[Tuple[Any, Any]] = sorted(shapes_rules.items(), key=lambda x: x[0].order)
    total_modified = 0
    for shape, rules in sorted_shapes_rules:
        # sort the rules by the sh:order before execution
        rules = sorted(rules, key=lambda x: x.order)
        iterate_limit = 100
        while True:
            if iterate_limit < 1:
                raise ReportableRuntimeError("SHACL Shape Rule iteration exceeded iteration limit of 100.")
            iterate_limit -= 1
            this_modified = 0
            for r in rules:
                if r.deactivated:
                    continue
                n_modified = r.apply(data_graph)
                this_modified += n_modified
            if this_modified > 0:
                total_modified += this_modified
                if iterate:
                    continue
                else:
                    break
            break
    return total_modified
 def _evaluate_node_shape(node_shape):
     nonlocal self, target_graph, shape, focus_value_nodes, _evaluation_path
     _reports = []
     _non_conformant = False
     node_shape = shape.get_other_shape(node_shape)
     if node_shape in potentially_recursive:
         warn(ShapeRecursionWarning(_evaluation_path))
         return _non_conformant, _reports
     if not node_shape or node_shape.is_property_shape:
         raise ReportableRuntimeError(
             "Shape pointed to by sh:node does not exist or "
             "is not a well-formed SHACL NodeShape.")
     for f, value_nodes in focus_value_nodes.items():
         for v in value_nodes:
             _is_conform, _r = node_shape.validate(
                 target_graph,
                 focus=v,
                 _evaluation_path=_evaluation_path[:])
             # ignore the fails from the node, create our own fail
             if (not _is_conform) or len(_r) > 0:
                 _non_conformant = True
                 rept = self.make_v_result(target_graph,
                                           f,
                                           value_node=v)
                 _reports.append(rept)
     return _non_conformant, _reports
Example #18
0
 def _evaluate_min_rule(self, m_val, target_graph, f_v_dict):
     reports = []
     non_conformant = False
     assert isinstance(m_val, rdflib.Literal)
     min_is_string = isinstance(m_val.value, str)
     for f, value_nodes in f_v_dict.items():
         for v in value_nodes:
             flag = False
             if isinstance(v, rdflib.BNode):
                 # blank nodes cannot pass val comparison
                 pass
             elif isinstance(v, rdflib.URIRef):
                 # TODO: Don't know if URIRefs can be compared here
                 pass
             elif isinstance(v, rdflib.Literal):
                 v_is_string = isinstance(v.value, str)
                 if min_is_string and not v_is_string:
                     pass
                 elif v_is_string and not min_is_string:
                     pass
                 else:
                     try:
                         # pass if v > m_val
                         cmp = compare_literal(v, m_val)
                         flag = cmp > 0
                     except (TypeError, NotImplementedError):
                         flag = False
             else:
                 raise ReportableRuntimeError(
                     "Not sure how to compare anything else.")
             if not flag:
                 non_conformant = True
                 rept = self.make_v_result(target_graph, f, value_node=v)
                 reports.append(rept)
     return non_conformant, reports
Example #19
0
def check_dash_result(report_graph, expected_result_graph):
    DASH = rdflib.namespace.Namespace('http://datashapes.org/dash#')
    DASH_TestCase = DASH.term('GraphValidationTestCase')
    DASH_expectedResult = DASH.term('expectedResult')

    test_cases = expected_result_graph.subjects(RDF_type, DASH_TestCase)
    test_cases = set(test_cases)
    if len(test_cases) < 1:  # pragma: no cover
        raise ReportableRuntimeError("Cannot check the expected result, the given expected result graph does not have a GraphValidationTestCase.")
    test_case = next(iter(test_cases))
    expected_results = expected_result_graph.objects(test_case, DASH_expectedResult)
    expected_results = set(expected_results)
    if len(expected_results) < 1: # pragma: no cover
        raise ReportableRuntimeError("Cannot check the expected result, the given GraphValidationTestCase does not have an expectedResult.")
    expected_result = next(iter(expected_results))
    return compare_validation_reports(report_graph, expected_result_graph, expected_result)
    def _evaluate_value_shape(self, v_shape, target_graph, f_v_dict):
        reports = []
        non_conformant = False
        other_shape = self.shape.get_other_shape(v_shape)
        if not other_shape:
            raise ReportableRuntimeError(
                "Shape pointed to by sh:property does not "
                "exist or is not a well-formed SHACL Shape.")
        if self.is_disjoint:
            # Textual Definition of Sibling Shapes:
            # Let Q be a shape in shapes graph G that declares a qualified cardinality constraint (by having values for sh:qualifiedValueShape and at least one of sh:qualifiedMinCount or sh:qualifiedMaxCount). Let ps be the set of shapes in G that have Q as a value of sh:property. If Q has true as a value for sh:qualifiedValueShapesDisjoint then the set of sibling shapes for Q is defined as the set of all values of the SPARQL property path sh:property/sh:qualifiedValueShape for any shape in ps minus the value of sh:qualifiedValueShape of Q itself. The set of sibling shapes is empty otherwise.
            sibling_shapes = set()
            parent_shapes = set(
                self.shape.sg.subjects(SH_property, self.shape.node))
            for p in iter(parent_shapes):
                found_siblings = set(self.shape.sg.objects(p, SH_property))
                for s in iter(found_siblings):
                    if s == self.shape.node:
                        continue
                    sibling_shapes.update(
                        self.shape.sg.objects(s, SH_qualifiedValueShape))

            sibling_shapes = set(
                self.shape.get_other_shape(s) for s in sibling_shapes)
        else:
            sibling_shapes = set()
        for f, value_nodes in f_v_dict.items():
            number_conforms = 0
            for v in value_nodes:
                try:
                    _is_conform, _r = other_shape.validate(target_graph,
                                                           focus=v)
                    if _is_conform:
                        _conforms_to_sibling = False
                        for sibling_shape in sibling_shapes:
                            _c2, _r = sibling_shape.validate(target_graph,
                                                             focus=v)
                            _conforms_to_sibling = _conforms_to_sibling or _c2
                        if not _conforms_to_sibling:
                            number_conforms += 1
                except ValidationFailure as v:
                    raise v
            if self.max_count is not None and number_conforms > self.max_count:
                non_conformant = True
                _r = self.make_v_result(
                    target_graph,
                    f,
                    constraint_component=SH_QualifiedMaxCountConstraintComponent
                )
                reports.append(_r)
            if self.min_count is not None and number_conforms < self.min_count:
                non_conformant = True
                _r = self.make_v_result(
                    target_graph,
                    f,
                    constraint_component=SH_QualifiedMinCountConstraintComponent
                )
                reports.append(_r)
        return non_conformant, reports
 def _evaluate_string_rule(self, r, target_graph, f_v_dict):
     reports = []
     non_conformant = False
     languages_need = set()
     sg = self.shape.sg.graph
     try:
         for lang_in in iter(sg.items(r)):
             try:
                 if not isinstance(lang_in,
                                   rdflib.Literal) or not isinstance(
                                       lang_in.value, str):
                     raise ReportableRuntimeError(
                         "All languages in sh:LanugageIn must be a Literal with type xsd:string"
                     )
             except (AssertionError, AttributeError):
                 raise ReportableRuntimeError(
                     "All languages in sh:LanugageIn must be a Literal with type xsd:string"
                 )
             languages_need.add(str(lang_in.value).lower())
     except (KeyError, AttributeError, ValueError):
         raise ReportableRuntimeError(
             "Value of sh:LanguageIn must be a RDF List")
     wildcard = False
     if '*' in languages_need:
         wildcard = True
     for f, value_nodes in f_v_dict.items():
         for v in value_nodes:
             flag = False
             if isinstance(v, rdflib.Literal):
                 lang = v.language
                 if lang:
                     if wildcard:
                         flag = True
                     elif str(lang).lower() in languages_need:
                         flag = True
                     else:
                         lang_parts = str(lang).split('-')
                         first_part = lang_parts[0]
                         if str(first_part).lower() in languages_need:
                             flag = True
             if not flag:
                 non_conformant = True
                 rept = self.make_v_result(target_graph, f, value_node=v)
                 reports.append(rept)
     return non_conformant, reports
Example #22
0
 def execute(self, g, *args):
     params = self.get_params_in_order()
     if len(args) != len(params):
         raise ReportableRuntimeError(
             "Got incorrect number of arguments for JSFunction {}.".format(
                 self.node))
     args_map = {}
     for i, p in enumerate(params):
         arg = args[i]
         ln = p.localname
         if arg is None and p.optional is False:
             raise ReportableRuntimeError(
                 "Got NoneType for Non-optional argument {}.".format(ln))
         args_map[ln] = arg
     results = self.js_exe.execute(g,
                                   args_map,
                                   mode="function",
                                   return_type=self.rtype)
     res = results['_result']
     return res
Example #23
0
 def apply(self, data_graph: 'GraphLike') -> int:
     focus_nodes = self.shape.focus_nodes(data_graph)  # uses target nodes to find focus nodes
     all_added = 0
     SPARQLQueryHelper = get_query_helper_cls()
     iterate_limit = 100
     while True:
         if iterate_limit < 1:
             raise ReportableRuntimeError("Local rule iteration exceeded iteration limit of 100.")
         iterate_limit -= 1
         added = 0
         applicable_nodes = self.filter_conditions(focus_nodes, data_graph)
         construct_graphs = set()
         for a in applicable_nodes:
             for c in self._constructs:
                 init_bindings = {}
                 found_this = SPARQLQueryHelper.bind_this_regex.search(c)
                 if found_this:
                     init_bindings['this'] = a
                 c = self._qh.apply_prefixes(c)
                 results = data_graph.query(c, initBindings=init_bindings)
                 if results.type != "CONSTRUCT":
                     raise ReportableRuntimeError("Query executed by a SHACL SPARQLRule must be CONSTRUCT query.")
                 this_added = False
                 for i in results.graph:
                     if not this_added and i not in data_graph:
                         this_added = True
                         # We only need to know at least one triple was added, then break!
                         break
                 if this_added:
                     added += 1
                     construct_graphs.add(results.graph)
         if added > 0:
             for g in construct_graphs:
                 data_graph = clone_graph(g, target_graph=data_graph)
             all_added += added
             if self.iterate:
                 continue  # Jump up to iterate
             else:
                 break  # Don't iterate
         break  # We've reached a local steady state
     return all_added
Example #24
0
 def parameter_name(cls, parameter):
     path = str(parameter.path())
     hash_index = path.find('#')
     if hash_index > 0:
         ending = path[hash_index + 1:]
         return ending
     right_slash_index = path.rfind('/')
     if right_slash_index > 0:
         ending = path[right_slash_index + 1:]
         return ending
     raise ReportableRuntimeError(
         "Cannot get a local name for {}".format(path))
Example #25
0
 def bind_params(self):
     bind_map = {}
     shape = self.shape
     for p in self.constraint.parameters:
         name = p.localname
         if name in self.invalid_parameter_names:
             # TODO:coverage: No test for this case
             raise ReportableRuntimeError(
                 "Parameter name {} cannot be used.".format(name))
         shape_params = set(shape.objects(p.path()))
         if len(shape_params) < 1:
             if not p.optional:
                 # TODO:coverage: No test for this case
                 raise ReportableRuntimeError(
                     "Shape does not have mandatory parameter {}.".format(
                         str(p.path())))
             continue
         # TODO: Can shapes have more than one value for the predicate?
         # Just use one for now.
         # TODO: Check for sh:class and sh:nodeKind on the found param value
         bind_map[name] = next(iter(shape_params))
     self.param_bind_map = bind_map
 def parameter_name(cls, parameter):
     path = str(parameter.path())
     hash_index = path.find('#')
     if hash_index > 0:
         ending = path[hash_index + 1:]
         return ending
     right_slash_index = path.rfind('/')
     if right_slash_index > 0:
         # TODO:coverage: No test for this case where path has a right slash
         ending = path[right_slash_index + 1:]
         return ending
     raise ReportableRuntimeError(
         "Cannot get a local name for {}".format(path))
Example #27
0
 def get_fn_args(self, fn_name, args_map):
     c = self.context
     try:
         fn = c.get_global(fn_name)
     except BaseException as e:
         print(e)
         raise
     if fn is None:
         raise ReportableRuntimeError(
             "JS Function {} cannot be found in the loaded files.".format(
                 fn_name))
     if fn_name not in self.fns:
         raise ReportableRuntimeError(
             "JS Function {} args cannot be determined. Bad JS structure?".
             format(fn_name))
     known_fn_args = self.fns[fn_name]  # type: tuple
     needed_args = []
     for k, v in args_map.items():
         look_for = "$" + str(k)
         positions = []
         start = 0
         while True:
             try:
                 pos = known_fn_args.index(look_for, start)
                 positions.append(pos)
             except ValueError:
                 break
             start = pos + 1
         if not positions:
             continue
         for p in positions:
             needed_args.append((p, k, v))
     for i, a in enumerate(known_fn_args):
         if a.startswith("$"):
             a = a[1:]
         if a not in args_map:
             needed_args.append((i, a, None))
     needed_args = [v for p, k, v in sorted(needed_args)]
     return needed_args
Example #28
0
 def _evaluate_property_shape(self, prop_shape, target_graph, f_v_dict):
     reports = []
     non_conformant = False
     prop_shape = self.shape.get_other_shape(prop_shape)
     if not prop_shape or not prop_shape.is_property_shape:
         raise ReportableRuntimeError(
             "Shape pointed to by sh:property does not exist "
             "or is not a well-formed SHACL PropertyShape.")
     for f, value_nodes in f_v_dict.items():
         for v in value_nodes:
             _is_conform, _r = prop_shape.validate(target_graph, focus=v)
             non_conformant = non_conformant or (not _is_conform)
             reports.extend(_r)
     return non_conformant, reports
Example #29
0
def _load_into_graph(target, rdf_format=None):
    if isinstance(target, rdflib.Graph):
        return target
    target_is_open = False
    target_is_file = False
    target_is_text = False
    filename = None
    if isinstance(target, IOBase) and hasattr(target, 'read'):
        target_is_file = True
        target_is_open = True
        filename = target.name
    elif isinstance(target, str):
        if target.startswith('file://'):
            target_is_file = True
            filename = target[7:]
        elif len(target) < 240:
            target_is_file = True
            filename = target
        if not target_is_file:
            target_is_text = True
    else:
        raise ReportableRuntimeError(
            "Cannot determine the format of the input graph")
    if filename:
        if filename.endswith('.ttl'):
            rdf_format = rdf_format or 'turtle'
        if filename.endswith('.nt'):
            rdf_format = rdf_format or 'nt'
        elif filename.endswith('.xml'):
            rdf_format = rdf_format or 'xml'
        elif filename.endswith('.json'):
            rdf_format = rdf_format or 'json-ld'
    g = rdflib.Graph()
    if target_is_file and filename and not target_is_open:
        import os
        filename = os.path.abspath(filename)
        target = open(filename, mode='rb')
        target_is_open = True
    if target_is_open:
        g.parse(source=None,
                publicID=None,
                format=rdf_format,
                location=None,
                file=target)
        target.close()
    elif target_is_text:
        g.parse(data=target, format=rdf_format)
    return g
    def evaluate(self, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List):
        """
        :type target_graph: rdflib.Graph
        :type focus_value_nodes: dict
        :type _evaluation_path: list
        """
        reports = []
        non_conformant = False

        for lt in iter(self.property_compare_set):
            if isinstance(lt, rdflib.Literal) or isinstance(lt, rdflib.BNode):
                raise ReportableRuntimeError("Value of sh:lessThanOrEquals MUST be a URI Identifier.")
            _nc, _r = self._evaluate_ltoe(lt, target_graph, focus_value_nodes)
            non_conformant = non_conformant or _nc
            reports.extend(_r)
        return (not non_conformant), reports