mustrd 0.2.6.3__py3-none-any.whl → 0.3.0.0__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.
mustrd/__init__.py CHANGED
@@ -1 +0,0 @@
1
-
mustrd/anzo_utils.py CHANGED
@@ -33,6 +33,7 @@ import logging
33
33
 
34
34
  logger = logging.getLogger()
35
35
 
36
+
36
37
  def query_azg(anzo_config: dict, query: str,
37
38
  format: str = "json", is_update: bool = False,
38
39
  data_layers: List[str] = None):
@@ -41,7 +42,7 @@ def query_azg(anzo_config: dict, query: str,
41
42
  'format': format,
42
43
  'datasourceURI': anzo_config['gqe_uri'],
43
44
  'using-graph-uri' if is_update else 'default-graph-uri': data_layers,
44
- 'using-named-graph-uri' if is_update else'named-graph-uri': data_layers
45
+ 'using-named-graph-uri' if is_update else 'named-graph-uri': data_layers
45
46
  }
46
47
  url = f"{anzo_config['url']}/sparql"
47
48
  return send_anzo_query(anzo_config, url=url, params=params, query=query, is_update=is_update)
mustrd/logger_setup.py CHANGED
@@ -35,6 +35,7 @@ def setup_logger(name: str) -> logging.Logger:
35
35
  log = logging.getLogger(name)
36
36
  log.setLevel(LOG_LEVEL)
37
37
 
38
+
38
39
  stderr_handler = logging.StreamHandler(sys.stderr)
39
40
  stderr_handler.setLevel(logging.ERROR)
40
41
  log.addHandler(stderr_handler)
@@ -249,5 +249,14 @@ must:AnzoGraphmartQueryDrivenTemplatedStepSparqlSourceShape
249
249
  sh:minCount 1 ;
250
250
  sh:maxCount 1 ; ] .
251
251
 
252
-
253
-
252
+ must:SpadeEdnGroupSourceShape
253
+ a sh:NodeShape ;
254
+ sh:targetClass must:SpadeEdnGroupSource ;
255
+ sh:property [ sh:path must:file ;
256
+ sh:message "A SpadeEdnGroupSource must have a file property pointing to the spade.edn config." ;
257
+ sh:minCount 1 ;
258
+ sh:maxCount 1 ; ] ;
259
+ sh:property [ sh:path must:groupId ;
260
+ sh:message "A SpadeEdnGroupSource must have a groupId property referencing the group in the EDN file." ;
261
+ sh:minCount 1 ;
262
+ sh:maxCount 1 ; ] .
mustrd/model/ontology.ttl CHANGED
@@ -461,6 +461,11 @@ sh:order rdf:type owl:DatatypeProperty ;
461
461
  rdfs:isDefinedBy : ;
462
462
  rdfs:label "AnzoGraphmartQueryDrivenTemplatedStepSparqlSource" .
463
463
 
464
+ ### https://mustrd.com/model/SpadeEdnGroupSource
465
+ :SpadeEdnGroupSource rdf:type owl:Class ;
466
+ rdfs:subClassOf :SparqlSource ;
467
+ rdfs:comment "Allows reference to a spade.edn file, and a specific groupid (think Anzo layer), within that" ;
468
+ rdfs:label "SpadeEdnGroupSource" .
464
469
 
465
470
  ### https://mustrd.com/model/Then
466
471
  :Then rdf:type owl:Class ;
mustrd/mustrd.py CHANGED
@@ -55,7 +55,6 @@ import logging
55
55
  from http.client import HTTPConnection
56
56
  from .steprunner import upload_given, run_when
57
57
  from multimethods import MultiMethod
58
- import logging
59
58
  import traceback
60
59
 
61
60
  log = logging.getLogger(__name__)
@@ -239,7 +238,10 @@ def validate_specs(run_config: dict,
239
238
  advanced=True,
240
239
  js=False,
241
240
  debug=False)
242
-
241
+ if str(file.name).endswith("_duplicate"):
242
+ log.debug(f"Validation of {file.name} against SHACL shapes: {conforms}")
243
+ log.debug(f"{results_graph.serialize(format='turtle')}")
244
+ # log.debug(f"SHACL validation results: {results_text}")
243
245
  # Add error message if not conform to spec shapes
244
246
  if not conforms:
245
247
  for msg in results_graph.objects(predicate=SH.resultMessage):
@@ -284,6 +286,10 @@ def add_spec_validation(file_graph: Graph, subject_uris: set, file: Path, triple
284
286
  error_messages: list, invalid_specs: list, spec_graph: Graph):
285
287
 
286
288
  for subject_uri in file_graph.subjects(RDF.type, MUST.TestSpec):
289
+ # Always add file name and source file to the graph for error reporting
290
+ file_graph.add([subject_uri, MUST.specSourceFile, Literal(str(file))])
291
+ file_graph.add([subject_uri, MUST.specFileName, Literal(file.name)])
292
+
287
293
  # If we already collected a URI, then we tag it as duplicate and it won't be executed
288
294
  if subject_uri in subject_uris:
289
295
  log.warning(
@@ -326,8 +332,11 @@ def get_specs(spec_uris: List[URIRef], spec_graph: Graph, triple_stores: List[di
326
332
  specs += [get_spec(spec_uri, spec_graph,
327
333
  run_config, triple_store)]
328
334
  except (ValueError, FileNotFoundError, ConnectionError) as e:
335
+ # Try to get file name/path from the graph, but fallback to "unknown"
336
+ file_name = spec_graph.value(subject=spec_uri, predicate=MUST.specFileName) or "unknown"
337
+ file_path = spec_graph.value(subject=spec_uri, predicate=MUST.specSourceFile) or "unknown"
329
338
  skipped_results += [SpecSkipped(spec_uri, triple_store['type'],
330
- e, get_spec_file(spec_uri, spec_graph))]
339
+ str(e), str(file_name), Path(file_path))]
331
340
 
332
341
  except (BadSyntax, FileNotFoundError) as e:
333
342
  template = "An exception of type {0} occurred when trying to parse the triple store configuration file. " \
@@ -349,7 +358,14 @@ def run_specs(specs) -> List[SpecResult]:
349
358
 
350
359
 
351
360
  def get_spec_file(spec_uri: URIRef, spec_graph: Graph):
352
- return str(spec_graph.value(subject=spec_uri, predicate=MUST.specFileName, default="default.mustrd.ttl"))
361
+ file_name = spec_graph.value(subject=spec_uri, predicate=MUST.specFileName)
362
+ if file_name:
363
+ return str(file_name)
364
+ # fallback: try to get from MUST.specSourceFile
365
+ file_path = spec_graph.value(subject=spec_uri, predicate=MUST.specSourceFile)
366
+ if file_path:
367
+ return str(Path(file_path).name)
368
+ return "default.mustrd.ttl"
353
369
 
354
370
 
355
371
  def get_spec(spec_uri: URIRef, spec_graph: Graph, run_config: dict, mustrd_triple_store: dict = None) -> Specification:
@@ -382,10 +398,11 @@ def get_spec(spec_uri: URIRef, spec_graph: Graph, run_config: dict, mustrd_tripl
382
398
 
383
399
 
384
400
  def check_result(spec: Specification, result: Union[str, Graph]):
401
+
385
402
  log.debug(
386
403
  f"check_result {spec.spec_uri=}, {spec.triple_store=}, {result=} {type(spec.then)}")
387
404
  if isinstance(spec.then, TableThenSpec):
388
- log.debug(f"table_comparison")
405
+ log.debug("table_comparison")
389
406
  return table_comparison(result, spec)
390
407
  else:
391
408
  graph_compare = graph_comparison(spec.then.value, result)
@@ -397,20 +414,26 @@ def check_result(spec: Specification, result: Union[str, Graph]):
397
414
 
398
415
  return ret
399
416
  else:
400
- log.debug(f"not isomorphic")
417
+ log.debug("not isomorphic")
401
418
  if spec.when[0].queryType == MUST.ConstructSparql:
402
- log.debug(f"ConstructSpecFailure")
403
-
419
+ log.debug("ConstructSpecFailure")
404
420
  return ConstructSpecFailure(spec.spec_uri, spec.triple_store["type"], graph_compare)
405
421
  else:
406
- log.debug(f"UpdateSpecFailure")
422
+ log.debug("UpdateSpecFailure")
407
423
  return UpdateSpecFailure(spec.spec_uri, spec.triple_store["type"], graph_compare)
408
424
 
409
425
 
410
426
  def run_spec(spec: Specification) -> SpecResult:
411
427
  spec_uri = spec.spec_uri
412
428
  triple_store = spec.triple_store
413
- # close_connection = True
429
+
430
+ if not isinstance(spec, Specification):
431
+ log.warning(f"check_result called with non-Specification: {type(spec)}")
432
+ return spec
433
+ # return SpecSkipped(getattr(spec, 'spec_uri', None), getattr(spec, 'triple_store', {}), "Spec is not a valid Specification instance")
434
+
435
+ log.debug(
436
+ f"run_spec {spec=}")
414
437
  log.debug(
415
438
  f"run_when {spec_uri=}, {triple_store=}, {spec.given=}, {spec.when=}, {spec.then=}")
416
439
  if spec.given:
@@ -434,7 +457,8 @@ def run_spec(spec: Specification) -> SpecResult:
434
457
  return SparqlParseFailure(spec_uri, triple_store["type"], e)
435
458
  except NotImplementedError as ex:
436
459
  log.error(f"NotImplementedError {ex}")
437
- return SpecSkipped(spec_uri, triple_store["type"], ex.args[0])
460
+ raise ex
461
+ # return SpecSkipped(spec_uri, triple_store["type"], ex.args[0])
438
462
  return check_result(spec, result)
439
463
  except (ConnectionError, TimeoutError, HTTPError, ConnectTimeout, OSError) as e:
440
464
  # close_connection = False
@@ -446,12 +470,8 @@ def run_spec(spec: Specification) -> SpecResult:
446
470
  log.error(f"{type(e)} {e}")
447
471
  return SparqlExecutionError(spec_uri, triple_store["type"], e)
448
472
  except Exception as e:
449
- if e:
450
- log.error(f"Unknown error {e}\n{traceback.format_exc()}")
451
- raise
452
- else:
453
- log.error(f"Unknown error")
454
- return RuntimeError(spec_uri, triple_store["type"], e)
473
+ log.error(f"Unexpected error {e}")
474
+ return RuntimeError(spec_uri, triple_store["type"], f"{type(e).__name__}: {e}")
455
475
  # https://github.com/Semantic-partners/mustrd/issues/78
456
476
  # finally:
457
477
  # if type(mustrd_triple_store) == MustrdAnzo and close_connection:
mustrd/mustrdAnzo.py CHANGED
@@ -29,6 +29,7 @@ from mustrd.anzo_utils import query_azg, query_graphmart
29
29
  from mustrd.anzo_utils import query_configuration, json_to_dictlist, ttl_to_graph
30
30
 
31
31
 
32
+
32
33
  def execute_select(triple_store: dict, when: str, bindings: dict = None) -> str:
33
34
  try:
34
35
  if bindings:
@@ -39,7 +40,7 @@ def execute_select(triple_store: dict, when: str, bindings: dict = None) -> str
39
40
  f"FROM <{triple_store['input_graph']}>\nFROM <{triple_store['output_graph']}>").replace(
40
41
  "${targetGraph}", f"<{triple_store['output_graph']}>")
41
42
  # TODO: manage results here
42
- return query_azg(anzo_config=triple_store, query=when)
43
+ return query_azg(anzo_config=triple_store, query=when, data_layers=[triple_store['input_graph']])
43
44
  except (ConnectionError, TimeoutError, HTTPError, ConnectTimeout):
44
45
  raise
45
46
 
@@ -1,27 +1,3 @@
1
- """
2
- MIT License
3
-
4
- Copyright (c) 2023 Semantic Partners Ltd
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in all
14
- copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
- SOFTWARE.
23
- """
24
-
25
1
  import logging
26
2
  from dataclasses import dataclass
27
3
  import pytest
@@ -93,6 +69,14 @@ def pytest_addoption(parser):
93
69
  default=None,
94
70
  help="Give the secrets by command line in order to be able to store secrets safely in CI tools",
95
71
  )
72
+ group.addoption(
73
+ "--pytest-path",
74
+ action="store",
75
+ dest="pytest_path",
76
+ metavar="PytestPath",
77
+ default=None,
78
+ help="Filter tests based on the pytest_path property in .mustrd.ttl files.",
79
+ )
96
80
  return
97
81
 
98
82
 
@@ -217,27 +201,39 @@ class MustrdTestPlugin:
217
201
  @pytest.hookimpl(tryfirst=True)
218
202
  def pytest_collection(self, session):
219
203
  logger.info("Starting test collection")
204
+
220
205
  self.unit_tests = []
221
206
  args = session.config.args
222
- logger.info("Used arguments: " + str(args))
207
+
208
+ # Split args into mustrd and regular pytest args
209
+ mustrd_args = [arg for arg in args if ".mustrd.ttl" in arg]
210
+ pytest_args = [arg for arg in args if arg != os.getcwd() and ".mustrd.ttl" not in arg]
211
+
223
212
  self.selected_tests = list(
224
213
  map(
225
214
  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),
215
+ mustrd_args
229
216
  )
230
217
  )
231
218
  logger.info(f"selected_tests is: {self.selected_tests}")
232
219
 
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
- )
220
+ self.path_filter = session.config.getoption("pytest_path") or None
221
+
238
222
  logger.info(f"path_filter is: {self.path_filter}")
223
+ logger.info(f"Args: {args}")
224
+ logger.info(f"Mustrd Args: {mustrd_args}")
225
+ logger.info(f"Pytest Args: {pytest_args}")
226
+ logger.info(f"Path Filter: {self.path_filter}")
227
+
228
+ # Only modify args if we have mustrd tests to run
229
+ if self.selected_tests:
230
+ # Keep original pytest args and add config file for mustrd
231
+ session.config.args = pytest_args + [str(self.test_config_file.resolve())]
232
+ else:
233
+ # Keep original args unchanged for regular pytest
234
+ session.config.args = args
239
235
 
240
- session.config.args = [str(self.test_config_file.resolve())]
236
+ logger.info(f"Final session.config.args: {session.config.args}")
241
237
 
242
238
  def get_file_name_from_arg(self, arg):
243
239
  if arg and len(arg) > 0 and "[" in arg and ".mustrd.ttl " in arg:
@@ -247,6 +243,13 @@ class MustrdTestPlugin:
247
243
  @pytest.hookimpl
248
244
  def pytest_collect_file(self, parent, path):
249
245
  logger.debug(f"Collecting file: {path}")
246
+ # Only collect .ttl files that are mustrd suite config files
247
+ if not str(path).endswith('.ttl'):
248
+ return None
249
+ if Path(path).resolve() != Path(self.test_config_file).resolve():
250
+ logger.debug(f"{self.test_config_file}: Skipping non-matching-config file: {path}")
251
+ return None
252
+
250
253
  mustrd_file = MustrdFile.from_parent(parent, path=pathlib.Path(path), mustrd_plugin=self)
251
254
  mustrd_file.mustrd_plugin = self
252
255
  return mustrd_file
@@ -269,13 +272,24 @@ class MustrdTestPlugin:
269
272
  file_name or "*",
270
273
  selected_test_files=self.selected_tests,
271
274
  )
275
+ # Convert invalid specs to SpecInvalid instead of SpecSkipped
276
+ invalid_specs = [
277
+ SpecInvalid(
278
+ spec.spec_uri,
279
+ spec.triple_store,
280
+ spec.message,
281
+ spec.spec_file_name,
282
+ spec.spec_source_file
283
+ ) for spec in invalid_spec_results
284
+ ]
285
+
272
286
 
273
287
  specs, skipped_spec_results = get_specs(
274
288
  valid_spec_uris, spec_graph, triple_stores, config
275
289
  )
276
290
 
277
291
  # Return normal specs + skipped results
278
- return specs + skipped_spec_results + invalid_spec_results
292
+ return specs + skipped_spec_results + invalid_specs
279
293
 
280
294
  # Function called to generate the name of the test
281
295
  def get_test_name(self, spec):
@@ -383,39 +397,47 @@ class MustrdTestPlugin:
383
397
  with open(self.md_path, "w") as file:
384
398
  file.write(md)
385
399
 
400
+ @dataclass(frozen=True)
401
+ class SpecInvalid:
402
+ spec_uri: str
403
+ triple_store: str
404
+ message: str
405
+ spec_file_name: str = None
406
+ spec_source_file: Path = None
386
407
 
387
408
  class MustrdFile(pytest.File):
388
409
  mustrd_plugin: MustrdTestPlugin
389
410
 
390
411
  def __init__(self, *args, mustrd_plugin, **kwargs):
412
+ logger.debug(f"Creating MustrdFile with args: {args}, kwargs: {kwargs}")
391
413
  self.mustrd_plugin = mustrd_plugin
392
414
  super(pytest.File, self).__init__(*args, **kwargs)
393
415
 
394
416
  def collect(self):
395
417
  try:
396
- logger.debug(f"Collecting tests from file: {self.fspath}")
397
- test_configs = parse_config(self.fspath)
418
+ logger.info(f"{self.mustrd_plugin.test_config_file}: Collecting tests from file: {self.path=}")
419
+ # Only process the specific mustrd config file we were given
420
+
421
+ # if not str(self.fspath).endswith(".ttl"):
422
+ # return []
423
+ # Only process the specific mustrd config file we were given
424
+ # if str(self.fspath) != str(self.mustrd_plugin.test_config_file):
425
+ # logger.info(f"Skipping non-config file: {self.fspath}")
426
+ # return []
427
+
428
+ test_configs = parse_config(self.path)
429
+ from collections import defaultdict
430
+ pytest_path_grouped = defaultdict(list)
398
431
  for test_config in test_configs:
399
- # Skip if there is a path filter and it is not in the pytest path
400
432
  if (
401
433
  self.mustrd_plugin.path_filter is not None
402
- and self.mustrd_plugin.path_filter not in test_config.pytest_path
434
+ and not str(test_config.pytest_path).startswith(str(self.mustrd_plugin.path_filter))
403
435
  ):
436
+ logger.info(f"Skipping test config due to path filter: {test_config.pytest_path=} {self.mustrd_plugin.path_filter=}")
404
437
  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:
438
+
439
+ triple_stores = self.mustrd_plugin.get_triple_stores_from_file(test_config)
440
+ try:
419
441
  specs = self.mustrd_plugin.generate_tests_for_config(
420
442
  {
421
443
  "spec_path": test_config.spec_path,
@@ -424,27 +446,63 @@ class MustrdFile(pytest.File):
424
446
  triple_stores,
425
447
  None,
426
448
  )
449
+ except Exception as e:
450
+ logger.error(f"Error generating tests: {e}\n{traceback.format_exc()}")
451
+ specs = [
452
+ SpecInvalid(
453
+ MUST.TestSpec,
454
+ triple_store["uri"] if isinstance(triple_store, dict) else triple_store,
455
+ f"Test generation failed: {str(e)}",
456
+ spec_file_name=str(test_config.spec_path.name) if test_config.spec_path else "unknown.mustrd.ttl",
457
+ spec_source_file=self.path if test_config.spec_path else Path("unknown.mustrd.ttl"),
458
+ )
459
+ for triple_store in (triple_stores or test_config.filter_on_tripleStore)
460
+ ]
461
+ pytest_path = getattr(test_config, "pytest_path", "unknown")
427
462
  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
463
+ pytest_path_grouped[pytest_path].append(spec)
464
+
465
+ for pytest_path, specs_for_path in pytest_path_grouped.items():
466
+ logger.info(f"pytest_path group: {pytest_path} ({len(specs_for_path)} specs)")
467
+
468
+ yield MustrdPytestPathCollector.from_parent(
469
+ self,
470
+ name=str(pytest_path),
471
+ pytest_path=pytest_path,
472
+ specs=specs_for_path,
473
+ mustrd_plugin=self.mustrd_plugin,
474
+ )
435
475
  except Exception as e:
436
- # Catch error here otherwise it will be lost
437
476
  self.mustrd_plugin.collect_error = e
438
- logger.error(f"Error during collection: {e}")
477
+ logger.error(f"Error during collection {self.path}: {type(e)} {e} {traceback.format_exc()}")
439
478
  raise e
440
479
 
441
480
 
481
+ class MustrdPytestPathCollector(pytest.Class):
482
+ def __init__(self, name, parent, pytest_path, specs, mustrd_plugin):
483
+ super().__init__(name, parent)
484
+ self.pytest_path = pytest_path
485
+ self.specs = specs
486
+ self.mustrd_plugin = mustrd_plugin
487
+
488
+ def collect(self):
489
+ for spec in self.specs:
490
+ item = MustrdItem.from_parent(
491
+ self,
492
+ name=spec.spec_file_name,
493
+ spec=spec,
494
+ )
495
+ self.mustrd_plugin.items.append(item)
496
+ yield item
497
+
498
+
442
499
  class MustrdItem(pytest.Item):
443
500
  def __init__(self, name, parent, spec):
444
- logging.info(f"Creating item: {name}")
501
+ logging.debug(f"Creating item: {name}")
445
502
  super().__init__(name, parent)
446
503
  self.spec = spec
447
504
  self.fspath = spec.spec_source_file
505
+ self.originalname = name
448
506
 
449
507
  def runtest(self):
450
508
  result = run_test_spec(self.spec)
@@ -460,8 +518,7 @@ class MustrdItem(pytest.Item):
460
518
  f"{self.name} failed:\n"
461
519
  f"Spec: {self.spec.spec_uri}\n"
462
520
  f"File: {self.spec.spec_source_file}\n"
463
- f"Dir: {dir(self.spec)}\n"
464
- f"Error: {excinfo.value}\n"
521
+ f"Error: \n{excinfo.value}\n"
465
522
  f"Traceback:\n{tb_str}"
466
523
  )
467
524
 
@@ -476,6 +533,8 @@ def run_test_spec(test_spec):
476
533
  pytest.skip(f"Invalid configuration, error : {test_spec.message}")
477
534
  result = run_spec(test_spec)
478
535
  result_type = type(result)
536
+ if isinstance(test_spec, SpecInvalid):
537
+ raise ValueError(f"Invalid test specification: {test_spec.message} {test_spec}")
479
538
  if result_type == SpecSkipped:
480
539
  # FIXME: Better exception management
481
540
  pytest.skip("Unsupported configuration")
mustrd/spec_component.py CHANGED
@@ -35,8 +35,8 @@ from rdflib.term import Node
35
35
  from rdflib.plugins.stores.memory import Memory
36
36
 
37
37
  from . import logger_setup
38
- from .mustrdAnzo import get_queries_for_layer, get_queries_from_templated_step, get_spec_component_from_graphmart
39
- from .mustrdAnzo import get_query_from_querybuilder, get_query_from_step
38
+ from .mustrdAnzo import get_queries_for_layer, get_queries_from_templated_step
39
+ from .mustrdAnzo import get_query_from_querybuilder
40
40
  from .namespace import MUST, TRIPLESTORE
41
41
  from multimethods import MultiMethod, Default
42
42
  from .utils import get_mustrd_root
@@ -119,8 +119,9 @@ def parse_spec_component(subject: URIRef,
119
119
  data_source_type=data_source_type,
120
120
  run_config=run_config,
121
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?
122
+
123
+ # get_spec_component potentially talks to anzo for EVERY spec, massively slowing things down
124
+ # can we defer it to run time?
124
125
  spec_component = get_spec_component(spec_component_details)
125
126
  if isinstance(spec_component, list):
126
127
  spec_components += spec_component
@@ -433,15 +434,7 @@ def _get_spec_component_AnzoGraphmartDataset(spec_component_details: SpecCompone
433
434
 
434
435
  if spec_component_details.mustrd_triple_store["type"] == TRIPLESTORE.Anzo:
435
436
  # Get GIVEN or THEN from anzo graphmart
436
- graphmart = spec_component_details.spec_graph.value(subject=spec_component_details.spec_component_node,
437
- predicate=MUST.graphmart)
438
- layer = spec_component_details.spec_graph.value(subject=spec_component_details.spec_component_node,
439
- predicate=MUST.layer)
440
437
  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)
445
438
  else:
446
439
  raise ValueError(f"You must define {TRIPLESTORE.Anzo} to use {MUST.AnzoGraphmartDataset}")
447
440
 
@@ -555,7 +548,6 @@ def _get_spec_component_default(spec_component_details: SpecComponentDetails) ->
555
548
 
556
549
 
557
550
  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}")
559
551
  if predicate == MUST.given:
560
552
  spec_component = GivenSpec()
561
553
  elif predicate == MUST.when:
mustrd/steprunner.py CHANGED
@@ -24,7 +24,6 @@ SOFTWARE.
24
24
 
25
25
  import json
26
26
 
27
- from . import logger_setup
28
27
  from multimethods import MultiMethod, Default
29
28
  from .namespace import MUST, TRIPLESTORE
30
29
  from rdflib import Graph, URIRef
@@ -105,8 +104,7 @@ def _anzo_run_when_select(spec_uri: URIRef, triple_store: dict, when: AnzoWhenSp
105
104
 
106
105
  @run_when.method((TRIPLESTORE.GraphDb, MUST.UpdateSparql))
107
106
  def _graphdb_run_when_update(spec_uri: URIRef, triple_store: dict, when: WhenSpec):
108
-
109
- return execute_update_graphdb(triple_store, query, when.bindings)
107
+ return execute_update_graphdb(triple_store, when.value, when.bindings)
110
108
 
111
109
 
112
110
  @run_when.method((TRIPLESTORE.GraphDb, MUST.ConstructSparql))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mustrd
3
- Version: 0.2.6.3
3
+ Version: 0.3.0.0
4
4
  Summary: A Spec By Example framework for RDF and SPARQL, Inspired by Cucumber.
5
5
  License: MIT
6
6
  Author: John Placek
@@ -26,7 +26,7 @@ Requires-Dist: flake8 (==7.0.0)
26
26
  Requires-Dist: multimethods-py (>=0.5.3,<0.6.0)
27
27
  Requires-Dist: numpy (>=1.26.0,<1.27.0)
28
28
  Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
29
- Requires-Dist: pandas (>=1.5.2,<2.0.0)
29
+ Requires-Dist: pandas (>=2.0,<3.0)
30
30
  Requires-Dist: pyshacl (>=0.30.0,<0.31.0)
31
31
  Requires-Dist: pytest (>=7.2.0,<8.0.0)
32
32
  Requires-Dist: rdflib (>=7.1.3,<8.0.0)
@@ -1,32 +1,32 @@
1
1
  mustrd/README.adoc,sha256=E5KuShPEl2U6NmRzEAwZtAhBoyJsOvjGS1CM2UsbSQ4,1394
2
2
  mustrd/README.md,sha256=CR08uZ4eNELHBdDRXAVKkRZ4hgQB9OXA7tFRy4ER-LI,1364
3
3
  mustrd/TestResult.py,sha256=K4yth-rYrK6Pl7SFiTAZkUStBIzHlgq0oxSSpq5F34M,4849
4
- mustrd/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
5
- mustrd/anzo_utils.py,sha256=-i9fE-HArbni4MaKy1rH47U328ERHwkLi2X4TP6nRk4,4675
6
- mustrd/logger_setup.py,sha256=6Z3E5_h8vZFn4PZUyJVFdkgwFjDWthWEQVJsI9wQVVU,1720
4
+ mustrd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ mustrd/anzo_utils.py,sha256=CKNSF_oTFKc4v64EDXJzeirP1GxOIOCUKNfaJKk0oEc,4677
6
+ mustrd/logger_setup.py,sha256=AdHf1_rEYiWleR-8IVatsMu-ntYH3_uiDDhFchQ8BcM,1721
7
7
  mustrd/model/catalog-v001.xml,sha256=IEtaw3FK4KGQWKancEe1HqzUQTrKdk89vNxnoLKGF4o,381
8
- mustrd/model/mustrdShapes.ttl,sha256=6-W8onQBWOwAvsIYLRGOk2FePSp4SPFfWd7dSuNC5ho,9456
8
+ mustrd/model/mustrdShapes.ttl,sha256=3BjiOMLs0sS5Ky4_1YkzqYE7JpW-bsfw7FaFej6Ri8w,10056
9
9
  mustrd/model/mustrdTestOntology.ttl,sha256=W7IRbPKrhpYFweZvc9QH8gdjBiuZMHKETIuHBepLnYw,2034
10
10
  mustrd/model/mustrdTestShapes.ttl,sha256=5PUpU9AzPSeLpF_UzNBVnACLOhs3hfoQpiz-ybsrbj8,818
11
- mustrd/model/ontology.ttl,sha256=AK27qyT8GW_SwJDwTFvtfxndBPEfYT6Y1jiW26Hyjg0,16809
11
+ mustrd/model/ontology.ttl,sha256=089FOWtSN107xR04MFxtvPUJVFiT9TSzmKqqNOfm7Gk,17090
12
12
  mustrd/model/test-resources/resources.ttl,sha256=1Dsp1nuNxauj9bxeX-HShQsiO-CVy5Irwm2y2x0cdjI,1498
13
13
  mustrd/model/triplestoreOntology.ttl,sha256=9K5gj0hDOolRYjHc58UT4igex8cUnq9h7SUe4ToYbdw,5834
14
14
  mustrd/model/triplestoreshapes.ttl,sha256=G1kdgASdPa8s5JVGXL4KM2ewp-F5Vmbdist0f77VTBc,1706
15
- mustrd/mustrd.py,sha256=De-d9jPcvUa8OuaXrKs1BptwfuwtIkQfqfXzLowy3gM,38986
16
- mustrd/mustrdAnzo.py,sha256=xdwfdBz_bMv5IQHVCcoK9tXTZ7ZMwgFTIDCpJKizynQ,8308
15
+ mustrd/mustrd.py,sha256=-J_Od8Uv0WFWKIt6C2QBl_ZCQtubx3nBUjfTodJ3a4w,40289
16
+ mustrd/mustrdAnzo.py,sha256=0XhLkfagW_HManfZ3iGAf_K2_d-pLVTAOT-0pX8hhM4,8352
17
17
  mustrd/mustrdGraphDb.py,sha256=Ro_fxDPFl64r-FAM18awhZydydEY1-IXO0zdKpvZD3U,5405
18
18
  mustrd/mustrdRdfLib.py,sha256=CvrzEl1-lEPugYVe3y_Ip8JMzUxv6IeWauLOa_WA-XI,2073
19
- mustrd/mustrdTestPlugin.py,sha256=jcCi4EtJIZOWKhKxJELlsJn8VssnG5oo34RJZeqSlGY,17117
19
+ mustrd/mustrdTestPlugin.py,sha256=hbYo8i1j4uFuRekXGd4Mnjt9wkSgQrS5o809xtbcLgs,19664
20
20
  mustrd/namespace.py,sha256=xGfH-nRP3t_I4rmoGJPqlSGbI0G5HUMlUeAl7l_yW-s,3622
21
21
  mustrd/run.py,sha256=5xZUgKPMBQ-03cWROAnwtbOs2Nb0Vat6n8Fi6EyfS-k,4257
22
- mustrd/spec_component.py,sha256=EdSwO_eYDy5lLdOV0nyA4EzkA2V-OrTgDkoXcZ2yxXw,32076
23
- mustrd/steprunner.py,sha256=-KGE_bYSBJDVQUQ2ELSY92D-V8HxbBdZMqzfgAiOpc0,7978
22
+ mustrd/spec_component.py,sha256=5WQdvj0v9U-HEiOomoLcwwKfAt6kLDxPKomxyMkleI0,31382
23
+ mustrd/steprunner.py,sha256=73ykrrfZAPAQcr95ewcRfLO0gl_2xVGlEDYnI7FncXg,7951
24
24
  mustrd/templates/md_ResultList_leaf_template.jinja,sha256=IzwZjliCx7-viipATDQK6MQg_5q1kLMKdeNSZg1sXXY,508
25
25
  mustrd/templates/md_ResultList_template.jinja,sha256=_8joJ7vtw_qoqxv3HhUtBgRfhOeqmgfaRFwEo4MROvQ,203
26
26
  mustrd/templates/md_stats_template.jinja,sha256=96W62cMWu9UGLNv65ZQ8RYLjkxKHhJy-FlUtXgud6XY,155
27
27
  mustrd/utils.py,sha256=OGdLvw7GvjrFgTJo0J97Xwdh-_ZgSmapmOistrEchO0,1387
28
- mustrd-0.2.6.3.dist-info/LICENSE,sha256=r8nmh5fUct9h2w8_RDl13EIscvmwCLoarPr1kg35MnA,1078
29
- mustrd-0.2.6.3.dist-info/METADATA,sha256=Vjl1v-WM8_u0YRhXtGZ4BkcSK7wCmPNIsqUtyV1-Vl0,4208
30
- mustrd-0.2.6.3.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
31
- mustrd-0.2.6.3.dist-info/entry_points.txt,sha256=v7V7sN0_L1aB4Ug_9io5axlQSeJ1C0tNrQWwdXdV58s,50
32
- mustrd-0.2.6.3.dist-info/RECORD,,
28
+ mustrd-0.3.0.0.dist-info/LICENSE,sha256=r8nmh5fUct9h2w8_RDl13EIscvmwCLoarPr1kg35MnA,1078
29
+ mustrd-0.3.0.0.dist-info/METADATA,sha256=Eu_S5x8JM7ZP8LWF6nh9qkhYpjhLCApa2__EGBlNtXk,4204
30
+ mustrd-0.3.0.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
31
+ mustrd-0.3.0.0.dist-info/entry_points.txt,sha256=v7V7sN0_L1aB4Ug_9io5axlQSeJ1C0tNrQWwdXdV58s,50
32
+ mustrd-0.3.0.0.dist-info/RECORD,,