Exemplo n.º 1
0
from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import SH, RDFS_subClassOf, RDF_type,\
    SH_IRI, SH_BlankNode, SH_Literal, SH_IRIOrLiteral, SH_BlankNodeOrIRI,\
    SH_BlankNodeORLiteral
from pyshacl.errors import ConstraintLoadError

RDF_langString = RDF.term('langString')
XSD_string = XSD.term('string')
XSD_integer = XSD.term('integer')
XSD_float = XSD.term('float')
XSD_boolean = XSD.term('boolean')
XSD_date = XSD.term('date')
XSD_time = XSD.term('time')
XSD_dateTime = XSD.term('dateTime')

SH_class = SH.term('class')
SH_datatype = SH.term('datatype')
SH_nodeKind = SH.term('nodeKind')
SH_ClassConstraintComponent = SH.term('ClassConstraintComponent')
SH_DatatypeConstraintComponent = SH.term('DatatypeConstraintComponent')
SH_NodeKindConstraintComponent = SH.term('NodeKindConstraintComponent')


class ClassConstraintComponent(ConstraintComponent):
    """
    The condition specified by sh:class is that each value node is a SHACL instance of a given type.
    Link:
    https://www.w3.org/TR/shacl/#ClassConstraintComponent
    Textual Definition:
    For each value node that is either a literal, or a non-literal that is not a SHACL instance of $class in the data graph, there is a validation result with the value node as sh:value.
    """
Exemplo n.º 2
0
# -*- coding: utf-8 -*-
"""
https://www.w3.org/TR/shacl/#core-components-property-pairs
"""
import rdflib
from rdflib.term import Literal
from rdflib.namespace import XSD
from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import SH
from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError

SH_equals = SH.term('equals')
SH_disjoint = SH.term('disjoint')
SH_lessThan = SH.term('lessThan')
SH_lessThanOrEquals = SH.term('lessThanOrEquals')

SH_EqualsConstraintComponent = SH.term('EqualsConstraintComponent')
SH_DisjointConstraintComponent = SH.term('DisjointConstraintComponent')
SH_LessThanConstraintComponent = SH.term('LessThanConstraintComponent')
SH_LessThanOrEqualsConstraintComponent = SH.term(
    'LessThanOrEqualsConstraintComponent')


class EqualsConstraintComponent(ConstraintComponent):
    """
    sh:equals specifies the condition that the set of all value nodes is equal to the set of objects of the triples that have the focus node as subject and the value of sh:equals as predicate.
    Link:
    https://www.w3.org/TR/shacl/#EqualsConstraintComponent
    Textual Definition:
    For each value node that does not exist as a value of the property $equals at the focus node, there is a validation result with the value node as sh:value. For each value of the property $equals at the focus node that is not one of the value nodes, there is a validation result with the value as sh:value.
    """
Exemplo n.º 3
0
        desc = self.make_v_result_description(
            datagraph,
            focus_node,
            severity,
            value_node,
            messages,
            result_path=result_path,
            constraint_component=constraint_component,
            source_constraint=source_constraint,
            extra_messages=extra_messages,
        )
        self.shape.logger.debug(desc)
        return desc, r_node, r_triples


SH_nodeValidator = SH.term('nodeValidator')
SH_propertyValidator = SH.term('propertyValidator')
SH_validator = SH.term('validator')
SH_optional = SH.term('optional')
SH_SPARQLSelectValidator = SH.term('SPARQLSelectValidator')
SH_SPARQLAskValidator = SH.term('SPARQLAskValidator')
SH_JSValidator = SH.term('JSValidator')


class CustomConstraintComponentFactory(object):
    __slots__: Tuple = tuple()

    def __new__(cls, shacl_graph: 'ShapesGraph', node):
        self: List[Any] = list()
        self.append(shacl_graph)
        self.append(node)
Exemplo n.º 4
0
"""
https://www.w3.org/TR/shacl/#core-components-range
"""

from typing import Dict, List

import rdflib

from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import SH
from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError
from pyshacl.pytypes import GraphLike
from pyshacl.rdfutil import stringify_node
from pyshacl.rdfutil.compare import compare_literal

SH_MinExclusiveConstraintComponent = SH.term('MinExclusiveConstraintComponent')
SH_MinInclusiveConstraintComponent = SH.term('MinInclusiveConstraintComponent')
SH_minExclusive = SH.term('minExclusive')
SH_minInclusive = SH.term('minInclusive')
SH_MaxExclusiveConstraintComponent = SH.term('MaxExclusiveConstraintComponent')
SH_MaxInclusiveConstraintComponent = SH.term('MaxInclusiveConstraintComponent')
SH_maxExclusive = SH.term('maxExclusive')
SH_maxInclusive = SH.term('maxInclusive')


class MinExclusiveConstraintComponent(ConstraintComponent):
    """
    Link:
    https://www.w3.org/TR/shacl/#MinExclusiveConstraintComponent
    Textual Definition:
    For each value node v where the SPARQL expression $minExclusive < v does not return true, there is a validation result with v as sh:value.
Exemplo n.º 5
0
#
import typing

from typing import Dict

from rdflib import Literal

from pyshacl.consts import SH, SH_jsFunctionName, SH_jsLibrary
from pyshacl.errors import ConstraintLoadError

from .context import SHACLJSContext

if typing.TYPE_CHECKING:
    from pyshacl.shapes_graph import ShapesGraph

SH_jsLibraryURL = SH.term('jsLibraryURL')


class JSExecutable(object):
    __slots__ = ("sg", "node", "fn_name", "libraries")

    def __new__(cls, shapes_graph: 'ShapesGraph', node):
        return super(JSExecutable, cls).__new__(cls)

    def __init__(self, shapes_graph: 'ShapesGraph', node):
        self.node = node
        self.sg = shapes_graph
        fn_names = set(shapes_graph.objects(node, SH_jsFunctionName))
        if len(fn_names) < 1:
            raise ConstraintLoadError(
                "At least one sh:jsFunctionName must be present on a JS Executable.",
Exemplo n.º 6
0
"""
https://www.w3.org/TR/shacl/#core-components-logical
"""
from typing import Dict, List
from warnings import warn

import rdflib

from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import SH
from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError, ShapeRecursionWarning, ValidationFailure
from pyshacl.pytypes import GraphLike
from pyshacl.rdfutil import stringify_node


SH_not = SH.term('not')
SH_and = SH.term('and')
SH_or = SH.term('or')
SH_xone = SH.term('xone')

SH_NotConstraintComponent = SH.term('NotConstraintComponent')
SH_AndConstraintComponent = SH.term('AndConstraintComponent')
SH_OrConstraintComponent = SH.term('OrConstraintComponent')
SH_XoneConstraintComponent = SH.term('XoneConstraintComponent')


class NotConstraintComponent(ConstraintComponent):
    """
    sh:not specifies the condition that each value node cannot conform to a given shape. This is comparable to negation and the logical "not" operator.
    Link:
    https://www.w3.org/TR/shacl/#NotConstraintComponent
Exemplo n.º 7
0
# -*- coding: utf-8 -*-
"""
https://www.w3.org/TR/shacl/#core-components-others
"""
import rdflib
from rdflib.namespace import RDF, RDFS
from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import RDF_type, SH, SH_property, SH_path
from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError

SH_InConstraintComponent = SH.term('InConstraintComponent')
SH_ClosedConstraintComponent = SH.term('ClosedConstraintComponent')
SH_HasValueConstraintComponent = SH.term('HasValueConstraintComponent')
SH_in = SH.term('in')
SH_closed = SH.term('closed')
SH_ignoredProperties = SH.term('ignoredProperties')
SH_hasValue = SH.term('hasValue')


class InConstraintComponent(ConstraintComponent):
    """
    sh:in specifies the condition that each value node is a member of a provided SHACL list.
    Link:
    https://www.w3.org/TR/shacl/#InConstraintComponent
    Textual Definition:
    For each value node that is not a member of $in, there is a validation result with the value node as sh:value.
    """
    def __init__(self, shape):
        super(InConstraintComponent, self).__init__(shape)
        in_vals = list(self.shape.objects(SH_in))
        if len(in_vals) < 1:
Exemplo n.º 8
0
# -*- coding: utf-8 -*-
"""
https://www.w3.org/TR/shacl/#core-components-string
"""
import rdflib
import re
from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import SH, SH_property, SH_node
from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError

SH_PatternConstraintComponent = SH.term('PatternConstraintComponent')
SH_MinLengthConstraintComponent = SH.term('MinLengthConstraintComponent')
SH_MaxLengthConstraintComponent = SH.term('MaxLengthConstraintComponent')
SH_LanguageInConstraintComponent = SH.term('LanguageInConstraintComponent')
SH_UniqueLangConstraintComponent = SH.term('UniqueLangConstraintComponent')
SH_pattern = SH.term('pattern')
SH_flags = SH.term('flags')
SH_minLength = SH.term('minLength')
SH_maxLength = SH.term('maxLength')
SH_languageIn = SH.term('languageIn')
SH_uniqueLang = SH.term('uniqueLang')


class StringBasedConstraintBase(ConstraintComponent):
    """
    https://www.w3.org/TR/shacl/#core-components-string
    """
    def __init__(self, shape):
        super(StringBasedConstraintBase, self).__init__(shape)
        self.string_rules = []
        self.allow_multi_rules = True
Exemplo n.º 9
0
# -*- coding: utf-8 -*-
"""
https://www.w3.org/TR/shacl/#sparql-constraints
"""
import re
import rdflib
from rdflib import RDF, XSD

from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import SH, SH_message, SH_deactivated, SH_inversePath, SH_alternativePath, SH_zeroOrMorePath, \
    SH_oneOrMorePath, SH_zeroOrOnePath, SH_prefixes, SH_prefix, SH_namespace
from pyshacl.errors import ConstraintLoadError, ValidationFailure, ReportableRuntimeError

SH_sparql = SH.term('sparql')
SH_select = SH.term('select')
SH_declare = SH.term('declare')

SH_SPARQLConstraintComponent = SH.term('SPARQLConstraintComponent')
SH_AndConstraintComponent = SH.term('AndConstraintComponent')
SH_OrConstraintComponent = SH.term('OrConstraintComponent')
SH_XoneConstraintComponent = SH.term('XoneConstraintComponent')


class SPARQLConstraintObject(object):
    bind_this_regex = re.compile(r"([\s{}()])[\$\?]this", flags=re.M)
    bind_path_regex = re.compile(r"([\s{}()])[\$\?]PATH", flags=re.M)
    bind_sg_regex = re.compile(r"([\s{}()])[\$\?]shapesGraph", flags=re.M)
    bind_cs_regex = re.compile(r"([\s{}()])[\$\?]currentShape", flags=re.M)

    def __init__(self,
                 shape,
Exemplo n.º 10
0
# -*- coding: utf-8 -*-
"""
https://www.w3.org/TR/shacl/#sparql-constraints
"""
import re
import rdflib
from rdflib import RDF, XSD

from pyshacl.consts import SH, SH_inversePath, SH_alternativePath,\
    SH_zeroOrMorePath, SH_oneOrMorePath, SH_zeroOrOnePath, SH_prefixes, SH_prefix, SH_namespace, RDF_type, OWL_Ontology
from pyshacl.errors import ConstraintLoadError, ValidationFailure, ReportableRuntimeError

SH_declare = SH.term('declare')


class SPARQLQueryHelper(object):
    bind_this_regex = re.compile(r"([\s{}()])[\$\?]this", flags=re.M)
    bind_value_regex = re.compile(r"([\s{}()])[\$\?]value", flags=re.M)
    bind_path_regex = re.compile(r"([\s{}()])[\$\?]PATH", flags=re.M)
    bind_sg_regex = re.compile(r"([\s{}()])[\$\?]shapesGraph", flags=re.M)
    bind_cs_regex = re.compile(r"([\s{}()])[\$\?]currentShape", flags=re.M)
    has_minus_regex = re.compile(r"[^\?\$]MINUS[\s\{]", flags=re.M | re.I)
    has_values_regex = re.compile(r"[^\?\$]VALUES[\s\{]", flags=re.M | re.I)
    has_service_regex = re.compile(r"[^\?\$]SERVICE[\s\<]", flags=re.M | re.I)
    has_nested_select_regex = re.compile(
        r"SELECT[\s\(\)\$\?\a-z]*\{[^\}]*SELECT\s+((?:(?:[\?\$]\w+\s+)|(?:\*\s+))+)",
        flags=re.M | re.I)
    has_as_var_regex = re.compile(r"[^\w]+AS[\s]+[\$\?](\w+)",
                                  flags=re.M | re.I)

    def __init__(self,
from typing import Dict, List, Tuple, Type, Union

import rdflib

from pyshacl.constraints.constraint_component import ConstraintComponent, CustomConstraintComponent
from pyshacl.consts import SH, RDF_type, SH_ask, SH_ConstraintComponent, SH_message, SH_select
from pyshacl.errors import ConstraintLoadError, ValidationFailure
from pyshacl.helper import get_query_helper_cls
from pyshacl.pytypes import GraphLike

if typing.TYPE_CHECKING:
    from pyshacl.shape import Shape
    from pyshacl.shapes_graph import ShapesGraph

SH_SPARQLSelectValidator = SH.term('SPARQLSelectValidator')
SH_SPARQLAskValidator = SH.term('SPARQLAskValidator')


class BoundShapeValidatorComponent(ConstraintComponent):
    def __init__(self, constraint, shape: 'Shape', validator):
        """
        Create a new custom constraint, by applying a ConstraintComponent and a Validator to a Shape
        :param constraint: The source ConstraintComponent, this is needed to bind the parameters in the query_helper
        :type constraint: SPARQLConstraintComponent
        :param shape:
        :type shape: Shape
        :param validator:
        :type validator: AskConstraintValidator | SelectConstraintValidator
        """
        super(BoundShapeValidatorComponent, self).__init__(shape)
Exemplo n.º 12
0
# -*- coding: utf-8 -*-
"""
https://www.w3.org/TR/shacl/#sparql-constraints
"""
import re
import rdflib
from rdflib import RDF, XSD

from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import SH, SH_message, SH_deactivated, SH_inversePath, SH_alternativePath, SH_zeroOrMorePath, \
    SH_oneOrMorePath, SH_zeroOrOnePath, SH_prefixes, SH_prefix, SH_namespace
from pyshacl.errors import ConstraintLoadError, ValidationFailure, ReportableRuntimeError

SH_sparql = SH.term('sparql')
SH_select = SH.term('select')
SH_declare = SH.term('declare')

SH_SPARQLConstraintComponent = SH.term('SPARQLConstraintComponent')


class SPARQLQueryHelper(object):
    bind_this_regex = re.compile(r"([\s{}()])[\$\?]this", flags=re.M)
    bind_value_regex = re.compile(r"([\s{}()])[\$\?]value", flags=re.M)
    bind_path_regex = re.compile(r"([\s{}()])[\$\?]PATH", flags=re.M)
    bind_sg_regex = re.compile(r"([\s{}()])[\$\?]shapesGraph", flags=re.M)
    bind_cs_regex = re.compile(r"([\s{}()])[\$\?]currentShape", flags=re.M)
    has_minus_regex = re.compile(r"[^\?\$]MINUS[\s\{]", flags=re.M | re.I)
    has_values_regex = re.compile(r"[^\?\$]VALUES[\s\{]", flags=re.M | re.I)
    has_service_regex = re.compile(r"[^\?\$]SERVICE[\s\<]", flags=re.M | re.I)
    has_nested_select_regex = re.compile(
        r"SELECT[\s\(\)\$\?\a-z]*\{[^\}]*SELECT\s+((?:(?:[\?\$]\w+\s+)|(?:\*\s+))+)",
Exemplo n.º 13
0
# -*- coding: utf-8 -*-
"""
https://www.w3.org/TR/shacl/#core-components-shape
"""
from warnings import warn
import rdflib
from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import SH, SH_property, SH_node
from pyshacl.errors import ConstraintLoadError, ValidationFailure, ReportableRuntimeError, ConstraintLoadWarning, \
    ShapeRecursionWarning

SH_PropertyConstraintComponent = SH.term('PropertyConstraintComponent')
SH_NodeConstraintComponent = SH.term('NodeConstraintComponent')

SH_QualifiedValueCountConstraintComponent = SH.term(
    'QualifiedValueConstraintComponent')
SH_QualifiedMaxCountConstraintComponent = SH.term(
    'QualifiedMaxCountConstraintComponent')
SH_QualifiedMinCountConstraintComponent = SH.term(
    'QualifiedMinCountConstraintComponent')

SH_qualifiedValueShape = SH.term('qualifiedValueShape')
SH_qualifiedValueShapesDisjoint = SH.term('qualifiedValueShapesDisjoint')
SH_qualifiedMinCount = SH.term('qualifiedMinCount')
SH_qualifiedMaxCount = SH.term('qualifiedMaxCount')


class PropertyConstraintComponent(ConstraintComponent):
    """
    sh:property can be used to specify that each value node has a given property shape.
    Link:
Exemplo n.º 14
0
from typing import Any, Dict, List, Set, Tuple, Type, Union

import rdflib

from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.constraints.sparql.sparql_based_constraints import SPARQLQueryHelper
from pyshacl.consts import SH, RDF_type, SH_ask, SH_message, SH_parameter, SH_path, SH_select
from pyshacl.errors import ConstraintLoadError, ValidationFailure
from pyshacl.parameter import SHACLParameter
from pyshacl.pytypes import GraphLike

if typing.TYPE_CHECKING:
    from pyshacl.shape import Shape
    from pyshacl.shapes_graph import ShapesGraph

SH_nodeValidator = SH.term('nodeValidator')
SH_propertyValidator = SH.term('propertyValidator')
SH_validator = SH.term('validator')
SH_optional = SH.term('optional')

SH_ConstraintComponent = SH.term('ConstraintComponent')
SH_SPARQLSelectValidator = SH.term('SPARQLSelectValidator')
SH_SPARQLAskValidator = SH.term('SPARQLAskValidator')


class BoundShapeValidatorComponent(ConstraintComponent):
    def __init__(self, constraint, shape: 'Shape', validator):
        """
        Create a new custom constraint, by applying a ConstraintComponent and a Validator to a Shape
        :param constraint: The source ConstraintComponent, this is needed to bind the parameters in the query_helper
        :type constraint: SPARQLConstraintComponent
Exemplo n.º 15
0
https://www.w3.org/TR/shacl/#core-components-count
"""
from typing import Dict, List

from rdflib.namespace import XSD
from rdflib.term import Literal

from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import SH
from pyshacl.errors import ConstraintLoadError
from pyshacl.pytypes import GraphLike
from pyshacl.rdfutil import stringify_node


XSD_integer = XSD.term('integer')
SH_minCount = SH.term('minCount')
SH_maxCount = SH.term('maxCount')

SH_MinCountConstraintComponent = SH.term('MinCountConstraintComponent')
SH_MaxCountConstraintComponent = SH.term('MaxCountConstraintComponent')


class MinCountConstraintComponent(ConstraintComponent):
    """
    sh:minCount specifies the minimum number of value nodes that satisfy the condition. If the minimum cardinality value is 0 then this constraint is always satisfied and so may be omitted.
    Link:
    https://www.w3.org/TR/shacl/#MinCountConstraintComponent
    Textual Definition:
    If the number of value nodes is less than $minCount, there is a validation result.
    """
Exemplo n.º 16
0
# -*- coding: utf-8 -*-
"""
https://www.w3.org/TR/shacl/#sparql-constraints
"""
import rdflib

from pyshacl.constraints.constraint_component import ConstraintComponent
from pyshacl.consts import SH, SH_select, SH_message, SH_deactivated
from pyshacl.errors import ConstraintLoadError, ValidationFailure
from pyshacl.sparql_query_helper import SPARQLQueryHelper

SH_sparql = SH.term('sparql')

SH_SPARQLConstraintComponent = SH.term('SPARQLConstraintComponent')


class SPARQLBasedConstraint(ConstraintComponent):
    """
    SHACL-SPARQL supports a constraint component that can be used to express restrictions based on a SPARQL SELECT query.
    Link:
    https://www.w3.org/TR/shacl/#sparql-constraints
    """
    def __init__(self, shape):
        super(SPARQLBasedConstraint, self).__init__(shape)
        sg = self.shape.sg.graph
        sparql_node_list = set(self.shape.objects(SH_sparql))
        if len(sparql_node_list) < 1:
            raise ConstraintLoadError(
                "SPARQLConstraintComponent must have at least one sh:sparql predicate.",
                "https://www.w3.org/TR/shacl/#SPARQLConstraintComponent")
        sparql_constraints = set()
Exemplo n.º 17
0
from rdflib import Literal

from pyshacl.constraints import ConstraintComponent
from pyshacl.constraints.constraint_component import CustomConstraintComponent
from pyshacl.consts import SH, SH_ConstraintComponent, SH_message
from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError, ValidationFailure
from pyshacl.pytypes import GraphLike

from .js_executable import JSExecutable

if typing.TYPE_CHECKING:
    from pyshacl.shape import Shape
    from pyshacl.shapes_graph import ShapesGraph

SH_JSConstraint = SH.term('JSConstraint')
SH_JSConstraintComponent = SH.term('JSConstraintComponent')


class BoundShapeJSValidatorComponent(ConstraintComponent):
    invalid_parameter_names = {
        'this', 'shapesGraph', 'currentShape', 'path', 'PATH', 'value'
    }

    def __init__(self, constraint, shape: 'Shape', validator):
        """
        Create a new custom constraint, by applying a ConstraintComponent and a Validator to a Shape
        :param constraint: The source ConstraintComponent, this is needed to bind the parameters in the query_helper
        :type constraint: SPARQLConstraintComponent
        :param shape:
        :type shape: Shape
Exemplo n.º 18
0
#
import typing

from rdflib.plugins.sparql.operators import register_custom_function, unregister_custom_function
from rdflib.plugins.sparql.sparql import SPARQLError

from pyshacl.consts import SH
from pyshacl.errors import ReportableRuntimeError
from pyshacl.functions import SHACLFunction

from .js_executable import JSExecutable

if typing.TYPE_CHECKING:
    from pyshacl.shapes_graph import ShapesGraph

SH_JSFunction = SH.term('JSFunction')


class JSFunction(SHACLFunction):
    __slots__ = ('js_exe', )

    def __init__(self, fn_node, shapes_graph: 'ShapesGraph'):
        super(JSFunction, self).__init__(fn_node, shapes_graph)
        self.js_exe = JSExecutable(shapes_graph, fn_node)

    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))
Exemplo n.º 19
0
#
#
import typing

from pyshacl.consts import SH
from pyshacl.rules.shacl_rule import SHACLRule

from .js_executable import JSExecutable

if typing.TYPE_CHECKING:
    from pyshacl.shape import Shape
    from pyshacl.shapes_graph import ShapesGraph

SH_JSRule = SH.term('JSRule')


class JSRule(SHACLRule):
    __slots__ = ('js_exe', )

    def __init__(self, shape: 'Shape', rule_node):
        super(JSRule, self).__init__(shape, rule_node)
        shapes_graph = shape.sg  # type: ShapesGraph
        self.js_exe = JSExecutable(shapes_graph, rule_node)

    def apply(self, data_graph):
        focus_nodes = self.shape.focus_nodes(
            data_graph)  # uses target nodes to find focus nodes
        applicable_nodes = self.filter_conditions(focus_nodes, data_graph)
        sets_to_add = []
        for a in applicable_nodes:
            args_map = {"this": a}