def __init__(self, shape): super(ClosedConstraintComponent, self).__init__(shape) sg = self.shape.sg.graph closed_vals = list(self.shape.objects(SH_closed)) if len(closed_vals) < 1: raise ConstraintLoadError( "ClosedConstraintComponent must have at least one sh:closed predicate.", "https://www.w3.org/TR/shacl/#ClosedConstraintComponent") elif len(closed_vals) > 1: raise ConstraintLoadError( "ClosedConstraintComponent must have at most one sh:closed predicate.", "https://www.w3.org/TR/shacl/#ClosedConstraintComponent") assert isinstance( closed_vals[0], rdflib.Literal), "sh:closed must take a xsd:boolean literal." self.is_closed = bool(closed_vals[0].value) ignored_vals = list(self.shape.objects(SH_ignoredProperties)) self.ignored_props = set() for i in ignored_vals: try: items = set(sg.items(i)) for list_item in items: self.ignored_props.add(list_item) except ValueError: continue self.property_shapes = list(self.shape.objects(SH_property))
def _find_custom_constraints(self): g = self.graph constraint_component_set = set( g.subjects(RDF_type, SH_ConstraintComponent)) constraint_subclasses = set( g.subjects(RDFS_subClassOf, SH_ConstraintComponent)) for sc in iter(constraint_subclasses): subclass_components = set(g.subjects(RDF_type, sc)) constraint_component_set.update(subclass_components) components = set() for c in iter(constraint_component_set): optional_params = [] mandatory_params = [] param_nodes = set(g.objects(c, SH_parameter)) if len(param_nodes) < 1: raise ConstraintLoadError( "A sh:ConstraintComponent must have at least one value for sh:parameter", "https://www.w3.org/TR/shacl/#constraint-components-parameters" ) for p in iter(param_nodes): path_nodes = set(g.objects(p, SH_path)) if len(path_nodes) < 1: raise ConstraintLoadError( "A sh:ConstraintComponent parameter value must have at least one value for sh:path", "https://www.w3.org/TR/shacl/#constraint-components-parameters" ) elif len(path_nodes) > 1: raise ConstraintLoadError( "A sh:ConstraintComponent parameter value must have at most one value for sh:path", "https://www.w3.org/TR/shacl/#constraint-components-parameters" ) path = next(iter(path_nodes)) is_optional = False optional = set(g.objects(p, SH_optional)) for o in iter(optional): if not (isinstance(o, rdflib.Literal) and isinstance(o.value, bool)): raise ConstraintLoadError( "A sh:Parameter value for sh:optional must be a valid RDF Literal of type xsd:boolean.", "https://www.w3.org/TR/shacl/#constraint-components-parameters" ) is_optional = o.value parameter = Shape(self, p=True, node=p, path=path, logger=self.logger) if is_optional: optional_params.append(parameter) else: mandatory_params.append(parameter) if len(mandatory_params) < 1: raise ConstraintLoadError( "A sh:ConstraintComponent must have at least one non-optional parameter.", "https://www.w3.org/TR/shacl/#constraint-components-parameters" ) component = SPARQLConstraintComponent(self, c, mandatory_params, optional_params) components.add(component) return components
def apply_to_shape_via_constraint( self, constraint, shape, **kwargs) -> BoundShapeValidatorComponent: """ Create a new Custom Constraint (BoundShapeValidatorComponent) :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", ) return BoundShapeValidatorComponent(constraint, shape, self)
def __init__(self, shape): super(UniqueLangConstraintComponent, self).__init__(shape) self.allow_multi_rules = False is_unique_lang = set(self.shape.objects(SH_uniqueLang)) if len(is_unique_lang) < 1: raise ConstraintLoadError( "UniqueLangConstraintComponent must have at least one sh:uniqueLang predicate.", "https://www.w3.org/TR/shacl/#UniqueLangConstraintComponent") elif len(is_unique_lang) > 1: raise ConstraintLoadError( "UniqueLangConstraintComponent must have at most one sh:uniqueLang predicate.", "https://www.w3.org/TR/shacl/#UniqueLangConstraintComponent") if not shape.is_property_shape: raise ConstraintLoadError( "UniqueLangConstraintComponent can only be present on a PropertyShape, not a NodeShape.", "https://www.w3.org/TR/shacl/#UniqueLangConstraintComponent") is_unique_lang = next(iter(is_unique_lang)) try: assert isinstance(is_unique_lang, rdflib.Literal) assert isinstance(is_unique_lang.value, bool) except (AssertionError, AttributeError): raise ConstraintLoadError( "UniqueLangConstraintComponent must have an RDF Literal of type boolean as its sh:uniqueLang.", "https://www.w3.org/TR/shacl/#UniqueLangConstraintComponent") self.string_rules = {is_unique_lang.value}
def __init__(self, shape): super(MinCountConstraintComponent, self).__init__(shape) min_count = list(self.shape.objects(SH_minCount)) if len(min_count) < 1: raise ConstraintLoadError( "MinCountConstraintComponent must have at least one sh:minCount predicate.", "https://www.w3.org/TR/shacl/#MinCountConstraintComponent", ) if len(min_count) > 1: raise ConstraintLoadError( "MinCountConstraintComponent must have at most one sh:minCount predicate.", "https://www.w3.org/TR/shacl/#MinCountConstraintComponent", ) if not shape.is_property_shape: raise ConstraintLoadError( "MinCountConstraintComponent can only be present on a PropertyShape, not a NodeShape.", "https://www.w3.org/TR/shacl/#MinCountConstraintComponent", ) self.min_count = min_count[0] if not (isinstance(self.min_count, Literal) and self.min_count.datatype == XSD_integer): raise ConstraintLoadError( "MinCountConstraintComponent sh:minCount must be a literal with datatype xsd:integer.", "https://www.w3.org/TR/shacl/#MinCountConstraintComponent", ) if int(self.min_count.value) < 0: raise ConstraintLoadError( "MinCountConstraintComponent sh:minCount must be an integer >= 0.", "https://www.w3.org/TR/shacl/#MinCountConstraintComponent", )
def __init__(self, shape): super(QualifiedValueShapeConstraintComponent, self).__init__(shape) if not shape.is_property_shape: # Note, this no longer throws an error, this constraint is simply ignored on NodeShapes. raise ConstraintLoadWarning( "QualifiedValueShapeConstraintComponent can only be present on a PropertyShape, not a NodeShape.", "https://www.w3.org/TR/shacl/#QualifiedValueShapeConstraintComponent" ) value_shapes = set(self.shape.objects(SH_qualifiedValueShape)) if len(value_shapes) < 1: raise ConstraintLoadError( "QualifiedValueShapeConstraintComponent must have at least one sh:qualifiedValueShape predicate.", "https://www.w3.org/TR/shacl/#QualifiedValueShapeConstraintComponent" ) self.value_shapes = value_shapes min_count = set(self.shape.objects(SH_qualifiedMinCount)) if len(min_count) < 1: min_count = None elif len(min_count) > 1: raise ConstraintLoadError( "QualifiedMinCountConstraintComponent must have at most one sh:qualifiedMinCount predicate.", "https://www.w3.org/TR/shacl/#QualifiedValueShapeConstraintComponent" ) else: min_count = next(iter(min_count)) assert isinstance(min_count, rdflib.Literal) and isinstance( min_count.value, int) min_count = min_count.value max_count = set(self.shape.objects(SH_qualifiedMaxCount)) if len(max_count) < 1: max_count = None elif len(max_count) > 1: raise ConstraintLoadError( "QualifiedMaxCountConstraintComponent must have at most one sh:qualifiedMaxCount predicate.", "https://www.w3.org/TR/shacl/#QualifiedValueShapeConstraintComponent" ) else: max_count = next(iter(max_count)) assert isinstance(max_count, rdflib.Literal) and isinstance( max_count.value, int) max_count = max_count.value if min_count is None and max_count is None: raise ConstraintLoadError( "QualifiedValueShapeConstraintComponent must have at lease one sh:qualifiedMinCount or " "sh:qualifiedMaxCount", "https://www.w3.org/TR/shacl/#QualifiedValueShapeConstraintComponent" ) is_disjoint = False disjoint_nodes = set( self.shape.objects(SH_qualifiedValueShapesDisjoint)) for d in disjoint_nodes: if isinstance(d, rdflib.Literal): if isinstance(d.value, bool): is_disjoint = is_disjoint or d.value self.min_count = min_count self.max_count = max_count self.is_disjoint = is_disjoint
def collect_prefixes(self): sg = self.shape.sg.graph prefixes_vals = set(sg.objects(self.node, SH_prefixes)) if len(prefixes_vals) < 1: return named_graph = sg.identifier if named_graph: ng_declares = set(sg.objects(named_graph, SH_declare)) else: ng_declares = set() onts = set(sg.subjects(RDF_type, OWL_Ontology)) ont_declares = set() for o in onts: ont_declares.update(set(sg.objects(o, SH_declare))) global_declares = ng_declares.union(ont_declares) for prefixes_val in iter(prefixes_vals): pfx_declares = set(sg.objects(prefixes_val, SH_declare)) all_declares = global_declares.union(pfx_declares) for dec in iter(all_declares): if isinstance(dec, rdflib.Literal): raise ConstraintLoadError( "sh:declare value must be either a URIRef or a BNode.", "https://www.w3.org/TR/shacl/#sparql-prefixes", ) prefix_vals = set(sg.objects(dec, SH_prefix)) if len(prefix_vals) < 1 or len(prefix_vals) > 1: raise ConstraintLoadError( "sh:declare must have exactly one sh:prefix predicate.", "https://www.w3.org/TR/shacl/#sparql-prefixes", ) prefix = next(iter(prefix_vals)) if not (isinstance(prefix, rdflib.Literal) and isinstance(prefix.value, str)): raise ConstraintLoadError( "sh:prefix value must be an RDF Literal with type xsd:string.", "https://www.w3.org/TR/shacl/#sparql-prefixes", ) prefix = str(prefix.value) namespace_vals = set(sg.objects(dec, SH_namespace)) if len(namespace_vals) < 1 or len(namespace_vals) > 1: raise ConstraintLoadError( "sh:declare must have exactly one sh:namespace predicate.", "https://www.w3.org/TR/shacl/#sparql-prefixes", ) namespace = next(iter(namespace_vals)) if not (isinstance(namespace, rdflib.Literal) and namespace.datatype == XSD.anyURI): raise ConstraintLoadError( "sh:namespace value must be an RDF Literal with type xsd:anyURI.", "https://www.w3.org/TR/shacl/#sparql-prefixes", ) namespace = rdflib.URIRef(str(namespace.value)) self.prefixes[prefix] = namespace
def __init__(self, shape): super(DatatypeConstraintComponent, self).__init__(shape) datatype_rules = list(self.shape.objects(SH_datatype)) if len(datatype_rules) < 1: raise ConstraintLoadError( "DatatypeConstraintComponent must have at least one sh:datatype predicate.", "https://www.w3.org/TR/shacl/#DatatypeConstraintComponent") elif len(datatype_rules) > 1: raise ConstraintLoadError( "DatatypeConstraintComponent must have at most one sh:datatype predicate.", "https://www.w3.org/TR/shacl/#DatatypeConstraintComponent") self.datatype_rule = datatype_rules[0]
def __init__(self, shape): super(LessThanConstraintComponent, self).__init__(shape) property_compare_set = set(self.shape.objects(SH_lessThan)) if len(property_compare_set) < 1: raise ConstraintLoadError( "LessThanConstraintComponent must have at least one sh:lessThan predicate.", "https://www.w3.org/TR/shacl/#LessThanConstraintComponent") if not shape.is_property_shape: raise ConstraintLoadError( "LessThanConstraintComponent can only be present on a PropertyShape, not a NodeShape.", "https://www.w3.org/TR/shacl/#LessThanConstraintComponent") self.property_compare_set = property_compare_set
def __init__(self, shape): super(InConstraintComponent, self).__init__(shape) in_vals = list(self.shape.objects(SH_in)) if len(in_vals) < 1: raise ConstraintLoadError( "InConstraintComponent must have at least one sh:in predicate.", "https://www.w3.org/TR/shacl/#InConstraintComponent") elif len(in_vals) > 1: raise ConstraintLoadError( "InConstraintComponent must have at most one sh:in predicate.", "https://www.w3.org/TR/shacl/#InConstraintComponent") self.in_list = in_vals[0]
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)
def __init__(self, shape): super(NotConstraintComponent, self).__init__(shape) not_list = list(self.shape.objects(SH_not)) if len(not_list) < 1: raise ConstraintLoadError( "NotConstraintComponent must have at least one sh:not predicate.", "https://www.w3.org/TR/shacl/#NotConstraintComponent") if len(not_list) > 1: raise ConstraintLoadError( "NotConstraintComponent must have at most one sh:not predicate.", "https://www.w3.org/TR/shacl/#NotConstraintComponent") self.not_list = not_list
def __init__(self, shape): super(NodeKindConstraintComponent, self).__init__(shape) nodekind_rules = list(self.shape.objects(SH_nodeKind)) if len(nodekind_rules) < 1: raise ConstraintLoadError( "NodeKindConstraintComponent must have at least one sh:nodeKind predicate.", "https://www.w3.org/TR/shacl/#NodeKindConstraintComponent") elif len(nodekind_rules) > 1: raise ConstraintLoadError( "NodeKindConstraintComponent must have at most one sh:nodeKind predicate.", "https://www.w3.org/TR/shacl/#NodeKindConstraintComponent") self.nodekind_rule = nodekind_rules[0]
def __init__(self, shape): super(MinLengthConstraintComponent, self).__init__(shape) self.allow_multi_rules = False patterns_found = list(self.shape.objects(SH_minLength)) if len(patterns_found) < 1: raise ConstraintLoadError( "MinLengthConstraintComponent must have at least one sh:minLength predicate.", "https://www.w3.org/TR/shacl/#MinLengthConstraintComponent") elif len(patterns_found) > 1: raise ConstraintLoadError( "MinLengthConstraintComponent must have at most one sh:minLength predicate.", "https://www.w3.org/TR/shacl/#MinLengthConstraintComponent") self.string_rules = patterns_found
def __init__(self, shape): super(LanguageInConstraintComponent, self).__init__(shape) self.allow_multi_rules = False language_ins_found = list(self.shape.objects(SH_languageIn)) if len(language_ins_found) < 1: raise ConstraintLoadError( "LanguageInConstraintComponent must have at least one sh:languageIn predicate.", "https://www.w3.org/TR/shacl/#LanguageInConstraintComponent") elif len(language_ins_found) > 1: raise ConstraintLoadError( "LanguageInConstraintComponent must have at most one sh:languageIn predicate.", "https://www.w3.org/TR/shacl/#LanguageInConstraintComponent") self.string_rules = language_ins_found
def __init__(self, shapes_graph: 'ShapesGraph', node): super(JSConstraintImpl, self).__init__(shapes_graph, node) msgs_iter = shapes_graph.objects(node, SH_message) self.messages = [] for m in msgs_iter: if not isinstance(m, Literal): raise ConstraintLoadError( "JSConstraint sh:message must be a RDF Literal.", "https://www.w3.org/TR/shacl-js/#js-constraints", ) if not isinstance(m.value, str): raise ConstraintLoadError( "JSConstraint sh:message must be a RDF Literal with type string.", "https://www.w3.org/TR/shacl-js/#js-constraints", ) self.messages.append(m)
def __init__(self, shacl_graph, node, *args, **kwargs): super(SelectConstraintValidator, self).__init__(shacl_graph, node, **kwargs) g = shacl_graph.graph select_vals = set(g.objects(node, SH_select)) if len(select_vals) < 1 or len(select_vals) > 1: raise ConstraintLoadError( "SelectValidator must have exactly one value for sh:select.", "https://www.w3.org/TR/shacl/#ConstraintComponent") select_val = next(iter(select_vals)) if not (isinstance(select_val, rdflib.Literal) and isinstance(select_val.value, str)): raise ConstraintLoadError( "SelectValidator sh:select must be an RDF Literal of type xsd:string.", "https://www.w3.org/TR/shacl/#ConstraintComponent") self.query_text = select_val.value
def make_validator_for_shape(self, shape: 'Shape'): """ :param shape: :type shape: Shape :return: """ val_count = len(self.validators) node_val_count = len(self.node_validators) prop_val_count = len(self.property_validators) must_be_select_val = False must_be_ask_val = False if shape.is_property_shape and prop_val_count > 0: validator_node = next(iter(self.property_validators)) must_be_select_val = True elif (not shape.is_property_shape) and node_val_count > 0: validator_node = next(iter(self.node_validators)) must_be_select_val = True elif val_count > 0: validator_node = next(iter(self.validators)) must_be_ask_val = True else: raise ConstraintLoadError( "Cannot select a validator to use, according to the rules.", "https://www.w3.org/TR/shacl/#constraint-components-validators", ) validator = SPARQLConstraintComponentValidator(self.sg, validator_node) applied_validator = validator.apply_to_shape_via_constraint( self, shape, must_be_ask_val=must_be_ask_val, must_be_select_val=must_be_select_val) return applied_validator
def __new__(cls, shacl_graph: 'ShapesGraph', node, *args, **kwargs): cache_key = (id(shacl_graph.graph), str(node)) found_in_cache = cls.validator_cache.get(cache_key, False) if found_in_cache: return found_in_cache sg = shacl_graph.graph type_vals = set(sg.objects(node, RDF_type)) validator_type: Union[Type[SelectConstraintValidator], Type[AskConstraintValidator], None] = None if len(type_vals) > 0: if SH_SPARQLSelectValidator in type_vals: validator_type = SelectConstraintValidator elif SH_SPARQLAskValidator in type_vals: validator_type = AskConstraintValidator if not validator_type: sel_nodes = set(sg.objects(node, SH_select)) if len(sel_nodes) > 0: # TODO:coverage: No test for this case validator_type = SelectConstraintValidator if not validator_type: ask_nodes = set(sg.objects(node, SH_ask)) if len(ask_nodes) > 0: validator_type = AskConstraintValidator if not validator_type: # TODO:coverage: No test for this case raise ConstraintLoadError( "Validator must be of type sh:SPARQLSelectValidator or sh:SPARQLAskValidator and must have either a sh:select or a sh:ask predicate.", "https://www.w3.org/TR/shacl/#ConstraintComponent", ) validator = validator_type(shacl_graph, node, *args, **kwargs) cls.validator_cache[cache_key] = validator return validator
def __init__(self, shape): super(XoneConstraintComponent, self).__init__(shape) xone_nodes = list(self.shape.objects(SH_xone)) if len(xone_nodes) < 1: raise ConstraintLoadError( "XoneConstraintComponent must have at least one sh:xone predicate.", "https://www.w3.org/TR/shacl/#XoneConstraintComponent") self.xone_nodes = xone_nodes
def __init__(self, shape: 'Shape'): super(ExpressionConstraint, self).__init__(shape) self.expr_nodes = list(self.shape.objects(SH_expression)) if len(self.expr_nodes) < 1: raise ConstraintLoadError( "ExpressionConstraintComponent must have at least one sh:expression predicate.", "https://www.w3.org/TR/shacl-af/#ExpressionConstraintComponent", )
def __init__(self, shape): super(DisjointConstraintComponent, self).__init__(shape) property_compare_set = set(self.shape.objects(SH_disjoint)) if len(property_compare_set) < 1: raise ConstraintLoadError( "DisjointConstraintComponent must have at least one sh:disjoint predicate.", "https://www.w3.org/TR/shacl/#DisjointConstraintComponent") self.property_compare_set = property_compare_set
def __init__(self, shape): super(PropertyConstraintComponent, self).__init__(shape) property_shapes = list(self.shape.objects(SH_property)) if len(property_shapes) < 1: raise ConstraintLoadError( "PropertyConstraintComponent must have at least one sh:property predicate.", "https://www.w3.org/TR/shacl/#PropertyConstraintComponent") self.property_shapes = property_shapes
def __init__(self, shape): super(HasValueConstraintComponent, self).__init__(shape) has_value_set = set(self.shape.objects(SH_hasValue)) if len(has_value_set) < 1: raise ConstraintLoadError( "HasValueConstraintComponent must have at least one sh:hasValue predicate.", "https://www.w3.org/TR/shacl/#HasValueConstraintComponent") self.has_value_set = has_value_set
def __init__(self, shape): super(ClassConstraintComponent, self).__init__(shape) class_rules = list(self.shape.objects(SH_class)) if len(class_rules) < 1: raise ConstraintLoadError( "ClassConstraintComponent must have at least one sh:class predicate.", "https://www.w3.org/TR/shacl/#ClassConstraintComponent") self.class_rules = class_rules
def __init__(self, shape): super(OrConstraintComponent, self).__init__(shape) or_list = list(self.shape.objects(SH_or)) if len(or_list) < 1: raise ConstraintLoadError( "OrConstraintComponent must have at least one sh:or predicate.", "https://www.w3.org/TR/shacl/#OrConstraintComponent") self.or_list = or_list
def __init__(self, shape): super(MaxInclusiveConstraintComponent, self).__init__(shape) max_vals = list(self.shape.objects(SH_maxInclusive)) if len(max_vals) < 1: raise ConstraintLoadError( "MaxInclusiveConstraintComponent must have at least one sh:minInclusive predicate.", "https://www.w3.org/TR/shacl/#MaxInclusiveConstraintComponent") self.max_vals = max_vals
def __init__(self, shape): super(AndConstraintComponent, self).__init__(shape) and_list = list(self.shape.objects(SH_and)) if len(and_list) < 1: raise ConstraintLoadError( "AndConstraintComponent must have at least one sh:and predicate.", "https://www.w3.org/TR/shacl/#AndConstraintComponent") self.and_list = and_list
def __init__(self, shape): super(NodeShapeComponent, self).__init__(shape) node_shapes = list(self.shape.objects(SH_node)) if len(node_shapes) < 1: raise ConstraintLoadError( "NodeShapeComponent must have at least one sh:node predicate.", "https://www.w3.org/TR/shacl/#NodeShapeComponent") self.node_shapes = node_shapes
def __init__(self, shacl_graph, node, *args, **kwargs): super(AskConstraintValidator, self).__init__(shacl_graph, node, **kwargs) g = shacl_graph.graph ask_vals = set(g.objects(node, SH_ask)) if len(ask_vals) < 1 or len(ask_vals) > 1: # TODO:coverage: No test for this case raise ConstraintLoadError( "AskValidator must have exactly one value for sh:ask.", "https://www.w3.org/TR/shacl/#ConstraintComponent") ask_val = next(iter(ask_vals)) if not (isinstance(ask_val, rdflib.Literal) and isinstance(ask_val.value, str)): # TODO:coverage: No test for this case raise ConstraintLoadError( "AskValidator sh:ask must be an RDF Literal of type xsd:string.", "https://www.w3.org/TR/shacl/#ConstraintComponent") self.query_text = ask_val.value