@@ -62,187 +62,6 @@ def traverse(self, predecessors: Set[URIRef]) -> Tuple[List, Dict]:
6262
6363 return properties , attributes
6464
65- def validate (
66- self ,
67- target_graph : GraphLike ,
68- focus : Optional [
69- Union [
70- Tuple [Union [URIRef , BNode ]],
71- List [Union [URIRef , BNode ]],
72- Set [Union [URIRef , BNode ]],
73- Union [URIRef , BNode ],
74- ]
75- ] = None ,
76- abort_on_first : Optional [bool ] = False ,
77- allow_infos : Optional [bool ] = False ,
78- allow_warnings : Optional [bool ] = False ,
79- _evaluation_path : Optional [List ] = None ,
80- ):
81- if self .deactivated :
82- if self .sg .debug :
83- self .logger .debug (f"Skipping shape because it is deactivated: { str (self )} " )
84- return True , []
85- if focus is not None :
86- lh_shape = False
87- rh_shape = True
88- self .logger .debug (f"Running evaluation of Shape { str (self )} " )
89- if not isinstance (focus , (tuple , list , set )):
90- focus = [focus ]
91- self .logger .debug (f"Shape was passed { len (focus )} Focus Node/s to evaluate." )
92- if len (focus ) < 1 :
93- return True , []
94- else :
95- lh_shape = True
96- rh_shape = False
97- self .logger .debug (f"Checking if Shape { str (self )} defines its own targets." )
98- self .logger .debug ("Identifying targets to find focus nodes." )
99- focus = self .focus_nodes (target_graph )
100- self .logger .debug (f"Found { len (focus )} Focus Nodes to evaluate." )
101- if len (focus ) < 1 :
102- # It's possible for shapes to have _no_ focus nodes
103- # (they are called in other ways)
104- if self .sg .debug :
105- self .logger .debug (
106- f"Skipping shape { str (self )} because it found no focus nodes." )
107- return True , []
108- else :
109- self .logger .debug (f"Running evaluation of Shape { str (self )} " )
110- if _evaluation_path is None :
111- _evaluation_path = []
112- print (len (_evaluation_path ))
113- # elif len(_evaluation_path) >= 30:
114- # # 27 is the depth required to successfully do the meta-shacl test on shacl.ttl
115- # path_str = " -> ".join((str(e) for e in _evaluation_path))
116- # raise ReportableRuntimeError("Evaluation path too deep!\n{}".format(path_str))
117- t1 = perf_counter ()
118- # Lazy import here to avoid an import loop
119- CONSTRAINT_PARAMETERS , PARAMETER_MAP = getattr (
120- pyshacl .module , 'CONSTRAINT_PARAMS' , (None , None ))
121- if not CONSTRAINT_PARAMETERS or not PARAMETER_MAP :
122- from pyshacl .constraints import ALL_CONSTRAINT_PARAMETERS , CONSTRAINT_PARAMETERS_MAP
123-
124- setattr (pyshacl .shape , 'CONSTRAINT_PARAMS' ,
125- (ALL_CONSTRAINT_PARAMETERS , CONSTRAINT_PARAMETERS_MAP ))
126-
127- CONSTRAINT_PARAMETERS = ALL_CONSTRAINT_PARAMETERS
128- PARAMETER_MAP = CONSTRAINT_PARAMETERS_MAP
129- if self .sg .js_enabled or self ._advanced :
130- search_parameters = CONSTRAINT_PARAMETERS .copy ()
131- constraint_map = PARAMETER_MAP .copy ()
132- if self ._advanced :
133- from pyshacl .constraints .advanced import ExpressionConstraint , SH_expression
134-
135- search_parameters .append (SH_expression )
136- constraint_map [SH_expression ] = ExpressionConstraint
137- if self .sg .js_enabled :
138- from pyshacl .extras .js .constraint import JSConstraint , SH_js
139-
140- search_parameters .append (SH_js )
141- constraint_map [SH_js ] = JSConstraint
142- else :
143- search_parameters = CONSTRAINT_PARAMETERS
144- constraint_map = PARAMETER_MAP
145- parameters = (p for p , v in self .sg .predicate_objects (self .node ) if p in search_parameters )
146- reports = []
147- focus_value_nodes = self .value_nodes (target_graph , focus )
148- filter_reports : bool = False
149- allow_conform : bool = False
150- allowed_severities : Set [URIRef ] = set ()
151- if allow_infos :
152- allowed_severities .add (SH_Info )
153- if allow_warnings :
154- allowed_severities .add (SH_Info )
155- allowed_severities .add (SH_Warning )
156- if allow_infos or allow_warnings :
157- if self .severity in allowed_severities :
158- allow_conform = True
159- else :
160- filter_reports = True
161-
162- non_conformant = False
163- done_constraints = set ()
164- run_count = 0
165- _evaluation_path .append (self )
166- if self .sg .debug :
167- path_str = " -> " .join ((str (e ) for e in _evaluation_path ))
168- self .logger .debug (f"Current shape evaluation path: { path_str } " )
169- constraint_components = [constraint_map [p ] for p in iter (parameters )]
170- constraint_component : Type ['ConstraintComponent' ]
171- for constraint_component in constraint_components :
172- if constraint_component in done_constraints :
173- continue
174- try :
175- # if self.sg.debug:
176- # self.logger.debug(f"Constructing Constraint Component: {repr(constraint_component)}")
177- c = constraint_component (self )
178- except ConstraintLoadWarning as w :
179- self .logger .warning (repr (w ))
180- continue
181- except ConstraintLoadError as e :
182- self .logger .error (repr (e ))
183- raise e
184- _e_p_copy = _evaluation_path [:]
185- _e_p_copy .append (c )
186- if self .sg .debug :
187- self .logger .debug (f"Checking conformance for constraint: { str (c )} " )
188- ct1 = perf_counter ()
189- if self .sg .debug :
190- path_str = " -> " .join ((str (e ) for e in _e_p_copy ))
191- self .logger .debug (f"Current constraint evaluation path: { path_str } " )
192- _is_conform , _reports = c .evaluate (target_graph , focus_value_nodes , _e_p_copy )
193- ct2 = perf_counter ()
194- if self .sg .debug :
195- elapsed = ct2 - ct1
196- self .logger .debug (
197- f"Milliseconds to check constraint { str (c )} : { elapsed * 1000.0 :.3f} ms" )
198- if _is_conform :
199- self .logger .debug (f"DataGraph conforms to constraint { c } ." )
200- elif allow_conform :
201- self .logger .debug (
202- f"Focus nodes do _not_ conform to constraint { c } but given severity is allowed." )
203- else :
204- self .logger .debug (f"Focus nodes do _not_ conform to constraint { c } ." )
205- if lh_shape or (not rh_shape ):
206- for v_str , v_node , v_parts in _reports :
207- self .logger .debug (v_str )
208-
209- if _is_conform or allow_conform :
210- ...
211- elif filter_reports :
212- all_allow = True
213- for v_str , v_node , v_parts in _reports :
214- severity_bits = list (
215- filter (lambda p : p [0 ] == v_node and p [1 ] == SH_resultSeverity , v_parts ))
216- if severity_bits :
217- all_allow = all_allow and (severity_bits [0 ][2 ] in allowed_severities )
218- non_conformant = non_conformant or (not all_allow )
219- else :
220- non_conformant = non_conformant or (not _is_conform )
221- reports .extend (_reports )
222- run_count += 1
223- done_constraints .add (constraint_component )
224- if non_conformant and abort_on_first :
225- break
226- applicable_custom_constraints = self .find_custom_constraints ()
227- for a in applicable_custom_constraints :
228- if non_conformant and abort_on_first :
229- break
230- _e_p_copy2 = _evaluation_path [:]
231- validator = a .make_validator_for_shape (self )
232- _e_p_copy2 .append (validator )
233- _is_conform , _r = validator .evaluate (target_graph , focus_value_nodes , _e_p_copy2 )
234- non_conformant = non_conformant or (not _is_conform )
235- reports .extend (_r )
236- run_count += 1
237- t2 = perf_counter ()
238- if self .sg .debug :
239- elapsed = t2 - t1
240- self .logger .debug (
241- f"Milliseconds to evaluate shape { str (self )} : { elapsed * 1000.0 :.3f} ms" )
242- # print(_evaluation_path, "Passes" if not non_conformant else "Fails")
243- return (not non_conformant ), reports
244-
245-
24665
24766class ShapesGraphWrapper (ShapesGraph ):
24867
0 commit comments