mustrd 0.2.6.1__py3-none-any.whl → 0.2.6.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,22 +22,38 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
22
  SOFTWARE.
23
23
  """
24
24
 
25
+ import logging
25
26
  from dataclasses import dataclass
26
27
  import pytest
27
28
  import os
28
- from pathlib import Path
29
+ from pathlib import Path, PosixPath
29
30
  from rdflib.namespace import Namespace
30
31
  from rdflib import Graph, RDF
31
32
  from pytest import Session
32
33
 
34
+ from mustrd import logger_setup
33
35
  from mustrd.TestResult import ResultList, TestResult, get_result_list
34
36
  from mustrd.utils import get_mustrd_root
35
- from mustrd.mustrd import get_triple_store_graph, get_triple_stores
36
- from mustrd.mustrd import Specification, SpecSkipped, validate_specs, get_specs, SpecPassed, run_spec
37
+ from mustrd.mustrd import (
38
+ write_result_diff_to_log,
39
+ get_triple_store_graph,
40
+ get_triple_stores,
41
+ )
42
+ from mustrd.mustrd import (
43
+ Specification,
44
+ SpecSkipped,
45
+ validate_specs,
46
+ get_specs,
47
+ SpecPassed,
48
+ run_spec,
49
+ )
37
50
  from mustrd.namespace import MUST, TRIPLESTORE, MUSTRDTEST
38
51
  from typing import Union
39
52
  from pyshacl import validate
40
53
 
54
+ import pathlib
55
+ import traceback
56
+
41
57
  spnamespace = Namespace("https://semanticpartners.com/data/test/")
42
58
 
43
59
  mustrd_root = get_mustrd_root()
@@ -82,55 +98,87 @@ def pytest_addoption(parser):
82
98
 
83
99
  def pytest_configure(config) -> None:
84
100
  # Read configuration file
85
- if config.getoption("mustrd"):
86
- test_configs = parse_config(config.getoption("configpath"))
87
- config.pluginmanager.register(MustrdTestPlugin(config.getoption("mdpath"),
88
- test_configs, config.getoption("secrets")))
101
+ if config.getoption("mustrd") and config.getoption("configpath"):
102
+ config.pluginmanager.register(
103
+ MustrdTestPlugin(
104
+ config.getoption("mdpath"),
105
+ Path(config.getoption("configpath")),
106
+ config.getoption("secrets"),
107
+ )
108
+ )
89
109
 
90
110
 
91
111
  def parse_config(config_path):
92
112
  test_configs = []
93
113
  config_graph = Graph().parse(config_path)
94
- shacl_graph = Graph().parse(Path(os.path.join(mustrd_root, "model/mustrdTestShapes.ttl")))
95
- ont_graph = Graph().parse(Path(os.path.join(mustrd_root, "model/mustrdTestOntology.ttl")))
114
+ shacl_graph = Graph().parse(
115
+ Path(os.path.join(mustrd_root, "model/mustrdTestShapes.ttl"))
116
+ )
117
+ ont_graph = Graph().parse(
118
+ Path(os.path.join(mustrd_root, "model/mustrdTestOntology.ttl"))
119
+ )
96
120
  conforms, results_graph, results_text = validate(
97
- data_graph=config_graph,
98
- shacl_graph=shacl_graph,
99
- ont_graph=ont_graph,
100
- advanced=True,
101
- inference='none'
102
- )
121
+ data_graph=config_graph,
122
+ shacl_graph=shacl_graph,
123
+ ont_graph=ont_graph,
124
+ advanced=True,
125
+ inference="none",
126
+ )
103
127
  if not conforms:
104
- raise ValueError(f"Mustrd test configuration not conform to the shapes. SHACL report: {results_text}",
105
- results_graph)
128
+ raise ValueError(
129
+ f"Mustrd test configuration not conform to the shapes. SHACL report: {results_text}",
130
+ results_graph,
131
+ )
106
132
 
107
- for test_config_subject in config_graph.subjects(predicate=RDF.type, object=MUSTRDTEST.MustrdTest):
108
- spec_path = get_config_param(config_graph, test_config_subject, MUSTRDTEST.hasSpecPath, str)
109
- data_path = get_config_param(config_graph, test_config_subject, MUSTRDTEST.hasDataPath, str)
110
- triplestore_spec_path = get_config_param(config_graph, test_config_subject, MUSTRDTEST.triplestoreSpecPath, str)
111
- pytest_path = get_config_param(config_graph, test_config_subject, MUSTRDTEST.hasPytestPath, str)
112
- filter_on_tripleStore = list(config_graph.objects(subject=test_config_subject,
113
- predicate=MUSTRDTEST.filterOnTripleStore))
133
+ for test_config_subject in config_graph.subjects(
134
+ predicate=RDF.type, object=MUSTRDTEST.MustrdTest
135
+ ):
136
+ spec_path = get_config_param(
137
+ config_graph, test_config_subject, MUSTRDTEST.hasSpecPath, str
138
+ )
139
+ data_path = get_config_param(
140
+ config_graph, test_config_subject, MUSTRDTEST.hasDataPath, str
141
+ )
142
+ triplestore_spec_path = get_config_param(
143
+ config_graph, test_config_subject, MUSTRDTEST.triplestoreSpecPath, str
144
+ )
145
+ pytest_path = get_config_param(
146
+ config_graph, test_config_subject, MUSTRDTEST.hasPytestPath, str
147
+ )
148
+ filter_on_tripleStore = tuple(
149
+ config_graph.objects(
150
+ subject=test_config_subject, predicate=MUSTRDTEST.filterOnTripleStore
151
+ )
152
+ )
114
153
 
115
154
  # Root path is the mustrd test config path
116
155
  root_path = Path(config_path).parent
117
156
  spec_path = root_path / Path(spec_path) if spec_path else None
118
157
  data_path = root_path / Path(data_path) if data_path else None
119
- triplestore_spec_path = root_path / Path(triplestore_spec_path) if triplestore_spec_path else None
158
+ triplestore_spec_path = (
159
+ root_path / Path(triplestore_spec_path) if triplestore_spec_path else None
160
+ )
120
161
 
121
- test_configs.append(TestConfig(spec_path=spec_path, data_path=data_path,
122
- triplestore_spec_path=triplestore_spec_path,
123
- pytest_path=pytest_path,
124
- filter_on_tripleStore=filter_on_tripleStore))
162
+ test_configs.append(
163
+ TestConfig(
164
+ spec_path=spec_path,
165
+ data_path=data_path,
166
+ triplestore_spec_path=triplestore_spec_path,
167
+ pytest_path=pytest_path,
168
+ filter_on_tripleStore=filter_on_tripleStore,
169
+ )
170
+ )
125
171
  return test_configs
126
172
 
127
173
 
128
174
  def get_config_param(config_graph, config_subject, config_param, convert_function):
129
- raw_value = config_graph.value(subject=config_subject, predicate=config_param, any=True)
175
+ raw_value = config_graph.value(
176
+ subject=config_subject, predicate=config_param, any=True
177
+ )
130
178
  return convert_function(raw_value) if raw_value else None
131
179
 
132
180
 
133
- @dataclass
181
+ @dataclass(frozen=True)
134
182
  class TestConfig:
135
183
  spec_path: Path
136
184
  data_path: Path
@@ -139,105 +187,92 @@ class TestConfig:
139
187
  filter_on_tripleStore: str = None
140
188
 
141
189
 
142
- @dataclass
190
+ @dataclass(frozen=True)
143
191
  class TestParamWrapper:
192
+ id: str
144
193
  test_config: TestConfig
145
194
  unit_test: Union[Specification, SpecSkipped]
146
195
 
147
196
 
197
+ # Configure logging
198
+ logger = logger_setup.setup_logger(__name__)
199
+
200
+
148
201
  class MustrdTestPlugin:
149
202
  md_path: str
150
- test_configs: list
203
+ test_config_file: Path
204
+ selected_tests: list
151
205
  secrets: str
152
206
  unit_tests: Union[Specification, SpecSkipped]
153
207
  items: list
208
+ path_filter: str
209
+ collect_error: BaseException
154
210
 
155
- def __init__(self, md_path, test_configs, secrets):
211
+ def __init__(self, md_path, test_config_file, secrets):
156
212
  self.md_path = md_path
157
- self.test_configs = test_configs
213
+ self.test_config_file = test_config_file
158
214
  self.secrets = secrets
159
215
  self.items = []
160
216
 
161
217
  @pytest.hookimpl(tryfirst=True)
162
218
  def pytest_collection(self, session):
219
+ logger.info("Starting test collection")
163
220
  self.unit_tests = []
164
221
  args = session.config.args
165
- if len(args) > 0:
166
- file_name = self.get_file_name_from_arg(args[0])
167
- # Filter test to collect only specified path
168
- config_to_collect = list(filter(lambda config:
169
- # Case we want to collect everything
170
- MUSTRD_PYTEST_PATH not in args[0]
171
- # Case we want to collect a test or sub test
172
- or (config.pytest_path or "") in args[0]
173
- # Case we want to collect a whole test folder
174
- or args[0].replace(f"./{MUSTRD_PYTEST_PATH}", "") in config.pytest_path,
175
- self.test_configs))
176
-
177
- # Redirect everything to test_mustrd.py,
178
- # no need to filter on specified test: Only specified test will be collected anyway
179
- session.config.args[0] = os.path.join(mustrd_root, "test/test_mustrd.py")
180
- # Collecting only relevant tests
181
-
182
- for one_test_config in config_to_collect:
183
- triple_stores = self.get_triple_stores_from_file(one_test_config)
184
-
185
- if one_test_config.filter_on_tripleStore and not triple_stores:
186
- self.unit_tests.extend(list(map(
187
- lambda triple_store:
188
- TestParamWrapper(test_config=one_test_config,
189
- unit_test=SpecSkipped(MUST.TestSpec, triple_store, "No triplestore found")),
190
- one_test_config.filter_on_tripleStore)))
191
- else:
192
- specs = self.generate_tests_for_config({"spec_path": one_test_config.spec_path,
193
- "data_path": one_test_config.data_path},
194
- triple_stores, file_name)
195
- self.unit_tests.extend(list(map(
196
- lambda spec: TestParamWrapper(test_config=one_test_config, unit_test=spec), specs)))
222
+ logger.info("Used arguments: " + str(args))
223
+ self.selected_tests = list(
224
+ map(
225
+ lambda arg: Path(arg.split("::")[0]),
226
+ # By default the current directory is given as argument
227
+ # Remove it as it is not a test
228
+ filter(lambda arg: arg != os.getcwd() and "::" in arg, args),
229
+ )
230
+ )
231
+ logger.info(f"selected_tests is: {self.selected_tests}")
232
+
233
+ self.path_filter = (
234
+ args[0]
235
+ if len(args) == 1 and args[0] != os.getcwd() and not "::" in args[0]
236
+ else None
237
+ )
238
+ logger.info(f"path_filter is: {self.path_filter}")
239
+
240
+ session.config.args = [str(self.test_config_file.resolve())]
197
241
 
198
242
  def get_file_name_from_arg(self, arg):
199
- if arg and len(arg) > 0 and "[" in arg and ".mustrd.ttl@" in arg:
200
- return arg[arg.index("[") + 1: arg.index(".mustrd.ttl@")]
243
+ if arg and len(arg) > 0 and "[" in arg and ".mustrd.ttl " in arg:
244
+ return arg[arg.index("[") + 1 : arg.index(".mustrd.ttl ")]
201
245
  return None
202
246
 
203
- @pytest.hookimpl(hookwrapper=True)
204
- def pytest_pycollect_makeitem(self, collector, name, obj):
205
- report = yield
206
- if name == "test_unit":
207
- items = report.get_result()
208
- new_results = []
209
- for item in items:
210
- virtual_path = MUSTRD_PYTEST_PATH + (item.callspec.params["unit_tests"].test_config.pytest_path or "default")
211
- item.fspath = Path(virtual_path)
212
- item._nodeid = virtual_path + "::" + item.name
213
- self.items.append(item)
214
- new_results.append(item)
215
- return new_results
216
-
217
- # Hook called at collection time: reads the configuration of the tests, and generate pytests from it
218
- def pytest_generate_tests(self, metafunc):
219
- if len(metafunc.fixturenames) > 0:
220
- if metafunc.function.__name__ == "test_unit":
221
- # Create the test in itself
222
- if self.unit_tests:
223
- metafunc.parametrize(metafunc.fixturenames[0], self.unit_tests,
224
- ids=lambda test_param: (test_param.unit_test.spec_file_name or "") + "@" +
225
- (test_param.test_config.pytest_path or ""))
226
- else:
227
- metafunc.parametrize(metafunc.fixturenames[0],
228
- [SpecSkipped(MUST.TestSpec, None, "No triplestore found")],
229
- ids=lambda x: "No configuration found for this test")
247
+ @pytest.hookimpl
248
+ def pytest_collect_file(self, parent, path):
249
+ logger.debug(f"Collecting file: {path}")
250
+ mustrd_file = MustrdFile.from_parent(parent, path=pathlib.Path(path), mustrd_plugin=self)
251
+ mustrd_file.mustrd_plugin = self
252
+ return mustrd_file
230
253
 
231
254
  # Generate test for each triple store available
232
255
  def generate_tests_for_config(self, config, triple_stores, file_name):
233
-
234
- shacl_graph = Graph().parse(Path(os.path.join(mustrd_root, "model/mustrdShapes.ttl")))
256
+ logger.debug(f"generate_tests_for_config {config=} {self=} {dir(self)}")
257
+ shacl_graph = Graph().parse(
258
+ Path(os.path.join(mustrd_root, "model/mustrdShapes.ttl"))
259
+ )
235
260
  ont_graph = Graph().parse(Path(os.path.join(mustrd_root, "model/ontology.ttl")))
236
- valid_spec_uris, spec_graph, invalid_spec_results = validate_specs(config, triple_stores,
237
- shacl_graph, ont_graph, file_name or "*")
261
+ logger.debug("Generating tests for config: " + str(config))
262
+ logger.debug(f"selected_tests {self.selected_tests}")
263
+
264
+ valid_spec_uris, spec_graph, invalid_spec_results = validate_specs(
265
+ config,
266
+ triple_stores,
267
+ shacl_graph,
268
+ ont_graph,
269
+ file_name or "*",
270
+ selected_test_files=self.selected_tests,
271
+ )
238
272
 
239
- specs, skipped_spec_results = \
240
- get_specs(valid_spec_uris, spec_graph, triple_stores, config)
273
+ specs, skipped_spec_results = get_specs(
274
+ valid_spec_uris, spec_graph, triple_stores, config
275
+ )
241
276
 
242
277
  # Return normal specs + skipped results
243
278
  return specs + skipped_spec_results + invalid_spec_results
@@ -248,28 +283,43 @@ class MustrdTestPlugin:
248
283
  if isinstance(spec, SpecSkipped):
249
284
  triple_store = spec.triple_store
250
285
  else:
251
- triple_store = spec.triple_store['type']
286
+ triple_store = spec.triple_store["type"]
287
+
252
288
  triple_store_name = triple_store.replace("https://mustrd.com/model/", "")
253
289
  test_name = spec.spec_uri.replace(spnamespace, "").replace("_", " ")
254
- return triple_store_name + ": " + test_name
290
+ return spec.spec_file_name + " : " + triple_store_name + ": " + test_name
255
291
 
256
292
  # Get triple store configuration or default
257
293
  def get_triple_stores_from_file(self, test_config):
258
294
  if test_config.triplestore_spec_path:
259
295
  try:
260
- triple_stores = get_triple_stores(get_triple_store_graph(test_config.triplestore_spec_path,
261
- self.secrets))
296
+ triple_stores = get_triple_stores(
297
+ get_triple_store_graph(
298
+ test_config.triplestore_spec_path, self.secrets
299
+ )
300
+ )
262
301
  except Exception as e:
263
- print(f"""Triplestore configuration parsing failed {test_config.triplestore_spec_path}.
264
- Only rdflib will be executed""", e)
265
- triple_stores = [{'type': TRIPLESTORE.RdfLib, 'uri': TRIPLESTORE.RdfLib}]
302
+ print(
303
+ f"""Triplestore configuration parsing failed {test_config.triplestore_spec_path}.
304
+ Only rdflib will be executed""",
305
+ e,
306
+ )
307
+ triple_stores = [
308
+ {"type": TRIPLESTORE.RdfLib, "uri": TRIPLESTORE.RdfLib}
309
+ ]
266
310
  else:
267
311
  print("No triple store configuration required: using embedded rdflib")
268
- triple_stores = [{'type': TRIPLESTORE.RdfLib, 'uri': TRIPLESTORE.RdfLib}]
312
+ triple_stores = [{"type": TRIPLESTORE.RdfLib, "uri": TRIPLESTORE.RdfLib}]
269
313
 
270
314
  if test_config.filter_on_tripleStore:
271
- triple_stores = list(filter(lambda triple_store: (triple_store["uri"] in test_config.filter_on_tripleStore),
272
- triple_stores))
315
+ triple_stores = list(
316
+ filter(
317
+ lambda triple_store: (
318
+ triple_store["uri"] in test_config.filter_on_tripleStore
319
+ ),
320
+ triple_stores,
321
+ )
322
+ )
273
323
  return triple_stores
274
324
 
275
325
  # Hook function. Initialize the list of result in session
@@ -284,7 +334,7 @@ class MustrdTestPlugin:
284
334
  outcome = yield
285
335
  result = outcome.get_result()
286
336
 
287
- if result.when == 'call':
337
+ if result.when == "call":
288
338
  # Add the result of the test to the session
289
339
  item.session.results[item] = result
290
340
 
@@ -300,7 +350,11 @@ class MustrdTestPlugin:
300
350
  if test_conf.originalname != test_conf.name:
301
351
  module_name = test_conf.parent.name
302
352
  class_name = test_conf.originalname
303
- test_name = test_conf.name.replace(class_name, "").replace("[", "").replace("]", "")
353
+ test_name = (
354
+ test_conf.name.replace(class_name, "")
355
+ .replace("[", "")
356
+ .replace("]", "")
357
+ )
304
358
  is_mustrd = True
305
359
  # Case normal unit tests
306
360
  else:
@@ -309,26 +363,128 @@ class MustrdTestPlugin:
309
363
  test_name = test_conf.originalname
310
364
  is_mustrd = False
311
365
 
312
- test_results.append(TestResult(test_name, class_name, module_name, result.outcome, is_mustrd))
313
-
314
- result_list = ResultList(None, get_result_list(test_results,
315
- lambda result: result.type,
316
- lambda result: is_mustrd and result.test_name.split("@")[1]),
317
- False)
366
+ test_results.append(
367
+ TestResult(
368
+ test_name, class_name, module_name, result.outcome, is_mustrd
369
+ )
370
+ )
371
+
372
+ result_list = ResultList(
373
+ None,
374
+ get_result_list(
375
+ test_results,
376
+ lambda result: result.type,
377
+ lambda result: is_mustrd and result.test_name.split("@")[1],
378
+ ),
379
+ False,
380
+ )
318
381
 
319
382
  md = result_list.render()
320
- with open(self.md_path, 'w') as file:
383
+ with open(self.md_path, "w") as file:
321
384
  file.write(md)
322
385
 
323
386
 
387
+ class MustrdFile(pytest.File):
388
+ mustrd_plugin: MustrdTestPlugin
389
+
390
+ def __init__(self, *args, mustrd_plugin, **kwargs):
391
+ self.mustrd_plugin = mustrd_plugin
392
+ super(pytest.File, self).__init__(*args, **kwargs)
393
+
394
+ def collect(self):
395
+ try:
396
+ logger.debug(f"Collecting tests from file: {self.fspath}")
397
+ test_configs = parse_config(self.fspath)
398
+ for test_config in test_configs:
399
+ # Skip if there is a path filter and it is not in the pytest path
400
+ if (
401
+ self.mustrd_plugin.path_filter is not None
402
+ and self.mustrd_plugin.path_filter not in test_config.pytest_path
403
+ ):
404
+ continue
405
+ triple_stores = self.mustrd_plugin.get_triple_stores_from_file(
406
+ test_config
407
+ )
408
+
409
+ if test_config.filter_on_tripleStore and not triple_stores:
410
+ specs = list(
411
+ map(
412
+ lambda triple_store: SpecSkipped(
413
+ MUST.TestSpec, triple_store, "No triplestore found"
414
+ ),
415
+ test_config.filter_on_tripleStore,
416
+ )
417
+ )
418
+ else:
419
+ specs = self.mustrd_plugin.generate_tests_for_config(
420
+ {
421
+ "spec_path": test_config.spec_path,
422
+ "data_path": test_config.data_path,
423
+ },
424
+ triple_stores,
425
+ None,
426
+ )
427
+ for spec in specs:
428
+ item = MustrdItem.from_parent(
429
+ self,
430
+ name=test_config.pytest_path + "/" + spec.spec_file_name,
431
+ spec=spec,
432
+ )
433
+ self.mustrd_plugin.items.append(item)
434
+ yield item
435
+ except Exception as e:
436
+ # Catch error here otherwise it will be lost
437
+ self.mustrd_plugin.collect_error = e
438
+ logger.error(f"Error during collection: {e}")
439
+ raise e
440
+
441
+
442
+ class MustrdItem(pytest.Item):
443
+ def __init__(self, name, parent, spec):
444
+ logging.info(f"Creating item: {name}")
445
+ super().__init__(name, parent)
446
+ self.spec = spec
447
+ self.fspath = spec.spec_source_file
448
+
449
+ def runtest(self):
450
+ result = run_test_spec(self.spec)
451
+ if not result:
452
+ raise AssertionError(f"Test {self.name} failed")
453
+
454
+ def repr_failure(self, excinfo):
455
+ # excinfo.value is the exception instance
456
+ # You can add more context here
457
+ tb_lines = traceback.format_exception(excinfo.type, excinfo.value, excinfo.tb)
458
+ tb_str = "".join(tb_lines)
459
+ return (
460
+ f"{self.name} failed:\n"
461
+ f"Spec: {self.spec.spec_uri}\n"
462
+ f"File: {self.spec.spec_source_file}\n"
463
+ f"Dir: {dir(self.spec)}\n"
464
+ f"Error: {excinfo.value}\n"
465
+ f"Traceback:\n{tb_str}"
466
+ )
467
+
468
+ def reportinfo(self):
469
+ r = "", 0, f"mustrd test: {self.name}"
470
+ return r
471
+
472
+
324
473
  # Function called in the test to actually run it
325
474
  def run_test_spec(test_spec):
326
475
  if isinstance(test_spec, SpecSkipped):
327
476
  pytest.skip(f"Invalid configuration, error : {test_spec.message}")
328
477
  result = run_spec(test_spec)
329
-
330
478
  result_type = type(result)
331
479
  if result_type == SpecSkipped:
332
480
  # FIXME: Better exception management
333
481
  pytest.skip("Unsupported configuration")
482
+ if result_type != SpecPassed:
483
+ write_result_diff_to_log(result, logger.info)
484
+ log_lines = []
485
+ def log_to_string(message):
486
+ log_lines.append(message)
487
+ write_result_diff_to_log(result, log_to_string)
488
+ raise AssertionError("Test failed: " + "\n".join(log_lines))
489
+
334
490
  return result_type == SpecPassed
mustrd/spec_component.py CHANGED
@@ -65,6 +65,7 @@ class WhenSpec(SpecComponent):
65
65
  class AnzoWhenSpec(WhenSpec):
66
66
  paramQuery: str = None
67
67
  queryTemplate: str = None
68
+ spec_component_details: any = None
68
69
 
69
70
 
70
71
  @dataclass
@@ -108,6 +109,7 @@ def parse_spec_component(subject: URIRef,
108
109
  for spec_component_node in spec_component_nodes:
109
110
  data_source_types = get_data_source_types(subject, predicate, spec_graph, spec_component_node)
110
111
  for data_source_type in data_source_types:
112
+ log.debug(f"parse_spec_component {spec_component_node} {data_source_type} {mustrd_triple_store=}")
111
113
  spec_component_details = SpecComponentDetails(
112
114
  subject=subject,
113
115
  predicate=predicate,
@@ -117,6 +119,8 @@ def parse_spec_component(subject: URIRef,
117
119
  data_source_type=data_source_type,
118
120
  run_config=run_config,
119
121
  root_paths=get_components_roots(spec_graph, subject, run_config))
122
+
123
+ # get_spec_component potentially talks to anzo for EVERY spec, massively slowing things down, can we defer it to run time?
120
124
  spec_component = get_spec_component(spec_component_details)
121
125
  if isinstance(spec_component, list):
122
126
  spec_components += spec_component
@@ -433,10 +437,11 @@ def _get_spec_component_AnzoGraphmartDataset(spec_component_details: SpecCompone
433
437
  predicate=MUST.graphmart)
434
438
  layer = spec_component_details.spec_graph.value(subject=spec_component_details.spec_component_node,
435
439
  predicate=MUST.layer)
436
- spec_component.value = get_spec_component_from_graphmart(
437
- triple_store=spec_component_details.mustrd_triple_store,
438
- graphmart=graphmart,
439
- layer=layer)
440
+ spec_component.spec_component_details = spec_component_details
441
+ # return get_spec_component_from_graphmart(
442
+ # triple_store=spec_component_details.mustrd_triple_store,
443
+ # graphmart=graphmart,
444
+ # layer=layer)
440
445
  else:
441
446
  raise ValueError(f"You must define {TRIPLESTORE.Anzo} to use {MUST.AnzoGraphmartDataset}")
442
447
 
@@ -468,14 +473,16 @@ def _get_spec_component_AnzoQueryBuilderSparqlSource(spec_component_details: Spe
468
473
 
469
474
  @get_spec_component.method((MUST.AnzoGraphmartStepSparqlSource, MUST.when))
470
475
  def _get_spec_component_AnzoGraphmartStepSparqlSource(spec_component_details: SpecComponentDetails) -> SpecComponent:
471
- spec_component = init_spec_component(spec_component_details.predicate)
476
+ spec_component = AnzoWhenSpec()
472
477
 
473
478
  # Get WHEN specComponent from query builder
474
479
  if spec_component_details.mustrd_triple_store["type"] == TRIPLESTORE.Anzo:
475
480
  query_step_uri = spec_component_details.spec_graph.value(subject=spec_component_details.spec_component_node,
476
481
  predicate=MUST.anzoQueryStep)
477
- spec_component.value = get_query_from_step(triple_store=spec_component_details.mustrd_triple_store,
478
- query_step_uri=query_step_uri)
482
+ spec_component.spec_component_details = spec_component_details
483
+ spec_component.query_step_uri = query_step_uri
484
+ # spec_component.value = get_query_from_step(triple_store=spec_component_details.mustrd_triple_store,
485
+ # query_step_uri=query_step_uri)
479
486
  # If anzo specific function is called but no anzo defined
480
487
  else:
481
488
  raise ValueError(f"You must define {TRIPLESTORE.Anzo} to use {MUST.AnzoGraphmartStepSparqlSource}")
@@ -529,6 +536,7 @@ def _get_spec_component_AnzoGraphmartLayerSparqlSource(spec_component_details: S
529
536
  spec_component.value = query.get("query")
530
537
  spec_component.paramQuery = query.get("param_query")
531
538
  spec_component.queryTemplate = query.get("query_template")
539
+ spec_component.spec_component_details = spec_component_details
532
540
  if spec_component.value:
533
541
  spec_component.queryType = spec_component_details.spec_graph.value(
534
542
  subject=spec_component_details.spec_component_node,
@@ -547,6 +555,7 @@ def _get_spec_component_default(spec_component_details: SpecComponentDetails) ->
547
555
 
548
556
 
549
557
  def init_spec_component(predicate: URIRef, triple_store_type: URIRef = None) -> GivenSpec | WhenSpec | ThenSpec | TableThenSpec: # noqa
558
+ log.info(f"init_spec_component {predicate} {triple_store_type}")
550
559
  if predicate == MUST.given:
551
560
  spec_component = GivenSpec()
552
561
  elif predicate == MUST.when:
mustrd/steprunner.py CHANGED
@@ -31,7 +31,7 @@ from rdflib import Graph, URIRef
31
31
  from .mustrdRdfLib import execute_select as execute_select_rdflib
32
32
  from .mustrdRdfLib import execute_construct as execute_construct_rdflib
33
33
  from .mustrdRdfLib import execute_update as execute_update_rdflib
34
- from .mustrdAnzo import upload_given as upload_given_anzo
34
+ from .mustrdAnzo import get_query_from_step, upload_given as upload_given_anzo
35
35
  from .mustrdAnzo import execute_update as execute_update_anzo
36
36
  from .mustrdAnzo import execute_construct as execute_construct_anzo
37
37
  from .mustrdAnzo import execute_select as execute_select_anzo
@@ -40,8 +40,9 @@ from .mustrdGraphDb import execute_update as execute_update_graphdb
40
40
  from .mustrdGraphDb import execute_construct as execute_construct_graphdb
41
41
  from .mustrdGraphDb import execute_select as execute_select_graphdb
42
42
  from .spec_component import AnzoWhenSpec, WhenSpec
43
+ import logging
43
44
 
44
- log = logger_setup.setup_logger(__name__)
45
+ log = logging.getLogger(__name__)
45
46
 
46
47
 
47
48
  def dispatch_upload_given(triple_store: dict, given: Graph):
@@ -80,7 +81,16 @@ run_when = MultiMethod('run_when', dispatch_run_when)
80
81
 
81
82
  @run_when.method((TRIPLESTORE.Anzo, MUST.UpdateSparql))
82
83
  def _anzo_run_when_update(spec_uri: URIRef, triple_store: dict, when: AnzoWhenSpec):
83
- return execute_update_anzo(triple_store, when.value, when.bindings)
84
+ log.debug(f"_anzo_run_when_update {spec_uri} {triple_store} {when} {type(when)}")
85
+ if when.value is None:
86
+ # fetch the query from the query step on anzo
87
+ query = get_query_from_step(triple_store=when.spec_component_details.mustrd_triple_store,
88
+ query_step_uri=when.query_step_uri)
89
+ else:
90
+ # we must already have the query
91
+ query = when.value
92
+ log.debug(f"_anzo_run_when_update.query {query}")
93
+ return execute_update_anzo(triple_store, query, when.bindings)
84
94
 
85
95
 
86
96
  @run_when.method((TRIPLESTORE.Anzo, MUST.ConstructSparql))
@@ -95,7 +105,8 @@ def _anzo_run_when_select(spec_uri: URIRef, triple_store: dict, when: AnzoWhenSp
95
105
 
96
106
  @run_when.method((TRIPLESTORE.GraphDb, MUST.UpdateSparql))
97
107
  def _graphdb_run_when_update(spec_uri: URIRef, triple_store: dict, when: WhenSpec):
98
- return execute_update_graphdb(triple_store, when.value, when.bindings)
108
+
109
+ return execute_update_graphdb(triple_store, query, when.bindings)
99
110
 
100
111
 
101
112
  @run_when.method((TRIPLESTORE.GraphDb, MUST.ConstructSparql))
@@ -152,6 +163,7 @@ def _multi_run_when_anzo_query_driven_update(spec_uri: URIRef, triple_store: dic
152
163
 
153
164
  @run_when.method(Default)
154
165
  def _multi_run_when_default(spec_uri: URIRef, triple_store: dict, when: WhenSpec):
166
+ log.error(f"run_when not implemented for {spec_uri} {triple_store} {when}")
155
167
  if when.queryType == MUST.AskSparql:
156
168
  log.warning(f"Skipping {spec_uri}, SPARQL ASK not implemented.")
157
169
  msg = "SPARQL ASK not implemented."